PIC SPI slave driver
PIC SPI slave driver
Hej!
Jag implementerar en SPI slave driver, och min approach är att göra den interrupt-driven.
PIC: 18F4321
Compiler: CC8e
Förutsättningar:
- SPI low priority interrupt
- W, STATUS and BSR sparas/återställs i isr.
Mitt problem:
Efter ett interrupt (SSPIF) sparas SSPBUF till RAM som rxData. Därefter vill jag i samma kontext uppdatera SSPBUF med txData, vilket ska shift:as ut nästa interrupt. Dock går inte detta, det verkar som att det inte är möjligt att påverka hårdvaruregister? Hur ska man göra? Några ideér?
Jag har testat pollande funktionalitet, och det fungerar, fast då riskerar man ju att inte fånga ett "spi-tåg"...eftersom main-loopen innehåller en hel del annan funktionalitet.
Tack på förhand för tips!
Jag implementerar en SPI slave driver, och min approach är att göra den interrupt-driven.
PIC: 18F4321
Compiler: CC8e
Förutsättningar:
- SPI low priority interrupt
- W, STATUS and BSR sparas/återställs i isr.
Mitt problem:
Efter ett interrupt (SSPIF) sparas SSPBUF till RAM som rxData. Därefter vill jag i samma kontext uppdatera SSPBUF med txData, vilket ska shift:as ut nästa interrupt. Dock går inte detta, det verkar som att det inte är möjligt att påverka hårdvaruregister? Hur ska man göra? Några ideér?
Jag har testat pollande funktionalitet, och det fungerar, fast då riskerar man ju att inte fånga ett "spi-tåg"...eftersom main-loopen innehåller en hel del annan funktionalitet.
Tack på förhand för tips!
Re: PIC SPI slave driver
Jag förstår inte vad du menar med "inte är möjligt att påverka hårdvaruregister". Du vill skriva till SSPBUF och det är inga problem. Databladet, sid 164, säger såhär:eloom skrev:Dock går inte detta, det verkar som att det inte är möjligt att påverka hårdvaruregister? Hur ska man göra? Några ideér?
SSPSR is the shift register used for shifting data in or out. SSPBUF is the buffer register to which data bytes are written to or read from.
In receive operations, SSPSR and SSPBUF together create a double-buffered receiver. When SSPSR receives a complete byte, it is transferred to SSPBUF and the SSPIF interrupt is set.
During transmission, the SSPBUF is not doublebuffered. A write to SSPBUF will write to both SSPBUF and SSPSR.
Re: PIC SPI slave driver
Håller med! Det är lite oklart vad du menar med "Inte möjligt". På vilket sätt? Vad händer?
Annars var det bra uppställt!
Annars var det bra uppställt!

Re: PIC SPI slave driver
Tack för svaren, ursäkta att jag var lite oklar.
Exempel:
Inne i interruptrutinen:
if( SSPIF )
{
rxByte = SSPBUF; (MOVFF SSPBUF,rxByte)
SSPBUF = txByte; (MOVFF txByte,SSPBUF)
SSPIF = 0;
}
Det som sker är att SSPBUF inte uppdateras med txByte, utan rxByte ligger kvar. Jag har även testat med att använda WREG (MOVWF) för att läsa/skriva registret.
Exempel:
Inne i interruptrutinen:
if( SSPIF )
{
rxByte = SSPBUF; (MOVFF SSPBUF,rxByte)
SSPBUF = txByte; (MOVFF txByte,SSPBUF)
SSPIF = 0;
}
Det som sker är att SSPBUF inte uppdateras med txByte, utan rxByte ligger kvar. Jag har även testat med att använda WREG (MOVWF) för att läsa/skriva registret.
Re: PIC SPI slave driver
Tack återigen för era kommentarer!
Ger nog snart upp på att lösa det interruptdrivet och kör på polling + en extra pinne som en "soft select" för att sparka in main-loopen i "receive" mode.
Vad gäller att ladda SSPBUF finns följande exempel i PIC18F4321 data sheet, p.170, EXAMPLE 18-1: LOADING THE SSPBUF (SSPSR) REGISTER:
Detta funkar bra för polling, fast hänger ju naturligtvis i den loopen tills BF är hög. Jag har testat att använda de 4 sista raderna i interrupt rutinen. WREG fyllls med txDatan, men SSPBUF innehåller fortfarande RxDatan efter MOVFW SSPBUF....

