how to get 10bit ADC data in PIC

Status
Not open for further replies.

Siddft

Junior Member level 2
Joined
Oct 19, 2012
Messages
20
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Bangalore
Visit site
Activity points
1,432
Hello all,

I am doing Single master multiple slave implemetation.
Master - PIC18F4550
Slave - PIC18F4520

A potentiometer is connected to the Slave. Slave will convert the Potentiometer value to digital and communicate with the master using SPI protocol.

I am getting 8bit data(ADRESH -- Left justified)correctly from slave. But I have to get 10bit data(ADRESH - 8bit, ADRESL - 2bit).

How to get 10bit data????

Here is the sample code for master and slave
Master
------
LATDbits.LATD0 = 0; //Slave select
while(SSPSTATbits.BF == 0); //wait untill the buffer is full
var1 = SSPBUF;
LATDbits.LATD0 = 1;
delay
LATDbits.LATD0 = 0;
while(SSPSTATbits.BF == 0);
var2 = SSPBUF;
LATDbits.LATD0 = 1;
delay

Slave
-----
ADCON0bits.CHS0 = 0;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS3 = 0;
ADCON0bits.GO = 1;
while (ADCON0bits.NOT_DONE);
ch1 = ADRESL;
ch2 = ADRESH;

SSPCON1bits.WCOL = 0;
while(PORTAbits.RA5 == 1);//wait untill slave select
SSPBUF = ch1;
while(SSPSTATbits.BF == 0);
delay
SSPCON1bits.WCOL = 0;
while(PORTAbits.RA5 == 1);//wait untill slave select
SSPBUF = ch2;
while(SSPSTATbits.BF == 0);
delay

The above code works fine for 8bit data but not giving 10bit data(May be because of some sync problem), So how to get 10bit data.

please share me if you have any sample code.

Advance thanks for your help.

regards,
Sid
 

I haven't worked with the 18 series but with the 16, 24, 33ds.
If I remember right in the 10 bits operation the data is AdressL (8 less significant bits), AdressH (2 most significant bits) and not the contrary.

Maybe your problem is there.
 

You have choosen Left justified for ADC result.

So your low byte is ADRESH and high byte is ADRESL.


Code C - [expand]
1
2
3
4
5
6
7
8
unsigned int lowbyte, highbyte, result;
 
 
highbyte = ADRESL;
highbyte = highbyte << 8;
lowbyte = ADRESH;
highbyte = highbyte | lowbyte;
result = highbyte;

 

I haven't worked with the 18 series but with the 16, 24, 33ds.
If I remember right in the 10 bits operation the data is AdressL (8 less significant bits), AdressH (2 most significant bits) and not the contrary.

Maybe your problem is there.

I think it's not mandatory that 8 less significant bits should be in AdressL and 2 most significant bits should be in AdressH.

It depends on the ADFM bit in ADCON2 register.

if ADFM=0
Then Left justified (D10-D2 --> ADRESH)
if ADFM=1
Then right justified (D1-D0 --> ADRESL)

In my prog i have done Left justified(ADFM = 0)

- - - Updated - - -

Hello Jayanth,


Above code may be correct but in SPI protocol we can send only 8bit at a time. But result contain 16 bit.

Thanks.
 

Then send ADRESL and ADRESH and at destination compose this two 8 bit in on 16 bit value(integer)

Yes, i tried with the following code.

LATDbits.LATD0 = 0; //Slave select
while(SSPSTATbits.BF == 0); //wait untill the buffer is full
var1 = SSPBUF;
LATDbits.LATD0 = 1;
delay
LATDbits.LATD0 = 0;
while(SSPSTATbits.BF == 0);
var2 = SSPBUF;
LATDbits.LATD0 = 1;
delay
mdata = var1 | var2;

but still 'm not getting the perfect output.

I think there is some sync problem.How to overcome from this problem???

Thanks.

- - - Updated - - -

1st time SSPBUF contains the ADRESH value(var1).
2nd time SSPBUF contains the ADRESL value(var2).
 

Master


LATDbits.LATD0 = 0; //Slave select
while(SSPSTATbits.BF == 0); //wait untill the buffer is full
var1 = SSPBUF;
LATDbits.LATD0 = 1;
delay

highbyte = var1;
highbyte = highbyte << 8;


LATDbits.LATD0 = 0;
while(SSPSTATbits.BF == 0);
var2 = SSPBUF;
LATDbits.LATD0 = 1;
delay

lowbyte = var;
highbyte = highbyte | lowbyte;
result = highbyte;
 

CS = Low
SPI_Write ADRESH
SPI_Write ADRESL
CS = High

Fix of lacmannmarcel's code


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
LATDbits.LATD0 = 0;  //Slave select
while(SSPSTATbits.BF == 0);  //wait untill the buffer is full
var1 = SSPBUF;  
LATDbits.LATD0 = 1; 
delay
 
highbyte = var1;
highbyte = highbyte << 8;
 
 
LATDbits.LATD0 = 0; 
while(SSPSTATbits.BF == 0);
var2 = SSPBUF;  
LATDbits.LATD0 = 1;
delay
 
lowbyte = var2;
highbyte = highbyte | lowbyte;
result = highbyte;

 

Hello lachmannmarcel,

I tried your code,still it is not working properly.
it's giving 10bit value but the values are not correct.
so i gave more delay but still it's not working.

Thanks
sid

- - - Updated - - -

 

No need to make slave low and high two times. You can send 8 bits 2 times with 2 write operations. Can you show your full master and slave codes?
SPI can send 8bit data at a time.

Here is the code for Master and Slave.


master code
-------------
OpenSPI(SPI_FOSC_64, MODE_01, SMPMID); //SPI configuration

SSPCON1bits.WCOL = 0; //Clearing SSPBUF
LATDbits.LATD0 = 0; //Slave select
WriteSPI(0xFF); //writing 0xFF to slave
for(mdelay = 0; mdelay < 10; mdelay++);
var1 = SSPBUF;
LATDbits.LATD0 = 1;
highbyte = var1;
highbyte = highbyte << 8; //deselecting SS
for(mdelay = 0; mdelay < 100; mdelay++);

SSPCON1bits.WCOL = 0;
LATDbits.LATD0 = 0; //2nd time slave selct
WriteSPI(0xAA);
for(mdelay = 0; mdelay < 10; mdelay++);
var2 = SSPBUF;
LATDbits.LATD0 = 1;
lowbyte = var2;
for(mdelay = 0; mdelay < 100; mdelay++);

highbyte = highbyte | lowbyte;
result = highbyte;

Slave
--------
int Count;
unsigned char ch1,ch2,data;

ADCON0 = 0x01; // AD Control Register 1: Enable (turn on ADC)
ADCON2 = 0x3C; // AD Control Register 2: 20 TAD (accuracy), FOSC 4 (freq/4)
ADCON2bits.ADFM = 0; // ADC result left justified (D10 - D2 --> ADRESH, D1 - D0 --> ADRESL)

TRISCbits.TRISC3 = 1; //SPI pins(PIC18F4520)
TRISCbits.TRISC4 = 1;
TRISCbits.TRISC5 = 0;
TRISAbits.TRISA5 = 1;

TRISDbits.TRISD0 = 0; //Configuring PORTD as output
TRISDbits.TRISD1 = 0;
TRISDbits.TRISD2 = 0;
TRISDbits.TRISD3 = 0;
TRISDbits.TRISD4 = 0;
TRISDbits.TRISD5 = 0;
TRISDbits.TRISD6 = 0;
TRISDbits.TRISD7 = 0;

SSPSTATbits.SMP = 0; //Configuration of SPI register
SSPSTATbits.CKE = 0;
SSPCON1bits.CKP = 0;
SSPCON1bits.SSPM3 = 0;
SSPCON1bits.SSPM2 = 1;
SSPCON1bits.SSPM1 = 0;
SSPCON1bits.SSPM0 = 0;
SSPCON1bits.SSPEN = 1;

while(1)
{

ADCON0bits.CHS0 = 1; //Selecting AN0 as analog input
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS3 = 0;
ADCON0bits.GO = 1; //Start analog to digital conversion
while (ADCON0bits.NOT_DONE);
ch1 = ADRESL;
ch2 = ADRESH;


data = SSPBUF; //loading the SSPBUF value to some dummy varible(Previous data in SSPBUF)

//First time slave select
SSPCON1bits.WCOL = 0; //Clearing SSPBUF register
while(PORTAbits.RA5 == 1); //wait for slave select
SSPBUF = ch1; //Loading ADRESH value to SSPBUF
while(SSPSTATbits.BF == 0); //wait untill the buffer is full

for(Count=0;Count<10;Count++); //delay

//Second time slave selct
SSPCON1bits.WCOL = 0; //Clearing SSPBUF register
while(PORTAbits.RA5 == 1); //wait for slave select
SSPBUF = ch2; //Loading ADRESL value to SSPBUF
while(SSPSTATbits.BF == 0); //wait untill the buffer is full

for(Count=0;Count<10;Count++); //delay
}
 

I have written a few programs where 8 bit address and 8 bit data have to be sent through spi to the spi device. I have used 2 spi writes between toggling of CS and they work fine. For your reference see this bit banging spi code. I have tested that code and it works fine.

https://www.maximintegrated.com/app-notes/index.mvp/id/4184
 

Thanks Jayanth,

I don't know anything about SPI BIT BANGING.
if u have any code which works for 10bit data, could u please share me that code.

Thanks,
Sid
 

'm using PIC18F4520 as master and PIC18F4550 as slave
Compiler --> MPLAB C18 C Compiler

Thanks,
Sid
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…