Sida 1 av 1
Programmeringsbekymmer, nu i C
Postat: 1 november 2005, 21:07:52
av PaNiC
I förra veckan skrev jag mina första rader C. Jag har lyckats med lite småsaker, exempelvis att blinka lite leds, räkna upp och ner, räkna med nixierör osv. Nu har det kommit till interrupts. Problemet här är att Timer1 overflow-interruptet aldrig tycks trigga. Eller i vart fall så fastnar något innan värdena hinner komma ut på PORTA-C.
Kod: Markera allt
#include "avr/io.h"
#include "inttypes.h"
#include "avr/interrupt.h"
#include "avr/signal.h"
#include "string.h"
#include "stdio.h"
#define clock = 2000000
unsigned char secs = 0;
unsigned char tsecs = 0;
unsigned char mins = 0;
unsigned char tmins = 0;
unsigned char hrs = 0;
unsigned char thrs = 0;
void delay1()
{
unsigned char delayvar1;
delayvar1 = 255;
while(delayvar1 != 0)
{
delayvar1--;
}
}
void setup()
{
DDRA = 0xFF;
DDRB = 0xFF;
DDRC = 0xFF;
DDRD = 0b00011000;
//OCR1A = 31250;
TCCR1A = (3<<CS10); //(CK/64)
//TCCR1B = (1<<CTC1);
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
TIMSK = (1<<TOIE1);
sei();
}
SIGNAL(SIG_OVERFLOW1)
{
secs++;
if ((secs == 10))
{
secs = 0;
tsecs++;
}
if ((tsecs == 6))
{
tsecs = 0;
mins++;
}
if ((mins == 10))
{
mins = 0;
tmins++;
}
if ((tmins == 6))
{
tmins = 0;
hrs++;
}
if ((hrs == 10))
{
hrs = 0;
thrs++;
}
if ((thrs == 2)&&(hrs == 4))
{
secs = 0;
tsecs = 0;
mins = 0;
tmins = 0;
hrs = 0;
thrs = 0;
}
PORTA = ((secs)|(tsecs<<4));
PORTB = ((mins)|(tmins<<4));
PORTC = ((hrs)|(thrs<<4));
delay1();
}
int main(void)
{
setup();
sei();
for(;;)
{
}
}
Använder WinAVR inpluggat i AVRStudio.
Postat: 1 november 2005, 21:58:43
av teodorl
OT:
Hur lär man sig detta..? Jag vill också!

Postat: 1 november 2005, 22:11:05
av sodjan
Som man lär sig allt annat, läser dokumentation, kollar (fungerande!) exempel, frågar på online forum, o.v.s o.s.v.
Personligen kan jag inte AVR-C, så jag kan nog inte vara till stor hjälp här.
Ett par mindre sakar bara (med bakgrund från PIC-assembler, men i alla fall...

)
- Behöver man inte "återställa" någon timer0-overflow-interrupt-flagga innan man avslutar interrupt rutinen ("SIG_OVERFLOW1") ? Eller läggs det till av compilatorn automatiskt ?
- Vad har du gjort för att debugga ?
- *Var* fastnar koden ?
- Anropas setup() alls ?
Postat: 1 november 2005, 22:12:21
av Icecap
Jag jobbar inte med AVR men generellt:
* Initialisering utförs vid att stoppa interrupts, rensa gamla interrupt-flaggor, tillåta interrupts och sist starta hårdvaran. Om man starter hårdvaran först kan den generera en interrupt innan den accepteras, det kan ge "roliga" effekter eller ingen effekt alls.
* En interruptrutin ska mycket ofta innehålla en funktion som berättar för hårdvaran som har genererat interrupten att den kan ta't lugnt fram till nästa gång. I PIC clearar man interruptflaggan t.ex.
Förklara för mig vad TUSAN en delay-rutin gör i en ISR? (ISR = Interrupt Service Rutin). Då en ISR ska köras igenom snabbast möjligt "får" sånt inte förekomma! (generellt synspunkt om ISR, specialfall finns).
Postat: 1 november 2005, 22:24:45
av sodjan
> Problemet här är att Timer1 overflow-interruptet aldrig tycks trigga.
"Tycks" ? Hur då "tycks" ?
Du måste vara *säker* på om den anropas eller inte.
Sätt in några hårdkodade värden istället för :
PORTA = ((secs)|(tsecs<<4));
PORTB = ((mins)|(tmins<<4));
PORTC = ((hrs)|(thrs<<4));
som t.ex :
PORTA = 0xFF;
PORTB = 0xFF;
PORTC = 0xFF;
då vet du om du kommer dit alls.
Eventuellt plocka bort all sek/min/tim beräkning...
Debuggning innebär att plocka bort (kommentera bort) kod
tills det fungerar, sedan lägga tillbaka mindre bitar tills
det lägger av igen. Å så fram och tillbaka tills du förstår vad
som är problemet...

