Bit Banging SPI  - Page 1
Forum section: electronics / general

author: yashrk
author_rank: Frequent Contributor
timestamp: June 20, 2016, 06:28:15 am
content: Hey guys,I am using MCP3551 ADC which has SPI communication protocol, interfacing with PIC18F4620. I cannot use the hardware peripheral as hardware is already developed. I am using MCP3551 in continues read mode and we have just permanently grounded select pin. Its gives out 24bit data which is then saved character string in the code. I have written the code but when I run it in PROTEUS it didn't work. LCD code is tested so no problem there for sure. I am using XC8 compiler and MPLAB IDE.I used the oscilloscope in PROTEUS where I found that ADC is showing data ready but not giving any data back. I have read through the datasheet it just says that first I have to read ready signal then by giving clock signal it will give me back 24bit value and at 25th bit it will gain the access to the register and save new ADC value to be read.Please check and see what I am doing wrong.Thank you,Yash.Code:#include <xc.h>#include <stdlib.h>// PIC18F4620 Configuration Bit Settings// 'C' source line config statements#pragma config CONFIG1H = 0x06#pragma config CONFIG2L = 0x1a#pragma config CONFIG2H = 0x0e#pragma config CONFIG3H = 0x81#pragma config CONFIG4L = 0x80#pragma config CONFIG5L = 0x00#pragma config CONFIG5H = 0x00#pragma config CONFIG6L = 0x0f#pragma config CONFIG6H = 0xe0#pragma config CONFIG7L = 0x0f#pragma config CONFIG7H = 0x40#define rs PORTDbits.RD6 //LATBbits.LB6#define en PORTDbits.RD7 //LATBbits.LB7#define _XTAL_FREQ 40000000void delay(void);void lcddata(unsigned char value);void lcdcmd(unsigned char value);void lcd_init();void Lcd_Set_Cursor(char a, char b);void lcd_data_string(char *a, unsigned int b);void Lcd_Shift_Right();void Lcd_Shift_Left();void lcd_num(unsigned int a, unsigned int b);int num = 1000;char disp[] = "Error";char disp1[] = "Hello";/////////////////////////////////////////////////////////////////////////////////////////////#define SDI_DIR TRISCbits.TRISC0#define SDI PORTCbits.RC1#define SCLK_DIR TRISCbits.RC0#define SCLK LATCbits.LC0 //PORTCbits.RC0#define nop 3void sbit_in(unsigned char *data); // inputs a bit from the SPI busvoid ini_spi(void);void read_temp(void);void clock(void);char adc_temp[]="111";void main(){TRISB =0x00; // lcd 0-7TRISD =0x00; // D6, D7ADCON0 = 0x00; // all pins digitaldelay();lcd_init();delay();lcdcmd(0x01);delay();lcdcmd(0x01);Lcd_Set_Cursor(1,1);lcd_data_string(disp1,5);ini_spi(); //initialize spifor(int i=0; i<500; i++) __delay_ms(10);read_temp();lcdcmd(0x01);delay();Lcd_Set_Cursor(1,1);lcd_data_string(adc_temp,3);delay();lcddata('H');while(1){;}}void lcd_init(){en = 0;for(int i =0; i<25; i++)__delay_ms(10);lcdcmd(0x38);for(int i =0; i<25; i++)__delay_ms(10);lcdcmd(0x0C); //display on cursor offdelay();lcdcmd(0x01); //clear LCDdelay();lcdcmd(0x06);delay();lcdcmd(0x02); //shift cursor rightdelay();}void Lcd_Set_Cursor(char a, char b){ //row, columchar temp;if(a == 1){temp = 0x80 + b - 1;lcdcmd(temp);}else if(a == 2){temp = 0xC0 + b - 1;lcdcmd(temp);}delay();}void lcdcmd(unsigned char value){PORTB = value;rs =0;en =1;__delay_us(1);en =0;}void lcddata(unsigned char value){PORTB = value;rs =1;en =1;__delay_us(1);en =0;//rs =0;}void delay(void) {__delay_ms(15);}void lcd_data_string(char *a, unsigned int b){ //(array, length)int i;for(i=0;i<b;i++){lcddata(a);__delay_ms(2);}}void Lcd_Shift_Right(){lcdcmd(0x01);delay();lcdcmd(0x0C);}void Lcd_Shift_Left(){lcdcmd(0x01);delay();lcdcmd(0x08);}void lcd_num(unsigned int a, unsigned int b){ //integer to be printedchar buf;itoa(buf, a, 10);lcd_data_string(buf,b);}///////////////////////////////////////////////////////////char spi_readC(){unsigned char i; // loop counterunsigned char ret=0; // return valuefor (i = 0; i < 8; i++){ // loop through each bitret = ret << 1; // shift left for next bitSCLK =1; // clock highret |= SDI; // input the received bitSCLK =0; // clock low}return ret;}void ini_spi(void){SDI_DIR =1; // Direction of data in pin -inputSCLK_DIR =0; // Direction of clock pin -output}void clock(void){ // Giving HIGH to LOW pulseSCLK =1;NOP();NOP();SCLK =0;}void read_temp(){if(!SDI){ // if data is readyadc_temp =spi_readC(); // MSBadc_temp =spi_readC();adc_temp =spi_readC(); // LSBclock(); // 25th clock after 24 bit of data}else{lcdcmd(0x01);Lcd_Set_Cursor(1,1);lcd_data_string(disp,5);}}

