Problem med AVR SPI

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Oskar
Inlägg: 1946
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Problem med AVR SPI

Inlägg av Oskar »

Hej på er alla!

Har följande uppkopplat:
Två stycken Atmega 8515:

MISO-MISO
MOSI-MOSI
SCK-SCK
SS-SS

Mastern aktiverar slaven med SS före varje paket data skall skickas, detta eftersom jag sedan skall ha ett system med fem slaves. Det jag försöker få igång nu är en överföring master-slave totalt 40byte.

I mastern kör jag med pollad SPI, bara en loop som matar ut byte efter byte och väntar på SPIF emellan.

Mitt problem är på slavesidan, där kommunikationen måste vara interruptstyrd, jag har en tvådimensionell array som jag vill ta tecken för tecken. Det jag ser med skopet är att data skiftas ut på korrekt sett från mastern, men från slaven kommer inget. Som jag kodat nu skriver jag det värde som jag vill ha skiftat ut vid nästa sändning till SPDR i slutet av interruptrutinen, det verkar inte fungera. Jag känner på mig att jag missat något, nollas dataregistret när interruptrutinen körts klart? Skriver jag det data jag vill ha ut till SPDR någon annanstans, till exempel i main, så skiftas det ut på korrekt sätt.

Jag kör WinAVR.

Vill ni se koden (något inaktuell, men fortfarande samma SPI kodning .. och ja .. hopplöst rörig):
http://www.gargnas.net:3000/Exjobb/Cpro ... VR/Slaves/

Tacksam för svar .. håret börjar gråna .. ;)

/Oskar
Senast redigerad av Oskar 13 oktober 2006, 15:11:56, redigerad totalt 1 gång.
Användarvisningsbild
Abra Hana
Inlägg: 94
Blev medlem: 12 maj 2005, 13:20:58

Inlägg av Abra Hana »

Du skrev inget om hur dina SPI inställning är . annars jag gör som sodjan KOLLA DATASHEET , Kul vad !!

Du får ingen data från AVR_Slave ! , det kan vara på grund av att AVR_SLAVE hinner inte skriva i SPDR den byte som ska shiftas från AVR_Slav till AVR_Master under SPI kommunication .

Om jag förstå dig rätt , du vill att AVR_Master antingen läsa från eller skriva till en 2 dimensionell som finns i AVR_Slaves minnet . och du har ingen kontroll alls over data , du bara skriver i en loop en byte till SPDR i AVR_Master och du förväntar dig samtidig få en svar från AVR_Slave , du har ingen kontroll alls över den tid det tar för AVR_Slave att läsa mottagit data , bearbeta den, och sist skriva svaret i sin SPDR registret .

AVR_Master kör en Pollad SPI i en Loop .
I Första loopet Skriver AVR_Master en byte i SPDR detta startar SPI kommunikation , Bitarna shiftas från AVR_Master till AVR_Slave , samtidigt shiftas bitarna från AVR_Slave till AVR_Master .

i första Loopet , Första bytet du får från AVR_Slave är en så kallad dummy byte , altså om du inte i förväg har skrivet en byte i AVR_Slaves SPDR kommer AVR_Master att få det SPDR:s tidigare eller initierad register värdet . det kan vara helt enket 0X00 .

I andra Loopet , Om AVR_Master ( innan han skriver sin andra databyte i SPDR ) inte tar hänsyn till den tid det krävs för att AVR_Slave bearbetar sitt första mottagit data bytet , kommer AVR_Master att få ett oönskat svar .

Alltså , Det räcker inte bara med att sälla in SPI kommunikation mellan AVR_Master och AVR_Slave , du måste också komma på ditt eget protokoll som uppfyller programmet krav . till ex .

Du vill skriva 2 bytes i minnet som finns i en AVR_Slave , för varje byte AVR_Master skickar måste det komma en bekräftelse från AVR_Slave som säger att skrivning till minnet är OK eller inte OK ( 0X0F = inte OK och 0XFF = OK.

1 ) du Ställer in SPI i båda AVR_Master och AVR_Slave .

2) AVR_Master väljer AVR_Slave med hjälp av SS pin
AVR_Slave skriver en dummy byte i sin SPDR till ex 0X00 .

2) AVR_Master skriver första bytet i sin SPDR registret , detta startar automatisk Shiftning av data mellan AVR_Master och AVR_Slave .

3) AVR_Master läser första mottagit data byte och jämför den med OK eller inte OK . Första mottagit bytet är en dummy byte , alltså varken OK eller inte OK . AVR_Master måste vänta den tiden det krävs för AVR_Slave att bearbeta första mottagit data byte ( att läsa sitt första mottagit data byte , skriva denna bytet i ett önskat minne, och sist skriver OK eller int OK i sin SPDR.)

3) Slave läser sin första Mottagit data , jämför den med dummy byte , om dem är lika , gör ingenting , annars skriv detta byte i önskat minnet och bekräfta detta med OK eller inte OK .

4) AVR_Master har nu vänat tillräkligt länge .( tid som krävs för att AVR_Slave bearbeta första mottagit data bytet) . Han skriver en dummy byte i SPDR för att ta reda om förra data bytet är rätt lagrat i AVR_Slave minnet , AVR_Master läser mottagit data bytet och jämför det med OK eller Inte OK . AVR_Slaves mottagit data är en dummy data , så han får inte göra nåt , han måste vänta på nästa byte .

5) *Om svaret är OK , kommer AVR_Master att skicka andra bytet genom att skriva detta bytet i SPDR och vänta ett tag .AVR_Slave ta emot och bearbeta sin andra data byte , sedan bekräfta det genom att skriva OK eller inte OK .