Postat: 1 november 2005, 22:25:53
av exile
TCCR1A borde det inte vara TCCR1B ?
sodjan: AVRen rensar själv interupt flagan..
Postat: 1 november 2005, 22:39:48
av björn
Behöver man verkligen inte en clear interrupt? Jag har i den lilla interrupt kod jag gjort iallafall cli() när man kommer in i interrupten, men det är möjligt att det inte behövs.
Postat: 1 november 2005, 22:52:54
av PaNiC
We have a winner!
exile is the one.
Och gah, det borde jag verkligen ha sett. Jag kollade ju alla kontrollregister hur många gånger som helst. Stirrade väl mig blind som vanligt.
sodjan: Tycks var väl ett dåligt ordval. Jag var säker

.
I övrigt, Icecap och sodjan. AVR sköter det där själv, vilket gör mig glad att jag valde dem en gång i tiden

.
Delayrutinen blev kvar efter att jag i debuggningen ändrade till att kalla på interruptrutinen manuellt. Den ska mycket riktigt inte vara där.
teodorl: Jag rekommenderar iaf att börja med assembler så att du vet vad som händer på låg nivå. När du fått hyfsad kläm på det så kan du börja med något annat språk, fördelaktligen C.
Visst kan man börja med C också, men jag är iallafall sådan att om jag inte vet något om bakomliggande orsaker till att saker händer så begriper jag ingenting alls. Kan vara det som har gjort mig så dålig i matte.
Tack alla!
Edit:
http://panic.klippanlan.net/annat/CIMG0220.AVI
Postat: 1 november 2005, 22:53:11
av exile
Nej den rensar clerar globala interupt flagan själv och sätter den själv när den hoppar ur interuptet, det är därför man har en egen opcod för return när man hoppar tillbaka fråninterupt (reti som sätter flagan) ser du
Panic: Visst är stödet för GCC AVRstudet under bart

Postat: 1 november 2005, 22:59:15
av sodjan
Fint att det fungerar
När det gäller int flaggorna, och eftersom jag nämnde det först...
Det var inte *globala* interrupt flaggan jag tänkte på, utan den/de specifica flaggorna för de olika int källorna, t.ex "timer1 overflow". Jag antog att man får cleara den innan man gör "return from interrupt", annars anropas samma interrupt direkt igen.
Hur som helst, kompilatorn (eller AVR hårdvaran) kanske fixar det självt (om det behövs alls !)...
Postat: 1 november 2005, 23:04:23
av exile
När det gäller timer1 overflow flagan så "cleras" den mär man hoppar in i timer1 overflow interupten av AVRs hårdvara... och det är liknade för alla interupt.
Ex uart reciv interuptet "cleara" när man läser ut datan från uarten...
Postat: 1 november 2005, 23:05:49
av PaNiC
exile: Visst är det

. Det var först när jag fick höra talas om att det fanns stöd för C i AVRStudio som jag bestämde mig för att börja med C. Orkar verkligen inte hoppa mellan en massa olika jobbiga program.
sodjan: Vi pratar nog om lite skilda saker. En sak som jag vill minnas skiljer PIC och AVR är att PIC bara har en interruptflagga och sedan måste man själv ta reda på var interruptet kommer ifrån. AVR har många flaggor och kan hoppa direkt till rätt kodsnutt. Flaggorna clearas av hårdvaran, exakt när har jag inte riktigt koll på, men man behöver iallafall inte bry sig.
Postat: 2 november 2005, 07:41:47
av Icecap
Det lät ju smidigt faktisk med att den rensar flaggan själv och det är bra att den kör numera. Nu fattas det bara en DCF77-mottagare på med tillhörande dekodning, sen har du en stabil klocka!

Postat: 2 november 2005, 17:46:47
av PaNiC
Mja.. DCF77 har jag inte på denna klockan, som för övrigt är min nixieklocka som jag visade här för hur länge sedan som helst.
Den nyttjar en DS1302 istället.