ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
mmarks
Inlägg: 46
Blev medlem: 4 februari 2012, 16:00:14

ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av mmarks »

Jag håller på med ett projekt där en atmega16 (som sitter på en stk500 för tillfället) kommunicerar seriellt med ett pythonprogram på min pc. Atmegan har en 5 element lång vektor/array av uint_8 vars värden updateras genom denna kommunikation. I atmegan sköts all kommunikation genom en interruptfunktion. Upplägget är följande:

python skickar först ett tecken som avgör vilket index som nästkommande värde ska sparas till
atmegan svarar genom att skicka tillbaka samma sak som den har mottagit (på så vis kan det kontrolleras i python att kommunikationen har gått rätt till)
python skickar nu det värde som ska sparas
atmegan sparar detta värde (samt skickar tillbaka det till python)

För att debugga så låter jag atmegan visa ett värde ur denna array mha LED:sen på STK:n, vilket index som visas kan jag ändra genom att skicka ett speciellt tecken från python.

Det hela funkar fint.. nästan hela tiden, ibland så byter atmegan det index som visas utan att python har skickat ett kommando om detta! i python görs en automatisk kontroll att det som kommer tillbaka från atmegan överrensstämmer med det som skickades så jag ser då att atmegan inte har feltolkat något kommando. Eftersom python alltid väntar på ett svar innan det skickar nästa kommando så sker det heller inga buffer overflows(?). Pga detta så är jag tämligen säker på att felet inte ligger i själva kommunikationen utan någon annanstans men jag kan inte komma på var :(
Min enda tanke om vad det skulle kunna vara är att jag har deklarerat för lite utrymme för någon variabel och att denna i så fall ibland skriver över variabeln "displayed_channel" men som sagt så kan jag inte komma på var i såna fall.

Nedan ser ni min interruptfunktion i atmegan, sist i kommentarerna till varje case har jag lagt till vilket tecken som motsvarar respektive case.

Kod: Markera allt

ISR(USARTRXC_vect){
	static int index;
	static int displayed_channel= 0;
	static uint8_t serial_data[5]; //vector, 5 elements
	static char received_byte;
	
	received_byte = UDR; //reading register
	
	switch(received_byte){
		case CHANNEL_1: //axis 0 'a'
			index = 0;
			break;
		case CHANNEL_2: //axis 1 'b'
			index = 1;
			break;
		case CHANNEL_3: //axis 2 'c'
			index = 2;
			break;
		case CHANNEL_4: //axis 3 'd'
			index = 3;
			break;
		case CHANNEL_5: //axis 4 'e'
			index = 4;
			break;
		case CHANGE_CHANNEL_TO_DISPLAY: // for debugging 'f'
			displayed_channel++;
			if (displayed_channel > 4){
				displayed_channel = 0;
			}
			break;
		default:
			serial_data[index] = (uint8_t)received_byte;
			PORTB = ~serial_data[displayed_channel]; // for debugging
			break;
	}
	serial_write(&received_byte);
}
Senast redigerad av mmarks 11 augusti 2013, 09:37:07, redigerad totalt 1 gång.
spaderkung
Inlägg: 138
Blev medlem: 12 maj 2007, 11:24:24
Ort: Sjöbo

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av spaderkung »

Ifall någon av variablerna inne i ISR används utanför ISR rekommenderas att de skall definieras som volatile.

En annan luring är om man i Main glömmer att disabla interrupts när man behöver en atomär operation.
mmarks
Inlägg: 46
Blev medlem: 4 februari 2012, 16:00:14

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av mmarks »

Just nu är denna ISR-funktion den enda koden som körs kontinuerligt (det går lite uppstartsfunktioner innan dess) så varken deklaration som volatile eller atomära funktioner i main är ett problem i detta fall :-(
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av Swech »

while(1){}
Innebär väl att du inte lämnar interruptrutinen?
Du skall ha din evighetsloop utanför interruptet annars får du väl interupt på interupt
inne i rutinen och stacken tar slut tilll sist

Swech
mmarks
Inlägg: 46
Blev medlem: 4 februari 2012, 16:00:14

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av mmarks »

Ja du har helt rätt i detta men min anledning till att ha denna till synes dumma/meningslösa rad är helt enkelt att atmegan SKA "frysa" om jag får ett parity bit error så att jag ser att detta har inträffat mha den kombination på LED:sen som jag sätter på raden innan (kan såklart visas på andra sätt men detta var det snabbaste att implementera).
Användarvisningsbild
AndLi
Inlägg: 18282
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av AndLi »

Du kör alltså inte 8N1 som väl får ses som standard idag?
Då har du ingen paritet att kolla!

Jag skyller på 4 veckors semester, men normalt är väll inte interupten enablade i interruptfunktionen ? Så while(1) bör som önskat låsa hela uc.
mmarks
Inlägg: 46
Blev medlem: 4 februari 2012, 16:00:14

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av mmarks »

@AndLi: Jag får skylla på att jag gick upp för tidigt idag då ;-) i Atmega16 är interrupts "enablade" även när ett interrupt körs men de kan enbart avbryta pågående interrupt om de har högre prioritet (det är ett tag sen jag läste ordentligt i manualen om detta och provade men jag har för mig att det var detta jag kom fram till), jag har prövat att "tvinga" koden att köra dessa rader och det låser uc:n som väntat.

Från början körde jag 8N1 men ändrade detta när jag misstänkte att det kunde vara parity bit error men eftersom detta inte var fallet så kan jag ju ta bort detta igen, jag uppdaterar koden i första inlägget också så att den är uppdaterad.
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av snigelen »

i Atmega16 är interrupts "enablade" även när ett interrupt körs men de kan enbart avbryta pågående interrupt om de har högre prioritet
Nej det är de inte. Interrupt slås alltid av när en avbrottsrutin exekveras och slås sedan på igen med den avslutande reti-instruktionen som kompilatorn stoppar in sist i ISR:en.
mmarks
Inlägg: 46
Blev medlem: 4 februari 2012, 16:00:14

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av mmarks »

Tack snigelen då är det utrett.
Faktum kvarstår att python alltid väntar på svar innan ett nytt kommando skickas så oavsett hur interrupts hanteras så är detta inte en aktuell felkälla eftersom det aldrig kan ske en ny sändning innan atmegan är redo att ta emot den.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av sodjan »

> Från början körde jag 8N1 men ändrade detta när jag misstänkte att det kunde vara parity bit error

Om du kör "8 bit No parity 1 stop bit" (d.v.s "8N1") så kan det inte bli något "partity bit error",
du har inte någon "parity bit" över huvudtaget som kan bli fel...
mmarks
Inlägg: 46
Blev medlem: 4 februari 2012, 16:00:14

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av mmarks »

Det jag menar är att själva felet som ett parity bit error visar på, dvs att någon bit inte har kommit fram som den skickades fortfarande kan inträffa även om koden inte kollar efter det genom att skicka med en parity bit. Eller är det så att detta fel på något magiskt sätt aldrig kan inträffa om man inte kollar efter det?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46976
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av TomasL »

I :default använder du en oinitierad variabel, dvs "index"
Börja med att initiera den.
hur ser din enum ut, tänker nu på switchen
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av sodjan »

> Eller är det så att detta fel på något magiskt sätt aldrig kan inträffa om man inte kollar efter det?

Du kan så klart inte få "parity bit error" ifall du inte ens har någon "parity bit"!
Du måste också ändra i båda ändarna till t.ex 7Y1, men det kanske du gjorde...
Men visst, som en test för att se om man har bit-fel kan det ju fungera. :-)

