So erhalten Sie 10-Bit-Daten von ADC mit dem SPI-Protokoll

Ich mache eine Single-Master-Multiple-Slave-Implementierung.
Master - PIC18F4550
Slave - PIC18F4520

Am Slave ist ein Potentiometer angeschlossen. Der Slave konvertiert den Potentiometerwert in einen digitalen Wert und kommuniziert mit dem Master über das SPI-Protokoll.

Ich erhalte 8-Bit-Daten (ADRESH – linksbündig) korrekt vom Slave. Aber ich muss 10-Bit-Daten erhalten (ADRESH - 8 Bit, ADRESL - 2 Bit).

Wie bekomme ich 10bit Daten?

Hauptkennziffer

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;

Sklave

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
}

Antworten (1)

Es gibt ein paar Dinge, die mir verdächtig erscheinen. Auf der Master-Seite würde ich eine kleine Verzögerung zwischen dem Setzen des Slave-Auswahlsignals und dem Senden der Dummy-Daten (um die Übertragung zu starten) einführen, obwohl dies möglicherweise kein Problem darstellt. Die anderen Dinge, die verdächtig sind, sind, dass Sie in Ihrem Sklavencode zuerst ...

ch1 = ADRESL;   
ch2 = ADRESH;

aber dann

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

Nach Ihren Kommentaren und dem Code, den der Master erwartet, erwarten Sie also, zuerst das High-Byte und dann das Low-Byte zu erhalten, aber der Slave sendet tatsächlich zuerst ADRESL und dann ADRESH.

Schließlich fügen Sie nach der Übertragung des ersten Bytes eine (längere) Verzögerung (mdelay < 100) ein, bevor Sie SS auf dem Master abwählen. Auf der Slave-Seite gibt es nur eine kurze Verzögerung, dann wartet man darauf, dass die SS erneut gesetzt wird, die höchstwahrscheinlich immer noch aufgrund der langen Verzögerung durch den Master gesetzt wird. Dann setzen Sie das zweite Datenbyte und warten auf das Setzen des BF-Bits. Ich bin mit dem PIC18F4550 nicht vertraut, daher weiß ich nicht, ob dies ein Problem ist, aber da Sie das BF-Bit nie explizit löschen, wird es möglicherweise noch von der ersten Runde an gesetzt, was dann dazu führen würde, dass Ihr Slave das neu startet Hauptschleife (nach einer weiteren kurzen Verzögerung).