Vad gäller att ladda SSPBUF finns följande exempel i PIC18F4321 data sheet, p.170, EXAMPLE 18-1: LOADING THE SSPBUF (SSPSR) REGISTER:
Kod: Markera allt
LOOP BTFSS SSPSTAT, BF ;Has data been received (transmit complete)?
BRA LOOP ;No
MOVF SSPBUF, W ;WREG reg = contents of SSPBUF
MOVWF RXDATA ;Save in user RAM, if data is meaningful
MOVF TXDATA, W ;W reg = contents of TXDATA
MOVWF SSPBUF ;New data to xmit
Re: PIC SPI slave driver
När du läser får du så klart alltid RX-data, men när du skriver skickas det iväg via SPI.
SSPBUF är inte ett fysiskt register, utan bara en kanal för att kunna hämta information ur en fysisk RX-buffert, och lägga information i en fysisk TX-buffert. När du läser SSPBUF läser du alltså ur en annan fysisk buffert än vad du skriver när du skriver till SSPBUF.
Det är så jag uppfattar det iaf.
SSPBUF är inte ett fysiskt register, utan bara en kanal för att kunna hämta information ur en fysisk RX-buffert, och lägga information i en fysisk TX-buffert. När du läser SSPBUF läser du alltså ur en annan fysisk buffert än vad du skriver när du skriver till SSPBUF.
Det är så jag uppfattar det iaf.
Re: PIC SPI slave driver
Utan att titta i databladet, så låter det som en trolig förklaring. Databladet borde ge facit!
Re: PIC SPI slave driver
Testa om det är interruptflaggan som blockerar.
if( SSPIF )
{
rxByte = SSPBUF; (MOVFF SSPBUF,rxByte)
SSPIF = 0;
SSPBUF = txByte; (MOVFF txByte,SSPBUF)
}
if( SSPIF )
{
rxByte = SSPBUF; (MOVFF SSPBUF,rxByte)
SSPIF = 0;
SSPBUF = txByte; (MOVFF txByte,SSPBUF)
}
Re: PIC SPI slave driver
Hur jag än konfigurerar SPI eller ordningen på läsa/skriva/rensa flaggor stöter jag på problem.
Mitt senaste försök var följande, vilket obönhörligen fastnar i i sista loopen eftersom WCOL trots allt sätts.
Läste på microchips support att SS måste togglas efter varje byte läst, ska undersöka det när jag får tid...
Mitt senaste försök var följande, vilket obönhörligen fastnar i i sista loopen eftersom WCOL trots allt sätts.
Kod: Markera allt
unsigned char x;
if( SSPIF )
{
SSPIF = 0;
if( SSPOV ) SSPOV = 0;
x = SSPBUF;
while( BF );
do
{
WCOL = 0;
SSPBUF = x;
} while( WCOL );
}
Re: PIC SPI slave driver
Ifall masterns klocka inte tar en paus mellan bytesen kommer ju programmet inte hinna ladda SSPBUF förrän det är försent, om jag förstår detta rätt. Möjligtvis räcker tiden mellan två flanker på SPI-klockan för att ladda SSPBUF, men ifall SPI-klockan är snabb i förhållande till Fosc kanske tiden inte finns.Tar mastern någon paus, och hur snabb är SPI-klockan?
Re: PIC SPI slave driver
Internal oscillator, 4MHz. -> Det kanske inte är så bra, bör kanske prova med en kristall eller RC-krets.
Mastern (inte en PIC) har en SCK bit rate på 32kBit/s, ingen paus mellan bytes skickade. -> Ska försöka med att skicka en byte i taget.
Mastern (inte en PIC) har en SCK bit rate på 32kBit/s, ingen paus mellan bytes skickade. -> Ska försöka med att skicka en byte i taget.
Re: PIC SPI slave driver
Problemet är löst
Mastern's klocka tog inte en paus mellan varje byte som shift:ades ut. Så inte konstigt att WCOL sattes sporadiskt.
Tack för era tips, de var värdefulla!

Tack för era tips, de var värdefulla!
Re: PIC SPI slave driver
Kul att det löste sig. En nyfiken fråga; efter att SSPBUF skrivits (utan kollision), finns den skrivna byten i SSPBUF när SSPBUF läses, eller läses då en byte som tidigare tagits emot?