Några andra saker...
Får du samma spontana fenomen med kablen till PC'n urkopplad?
Finns det något mönster tidsmässigt i hur fenomenet uppstår?

Jag kan inte hitta "while(1)" i koden, är det ändrat?
Sen så är det kanske renare att sätta en flagga i ISR'en som
sedan triggar en låsning i main()...
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46976
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av TomasL »

Kan du ge exempel på data som skickas.
mmarks
Inlägg: 46
Blev medlem: 4 februari 2012, 16:00:14

Re: ATmega16, C-kod som beter sig slumpmässigt (i mina ögon)

Inlägg av mmarks »

@TomasL, med enum gissar jag att du menar det som läses av till received_byte? Data som skickas är först en bokstav 'a' - 'f', denna avgör vilket index som nästkommande sändning ska sparas till förutom då ett 'f' skickas, då uppdateras variabeln displayed_channel. Det som skickas sen är en 8-bitars int, dvs 0-255. I python använder jag mig av modulen pySerial där jag initierar COMporten med följande:

Kod: Markera allt

ser = serial.Serial(usbport, 250000, timeout=1)
där usbport är den port som används, 250000 är baudrate och timeout=1 är hur länge skriv- och läsanrop får blocka.
Någonstans läste jag att default är 8-bitars kommunikation för pySerial men hittar det inte nu, jag har prövat att ha med det i initieringen (dvs, bytesize=serial.EIGHTBITS) och märker ingen skillnad.
för att skicka en bokstav alt siffra använder jag sedan t ex:

Kod: Markera allt

ser.write('a')
ser.write(chr(255))
@sodjan, okej det jag menar med parity bit error är det du kallar för bit-fel så jag hade kanske kunnat uttrycka mig annorlunda för att vara tydligare. Att ändra i båda ändarna, då gissar jag att du menar både i atmegan och i python vilket jag gjorde.
Jag kan tyvärr inte testa om felet fortfarande uppstår med kabeln till PC:n utdragen eftersom jag inte har tillgång till sakerna på en vecka nu (jag är mitt i en flytt)
Vad gäller att reproducera felet så verkar det uppstå helt sporadiskt när jag skickar data kontinuerligt (kom dock ihåg att python alltid väntar på svar innan mer data skickas), jag kan inte hitta något som helst mönster vilket gör mig otroligt frustrerad :?
Vad gäller while(1){} så ja, det är borttaget eftersom det inte tillförde något annat än att göra koden mer svårförstådd. Jag håller helt med dig om att det är bättre att sätta en flagga som sedan triggar en låsning i main(), att gör det i ISR:en var min "quick'n dirty fix" för att se om det skulle hända något.
Skriv svar