Author Topic: Bit Banging SPI  (Read 4833 times)

0 Members and 1 Guest are viewing this topic.

Offline yashrkTopic starter

  • Frequent Contributor
  • **
  • Posts: 277
  • Country: in
  • A MAKER, AN ENGINEER, A HOBBYIST FOR LIFE
    • My Personal Blog
Bit Banging SPI
« on: June 20, 2016, 06:28:15 am »
Hey guys  :popcorn: ,
              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: [Select]

#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 40000000

void 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 3


void sbit_in(unsigned char *data);               // inputs a bit from the SPI bus
void ini_spi(void);
void read_temp(void);
void clock(void);

char adc_temp[]="111";

void main(){
    TRISB =0x00;                            // lcd 0-7
    TRISD =0x00;                            // D6, D7
    ADCON0 = 0x00;                          // all pins digital
    delay();
    lcd_init();
    delay();
    lcdcmd(0x01);
    delay();
    lcdcmd(0x01);
    Lcd_Set_Cursor(1,1);
    lcd_data_string(disp1,5);
   
    ini_spi();                             //initialize spi
   
    for(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 off
    delay();
    lcdcmd(0x01);                //clear LCD
    delay();
    lcdcmd(0x06);               
    delay();
    lcdcmd(0x02);                //shift cursor right
    delay();
   
}

void Lcd_Set_Cursor(char a, char b){  //row, colum
char 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[i]);
        __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 printed
    char buf[10];
    itoa(buf, a, 10);
    lcd_data_string(buf,b);
}

///////////////////////////////////////////////////////////

char spi_readC(){
    unsigned char i;                    // loop counter
    unsigned char ret=0;                // return value

    for (i = 0; i < 8; i++){        // loop through each bit
        ret = ret << 1;             // shift left for next bit
        SCLK =1;                    // clock high
        ret |= SDI;                 // input the received bit
        SCLK =0;                    // clock low
    }
    return ret;   
}

void ini_spi(void){
    SDI_DIR =1;                         // Direction of data in pin  -input
    SCLK_DIR =0;                        // Direction of clock pin    -output
}

void clock(void){ // Giving HIGH to LOW pulse
    SCLK =1;
    NOP();
    NOP();
    SCLK =0;
}

void read_temp(){
    if(!SDI){                       // if data is ready
    adc_temp[0] =spi_readC();           // MSB
    adc_temp[1] =spi_readC();
    adc_temp[2] =spi_readC();           // LSB
    clock();                            // 25th clock after 24 bit of data
    }
    else{
        lcdcmd(0x01);
        Lcd_Set_Cursor(1,1);
        lcd_data_string(disp,5);
    }
}
Find me and things I'm working on - https://www.yashkudale.com/
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 13066
Re: Bit Banging SPI
« Reply #1 on: June 20, 2016, 07:27:00 am »
Comes from: http://www.microchip.com/forums/m935215.aspx
What 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.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Bit Banging SPI
« Reply #2 on: June 20, 2016, 10:17:44 am »
"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?
================================
https://dannyelectronics.wordpress.com/
 

Offline wraper

  • Supporter
  • ****
  • Posts: 17581
  • Country: lv
Re: Bit Banging SPI
« Reply #3 on: June 20, 2016, 10:50:50 am »
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.
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 13066
Re: Bit Banging SPI
« Reply #4 on: June 20, 2016, 11:17:12 am »
The MCP3551 datasheet DS21950B alleges:
Quote
5.4.2 2-WIRE CONTINUOUS CONVERSION OPERATION,
(CS TIED PERMANENTLY LOW)

It is possible to use only two wires to communicate with the MCP3551/3 devices. In this state, the device is always in Continuous Conversion mode, with internal conversions continuously occurring. This mode can be entered by having CS low during power-up or changing it to a low position after power-up. If CS is low at power-up, the first conversion of the converter is initiated approximately 300 us after the power supply has stabilized.
Knowing 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.

« Last Edit: June 20, 2016, 11:20:18 am by Ian.M »
 

Offline yashrkTopic starter

  • Frequent Contributor
  • **
  • Posts: 277
  • Country: in
  • A MAKER, AN ENGINEER, A HOBBYIST FOR LIFE
    • My Personal Blog
Re: Bit Banging SPI
« Reply #5 on: June 20, 2016, 11:30:47 am »
Cool pic  :-DD !!

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.
Find me and things I'm working on - https://www.yashkudale.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Bit Banging SPI
« Reply #6 on: June 20, 2016, 10:13:19 pm »
"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.
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Bit Banging SPI
« Reply #7 on: June 21, 2016, 01:16:33 am »
mcp3551, continuous mode, adc input is 1v.

enjoy.
================================
https://dannyelectronics.wordpress.com/
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 13066
Re: Bit Banging SPI
« Reply #8 on: June 21, 2016, 01:49:17 am »
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 . . . .
« Last Edit: June 21, 2016, 03:54:40 am by Ian.M »
 

Offline yashrkTopic starter

  • Frequent Contributor
  • **
  • Posts: 277
  • Country: in
  • A MAKER, AN ENGINEER, A HOBBYIST FOR LIFE
    • My Personal Blog
Re: Bit Banging SPI
« Reply #9 on: June 21, 2016, 03:38:42 am »
@danny did you used that same code ?
Find me and things I'm working on - https://www.yashkudale.com/
 

Offline yashrkTopic starter

  • Frequent Contributor
  • **
  • Posts: 277
  • Country: in
  • A MAKER, AN ENGINEER, A HOBBYIST FOR LIFE
    • My Personal Blog
Re: Bit Banging SPI
« Reply #10 on: June 22, 2016, 03:58:07 am »
@dannyf Please reply !!
Find me and things I'm working on - https://www.yashkudale.com/
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf