Cómo obtener datos de 10 bits de ADC mediante el protocolo SPI

1

Estoy haciendo la implementación de esclavo múltiple maestro único.
Maestro - PIC18F4550
Esclavo - PIC18F4520

Un potenciómetro está conectado al esclavo. Slave convertirá el valor del potenciómetro a digital y se comunicará con el maestro utilizando el protocolo SPI.

Estoy obteniendo datos de 8 bits (ADRESH - Justificado por la izquierda) correctamente del esclavo. Pero tengo que obtener datos de 10 bits (ADRESH - 8 bits, ADRESL - 2 bits).

¿Cómo puedo obtener datos de 10 bits?

Código maestro

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;

Esclavo

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
}
    
pregunta user24432

1 respuesta

1

Hay algunas cosas que me parecen sospechosas. En el lado del maestro, introduciría un pequeño retraso entre la configuración de la señal de selección del esclavo y el envío de datos ficticios (para iniciar la transferencia), aunque esto no sea un problema. Las otras cosas que son sospechosas es que en tu código de esclavo tienes primero ...

ch1 = ADRESL;   
ch2 = ADRESH;

pero entonces

SSPBUF = ch1;    //Loading ADRESH value to SSPBUF
...
SSPBUF = ch2;    //Loading ADRESL value to SSPBUF

Entonces, de acuerdo con sus comentarios y el código que espera el maestro, espera obtener primero el byte alto, luego el byte bajo, pero el esclavo envía ADRESL primero, luego ADRESH.

Por último, después de la primera transferencia de bytes, introduce un retraso largo (er) (mdelay < 100) antes de deseleccionar SS en el maestro. En el lado del esclavo, solo hay un breve retraso, luego se espera a que se establezca nuevamente el SS, que probablemente todavía se establezca en función del largo retraso del maestro. A continuación, establece el segundo byte de datos y espera a que se establezca el bit BF. No estoy familiarizado con el PIC18F4550, por lo que no sé si esto es un problema, pero como nunca borras explícitamente el bit BF, es posible que todavía esté configurado desde la primera ronda, lo que provocaría que tu esclavo reinicie bucle principal (después de otro breve retraso).

    
respondido por el fm_andreas

Lea otras preguntas en las etiquetas