author: Ian.M
author_rank: Super Contributor
timestamp: June 20, 2016, 07:27:00 am
content: Comes from:http://www.microchip.com/forums/m935215.aspxWhat makes you think Proteus's simulation of the ADC is accurate? I wouldn't be surprised to find it doesn't support simulation with /CS hard grounded.I wouldn't entirely trust Proteus's PIC simulation either, as it has a certain reputation for running code that appears to work OK but doesn't work properly on real hardware.I've looked at the MCP3551 datasheet in some detail, and it looks like the *ONLY* way you can guarantee bit alignment in the data transfer with /CS grounded is if your MCU controls power to the ADC. Otherwise any glitch on the SCK line will result in an off by one error, and there is no pattern in the data that can be used to resynchronise. If you don't have a pull-up/down resistor on the SCK pin to bias it towards its idle state there is a high probability that the floating pin during startup will glitch SCK.Connect a DSO with protocol analyser and waveform export to the real hardware and find out what's actually happening, or at the very least show us the Proteus waveforms and the output of its SPI analyser, annotated in a graphics package to show us what you think is a problem.

author: dannyf
author_rank: Super Contributor
timestamp: June 20, 2016, 10:17:44 am
content: "ave just permanently grounded select pin."Many times the downward edge of the cs pin starts the adc. Read the datasheet, always." it didn't work."What does that mean?

author: wraper
author_rank: Unknown
timestamp: June 20, 2016, 10:50:50 am
content: Don't trust simulation in Proteus. In the past when I tried simulate some AVR, analog stuff was broken. Also there was some issue even with CPU simulation, some math worked wrong.

author: Ian.M
author_rank: Super Contributor
timestamp: June 20, 2016, 11:17:12 am
content: The MCP3551 datasheetDS21950Balleges:QuoteKnowing Microchip's tendencies for misleading documentation, I would take that with a large grain of salt:Odds are one Microchip intern got lucky and ran the ADC like that on the bench a few times, for a few thousand samples. If anyone's cellphone is within a metre or so of your board and pings the basestation, the odds of loss of sync are fairly high. If Microchip were serious about two wire operation, they'd have included some means of resetting its SPI state engine, maybe by implementing a timeout for SCK transitions.

author: yashrk
author_rank: Frequent Contributor
timestamp: June 20, 2016, 11:30:47 am
content: Cool pic!!I will try the program on hardware tomorrow and will notify you all. The thing is that the hardware is kind of a legacy product in which this part was designed but not implemented previously so if there is a need to change board layout then that will make few people unhappy.

author: dannyf
author_rank: Super Contributor
timestamp: June 20, 2016, 10:13:19 pm
content: "LCD code is tested so no problem there for sure. "Biggest mistake people cannot make in debugging is to assume.Bugs are rarely where you think they are. As a matter of fact, I typically start my debugging with code I think is the most unlikely place for bus. And I typically find them there.In your case, I would start by giving the display routines some known good values and see if it works as expected. And go from there.

author: dannyf
author_rank: Super Contributor
timestamp: June 21, 2016, 01:16:33 am
content: mcp3551, continuous mode, adc input is 1v.enjoy.

author: Ian.M
author_rank: Super Contributor
timestamp: June 21, 2016, 01:49:17 am
content: That's helpful. At least we now know Proteus supports continuous mode with /CS hard grounded for this ADC. Whether or not it can be got working reliably in real life is another matter . . . .

author: yashrk
author_rank: Frequent Contributor
timestamp: June 21, 2016, 03:38:42 am
content: @danny did you used that same code ?

author: yashrk
author_rank: Frequent Contributor
timestamp: June 22, 2016, 03:58:07 am
content: @dannyf Please reply !!