*Om svaret är inte OK , det blev fel under lagring eller annat av data bytet , AVR_Master måste starta hela SPI proceduren från början .

5) AVR_Master har nu skickat sina båda data byte , han fick OK för det första men inte för det andra . efter att AVR_Master har väntat länge skickar han en dummy byte för att ta emot bekräftelse av andra data bytet , Om bekräftelse är OK , avslutas SPI . annars startar Poceduren från början .eller skickar andra data bytet en gång till .



lycka till .
Användarvisningsbild
Oskar
Inlägg: 1946
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Inlägg av Oskar »

Tack för ett seriöst svar!

Har ändå en känsla av att det är något ändå allvarligare än bristen på överföringsprotokoll. Har testat att sakta ner överföringen löjligt mycket, men det verkar som om allt jag skriver till SPDR i interruptrutinen på slaven bara "försvinner".

Enligt det jag har hittat i exempelväg och dylikt så skall det ej vara nån flagga som jag missar att hala?

Funderar om man skall toggla SS mellan varje byte, men det tror jag heller inte ska göra någon skillnad?

Helt klart borde man som du säger säkra upp och bekräfta att slaven verkligen är med på varje byte, men det måste vara något annat som gör att absolut inget skickas från slaven. Gjorde ett litet test och frigjorde slaven från dess normala uppgift, så att den kunde ta emot pollat och skriva till SPDR utanför interruptrutinen, och då verkade det funka .. suck .. :)

BTW, har en liten "skvallerdiod" som säkrar att slaven verkligen går in i interruptrutinen ;)

/Oskar
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Ja se där, du hann före mig!
Funderar om man skall toggla SS mellan varje byte, men det tror jag heller inte ska göra någon skillnad?
Jag hittade din masterkod och såg att du togglade SS för varje ny byte. Tydligen så kan man inte göra så på en AVR(?) Längst upp på s.131 i databladet står det att slavens alla SPI-register nollställs såfort SS gå hög.
Du måste alltså låta den vara låg under hela tiden du överför ditt paket. (Finns andra processorer då det INTE är så... så det är lite konstigt tycker jag.. men men)
Användarvisningsbild
Oskar
Inlägg: 1946
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Inlägg av Oskar »

Logiskt nog heter min nuvarande masterkod "test", så oJsan kollade på fel kod. Här är den testkod jag för närvarande försöker att få ihop:
http://www.gargnas.net:3000/Exjobb/Cpro ... est/test.c
Användarvisningsbild
Abra Hana
Inlägg: 94
Blev medlem: 12 maj 2005, 13:20:58

Inlägg av Abra Hana »

*


Fil init.c
--------------------------------------------------------------------------
#define DDR_SPI PORTB
#define DD_MOSI PB5
#define DD_SCK PB7

void spi_master_init(void)
{
// Set MOSI and SCK output, all others input
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);

???? Vad vill du åstadkomma med denna kod rad ? kolla din #define DDR_SPI PORTB
------------------------------------------------------------------------

Man skriver till DDRB och inte till PORTB om man vill konfiguera MOSI och SCK som output eller input pinnar .



*
Användarvisningsbild
Oskar
Inlägg: 1946
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Inlägg av Oskar »

Hade en hel del skräp i den kod jag lade upp när jag ställde min första fråga, ville egentligen bara visa hur jag kodat SPI interruptrutinen i slaven. Nu har jag i allafall uppdaterat koden på servern:

http://www.gargnas.net:3000/Exjobb/Cprogrammering_AVR/

Har även testat på morgonskvisten med en loopback kabel på mastern, och då "funkar" det. Problemet är att jag i slaven inte skriver till SPDR på rätt sätt .. verkar det som.

/oskar
Användarvisningsbild
Oskar
Inlägg: 1946
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Inlägg av Oskar »

AHA!! Tror jag har hittat felet .. ååh, varför kan man aldrig läsa databladen tillräckligt noga .. suck :)

Återkommer med besked om hur det går .. nu skall här kodas .. muahaa

EDIT: På med kodarmusiken .. Blind Guardian och ETOS!! \m/

/Oskar
Användarvisningsbild
Oskar
Inlägg: 1946
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Inlägg av Oskar »

Nu har jag fått ordning på saker och ting. Två fel låg bakom mina felsymptom. Slave select behandlades inte på ett korrekt sätt i mastern, vidare så hade jag lyckats göra ett klassiskt copy-paste misstag i min huvvudrutin i slaven. Felet i mastern var att jag inte läst följande tillräckligt noga:
"When configured as a Slave, the SPI interface will remain sleeping with MISO tri-stated as long as the SS pin is driven high. In this state, software may update the contents of the SPI Data Register, SPDR, but the data will not be shifted out by incoming clock pulses on the SCK pin until the SS pin is driven low." MEd andra ord måste man se till att skriva till SPDR när SS är hög, och det fixade genom att lägga in följande i interruptrutinen i slaven:
while(!CHECKBIT(PINB,PB4));
I interruptrutinen läser den nu innehållet i SPDR, väntar på att SS skall gå låg, sedan flyttas och joxas det lite med indexen till min array, sedan skrivs den aktuella positionen i arrayen till SPDR precis innan interruptrutinen är slut.
I mastern togglas nu SS mellan varje byte, och det verkar vara den korrekta vägen att gå.

I min huvudrutin, som slaven mestadels skall vara upptagen med att köra, håller jag på och trixar med datariktningar på pinnarna, mitt copy paste fel bestod av en elak rad kod som satte dataraktningen på MISO felaktigt. Det var detta som gjorde att jag aldrig fick något ut från slaven.

Ojoj .. det har varit frustrerande, men nu verkar jag ha hittat alla de större tokigheterna.

/oskar
Skriv svar