Sida 1 av 4
Interrupt fel, Krets: ATMega32, Språk: C
Postat: 19 januari 2006, 21:25:46
av Virr3
Tjenare. Jag har lite problem med min kod till en klocka.
Det hela byggs runt några 4094 om ni skulle undra. Kretsen som progameras är en ATMega32.
Jag får inga kompilerings fel, men ingenting händer när jag testar.
Så här ser koden ut:
Kod: Markera allt
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <avr/delay.h>
uint8_t Htio = 0;//Variabler som behövs
uint8_t Hen = 0;
uint8_t Mtio = 0;
uint8_t Men = 0;
uint8_t Stio = 0;
uint8_t Sen = 0;
void strobe(void);
void strobe(void)
{
DDRC = _BV(PA0);
PORTC |= _BV(PA0);
_delay_loop_1(10);
PORTC &= ~_BV(PA0);
}
void clock(void);
void clock(void)
{
DDRC = _BV(PA2);
PORTC |= _BV(PA2);
_delay_loop_1(10);
PORTC &= ~_BV(PA2);
}
void data_ok(void);
void data_ok(void)
{
DDRC = _BV(PA1);
PORTC |= _BV(PA1);
_delay_loop_1(10);
PORTC &= ~_BV(PA1);
}
void data_nej(void);
void data_nej(void)
{
_delay_loop_1(10);
}
void enable_on(void);
void enable_on(void)
{
DDRC = _BV(PA3);
PORTC |= _BV(PA3);
}
SIGNAL(SIG_OVERFLOW2)//interuppt triggas på owerflow
{
strobe();
clock();
enable_on();
Sen++;
if(Sen>10)
{
Sen=1;
Stio++;
}
else if(Stio==6)
{
Stio=0;
Men++;
}
else if(Men>10)
{
Men=0;
Mtio++;
}
else if(Mtio==6)
{
Mtio=0;
Hen++;
}
else if(Hen==10)
{
Hen=0;
Htio++;
}
else if(Htio==2){Htio=0;}
}
int main(void)
{
TCCR2 = 0x05; //Aktivera "Normal mode"
ASSR = 0x08 ; //Asynchronous Timer/Counter2 Enable
TIMSK = 0x80; //Timer/Counter2 Overflow Interrupt Enable
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
asm volatile("sei"); //enable interrupt
while(1)
{
for(a=0;a>9;a++)
{
if(Htio==a)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
}
{
for(b=0;b>9;b++)
{
f=0;
if(Hen==b)
{data_ok();}
else
{
data_nej();
clock();
}
}
}
{
for(c=0;c>9;c++)
{
if(Mtio==c)
{data_ok();}
else
{
data_nej();
clock();
}
}
}
{
for(d=0;d>9;d++)
{
if(Men==d){data_ok();}
else
{
data_nej();
clock();
}
}
}
{
for(e=0;e>9;e++)
{
if(Stio==e)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
}
{
for(f=0;f>9;f++)
{
if(Sen==f)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
}
}
}
Jag har kollat med oscilloskop på PA0,PA1,PA2,PA3. ungefär samma sak på alla.
Störst signal är de på PA0, Alltså Strobe, men det är absolut ingen stark signal, inte mer än några millivolt.
Det är inte heller några pulser utan det är mer ett brus.
har suttit och ändrat och ändrat, men nu har idéerna tagit slut, jag kan inte komma på vad som är fel.
Skulle uppskatta stort ifall någon berättade vad som var fel, och varför

Postat: 19 januari 2006, 21:46:53
av henkebenke
Du borde få kompileringsfel kan man tycka eftersom du har en massa onåbar kod. Din while-sats innehåller endast första for-loopen.
Sen kan man tillägga att funktionsprototyper raden innan deklarationen är meningslös. Man radar upp prototyperna först (lämpligtvis i en h-fil som man inkluderar) så att kompilatorn vet hur funktionen ser ut när den sedan anropas.
Dessutom har du block utanför dina for-loopar vilket bara gör att det ser rörigt ut, ta bort en nivå av {}-paranteser.
Postat: 19 januari 2006, 21:50:28
av speakman
Vad utvecklar du i? En god idé hade varit att simulera programmet (går i de flesta miljöer). Då ser du var koden går, och hur registrerna rör sig, osv. Breakpoints kan ju vara en bra idé också.
Mvh
speakman
Postat: 19 januari 2006, 22:20:02
av Virr3
Jag utvecklar de hela i Programmers notepad 2. d.v.s Winavr.
Om det går att simulera programmet där i så skulle jag bli mycket glad:)
Postat: 19 januari 2006, 22:57:32
av oJsan
Jag vet inte exakt vad du vill göra med programmet, men hela programstrukturen verkar väldigt ologiskt... Jag antar att du vill klocka ut pulser till skiftregistret men jag tror att det är fel på "tänket" när det gäller denna pryl... jag förstår i alla fall inte hur koden ska funka. men jag kanske är lite trött också! =)
Postat: 20 januari 2006, 00:00:06
av JJ
Virr3 skrev:Jag utvecklar de hela i Programmers notepad 2. d.v.s Winavr.
Om det går att simulera programmet där i så skulle jag bli mycket glad:)
Går det att simulera i AVR Studio?
Postat: 20 januari 2006, 00:11:16
av PaNiC
Jepp.
Postat: 20 januari 2006, 07:55:28
av Icecap
Kod: Markera allt
while(1)
{ // START MAIN-loop
for(a=0;a>9;a++)
{
if(Htio==a)
{
data_ok();
}
else
{
data_nej();
clock();
}
} // SLUT for(a=0;a>9;a++)
} // STOP MAIN-loop
{ // Hit kommer den aldrig...
for(b=0;b>9;b++)
{
f=0;
if(Hen==b)
{
data_ok();
}
else
{
data_nej();
clock();
..... // en del mer
Din main-loop kod kör alltså enbart ut en liten del av det samlade...
Sen tycker jag att det är konstigt att det lilla som kommer inte är digitala nivåer, belaster du för kraftigt eller har du glömt att sätta porten till ut?
Postat: 20 januari 2006, 12:59:02
av karlstedt
om du vill skippa inline asm så funkar ju även sei()

Postat: 20 januari 2006, 14:09:57
av Virr3
Har ändrat lite i koden nu. nu ser den ut såhär:
Kod: Markera allt
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <avr/delay.h>
uint8_t Htio = 0;//Variabler som behövs
uint8_t Hen = 0;
uint8_t Mtio = 0;
uint8_t Men = 0;
uint8_t Stio = 0;
uint8_t Sen = 0;
void strobe(void);
void strobe(void)
{
DDRA = _BV(PA0);
PORTA |= _BV(PA0);
_delay_loop_1(10);
PORTA &= ~_BV(PA0);
}
void clock(void);
void clock(void)
{
DDRA = _BV(PA2);
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
}
void data_ok(void);
void data_ok(void)
{
DDRA = _BV(PA1);
PORTA |= _BV(PA1);
_delay_loop_1(10);
PORTA &= ~_BV(PA1);
}
void data_nej(void);
void data_nej(void)
{
_delay_loop_1(10);
}
void enable_on(void);
void enable_on(void)
{
DDRA = _BV(PA3);
PORTA |= _BV(PA3);
}
SIGNAL(SIG_OVERFLOW2)//interuppt triggas på owerflow
{
enable_on();
strobe();
clock();
Sen++;
if(Sen>10)
{
Stio++;
Sen=1;
}
else if(Stio==6)
{
Men++;
Stio=0;
}
else if(Men>10)
{
Mtio++;
Men=0;
}
else if(Mtio==6)
{
Hen++;
Mtio=0;
}
else if(Hen==10)
{
Htio++;
Hen=0;
}
else if(Htio==2)
{
Htio=0;
}
}
int main(void)
{
TCCR2 = 0x05; //Aktivera "Normal mode"
ASSR = 0x08 ; //Asynchronous Timer/Counter2 Enable
TIMSK = 0x80; //Timer/Counter2 Overflow Interrupt Enable
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
uint8_t f;
asm volatile("sei"); //enable interrupt
while(1)
{
for(a=0;a>9;a++)
{
if(Htio==a)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
for(b=0;b>9;b++)
{
if(Hen==b)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
for(c=0;c>9;c++)
{
if(Mtio==c)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
for(d=0;d>9;d++)
{
if(Men==d)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
for(e=0;e>9;e++)
{
if(Stio==e)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
for(f=0;f>9;f++)
{
if(Sen==f)
{
data_ok();
}
else
{
data_nej();
clock();
}
}
}
}
Men, ingen större skilnad på utförandet...
Postat: 20 januari 2006, 14:36:52
av speakman
Då du ändå bara har utgångar, så ta bort alla DDRA-rader, och sätt DDRA = 0xFF i början av main() istället.
En vild gissning kan ju vara att den inte tycker om att sätta in/ut en klockcykel, och styra porten i nästa.
Samtliga portar som inte är inkopplade kan rekommenderas sättas som output.
Mvh
speakman
Postat: 23 januari 2006, 12:01:50
av oJsan
Bifoga ett kopplingsschema och en förklaring på hur allt SKA funka så blir det lättare för oss att felsöka vad som är fel...
Genom dina DDRA-rader så sätts en utgång i taget till utgång.. jag antar att alla pinnar ska ha samma riktning hela tiden och då är det bättre att bara sätta DDRA i början av programmet. Risken är mindre att man råkar skriva fel värden till DDRA och koden blir kompaktare och mer lättläst.
Postat: 23 januari 2006, 17:12:31
av Virr3
Okej, kopplingschema kommer här:
http://stuffnet.1go.dk/schema.png
Klistra in och klip ut i adressfältet ifall de inte funkar
Men i alla fall. Jag har läst i data bladet gång på gång, nu har jag hittat några rader om just den asynkrona timern. och på sida 216 här står det följande:
When Timer/Counter2 operates asynchronously, some considerations must be taken.
Warning: When switching between asynchronous and synchronous clocking of
Timer/Counter2, the Timer Registers TCNT2, OCR2, and TCCR2 might be
corrupted. A safe procedure for switching clock source is:
1. Disable the Timer/Counter2 interrupts by clearing OCIE2 and TOIE2.
2. Select clock source by setting AS2 as appropriate.
3. Write new values to TCNT2, OCR2, and TCCR2.
4. To switch to asynchronous operation: Wait for TCN2UB, OCR2UB, and
TCR2UB.
5. Clear the Timer/Counter2 Interrupt Flags.
6. Enable interrupts, if needed.
Så, nu har jag ändrat och ändrat, nu de sista har jag gjort såhär:
Kod: Markera allt
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <avr/delay.h>
uint8_t Htio = 0;//Variabler som behövs
uint8_t Hen = 0;
uint8_t Mtio = 0;
uint8_t Men = 0;
uint8_t Stio = 0;
uint8_t Sen = 0;
SIGNAL(SIG_OVERFLOW2)//interuppt triggas på owerflow
{
PORTA |= _BV(PA3);
PORTA |= _BV(PA0);
_delay_loop_1(10);
PORTA &= ~_BV(PA0);
Sen++;
if(Sen>10)
{
Stio++;
Sen=1;
}
else if(Stio==6)
{
Men++;
Stio=0;
}
else if(Men>10)
{
Mtio++;
Men=0;
}
else if(Mtio==6)
{
Hen++;
Mtio=0;
}
else if(Hen==10)
{
Htio++;
Hen=0;
}
else if(Htio==2)
{
Htio=0;
}
}
int main(void)
{
DDRA = 0xFF;
TIMSK = 0x00;
ASSR = _BV(AS2);
TCCR2 = _BV(CS20) | _BV(CS22);
TCNT2=0x00;
while(TCN2UB==0 |TCR2UB==0 )
{
TIFR = 0x00;
}
asm volatile("sei"); //enable interrupt
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
uint8_t f;
while(1)
{
for(a=0;a>9;a++)
{
if(Htio==a)
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
PORTA |= _BV(PA1);
_delay_loop_1(10);
PORTA &= ~_BV(PA1);
}
else
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
_delay_loop_1(10);
}
}
for(b=0;b>9;b++)
{
if(Hen==b)
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
PORTA |= _BV(PA1);
_delay_loop_1(10);
PORTA &= ~_BV(PA1);
}
else
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
_delay_loop_1(10);
}
}
for(c=0;c>9;c++)
{
if(Mtio==c)
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
PORTA |= _BV(PA1);
_delay_loop_1(10);
PORTA &= ~_BV(PA1);
}
else
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
_delay_loop_1(10);
}
}
for(d=0;d>9;d++)
{
if(Men==d)
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
PORTA |= _BV(PA1);
_delay_loop_1(10);
PORTA &= ~_BV(PA1);
}
else
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
_delay_loop_1(10);
}
}
for(e=0;e>9;e++)
{
if(Stio==e)
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
PORTA |= _BV(PA1);
_delay_loop_1(10);
PORTA &= ~_BV(PA1);
}
else
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
_delay_loop_1(10);
}
}
for(f=0;f>9;f++)
{
if(Sen==f)
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
PORTA |= _BV(PA1);
_delay_loop_1(10);
PORTA &= ~_BV(PA1);
}
else
{
PORTA |= _BV(PA2);
_delay_loop_1(10);
PORTA &= ~_BV(PA2);
_delay_loop_1(10);
}
}
}
}
Men fortfarande samma problem.
B1n4ry förklarade för mig ganska bra hur 4094 funkade i
detta inlägget.
Postat: 23 januari 2006, 18:41:26
av Icecap
Du har ett sista punkt i länken till schemat, ta bort det.
Du verkar sakna kondingar till klockkristallet, jag hade kopplat annolunda men det bör ju fungera rent elektrisk.
Du har ingen pull-down motstånder till dina tryckknappar, 2K2 - 10K borde duga fint.
Programmeringsfel däremot:
Kod: Markera allt
SIGNAL(SIG_OVERFLOW2)//interuppt triggas på overflow
{
PORTA |= _BV(PA3); // OK, den tror jag på
PORTA |= _BV(PA0); // Samma här
_delay_loop_1(10); // Öhhhh...delay i en interrupt???? Varför i all sin dar???
PORTA &= ~_BV(PA0); // Nåväl, någon anledning är det väl...
Sen++; // Räkna upp sekund-ental
if(Sen>10) // Det är ju en Nixie så minst 1 ska vara aktiv= OK
{
Stio++; // Räkna upp sekund-tiorna
Sen=1; // Nåja, det var en Nixie ju...fast de andra nollas ju...???
}
else if(Stio==6) // Nämen...ska vara if(Stio >= 6) OCH inget else!
{ // Originalt: kommer hit 1 sek för sent
Men++;
Stio=0;
}
else if(Men>10) // Same here: WHY 'else'????
{
Mtio++;
Men=0;
}
else if(Mtio==6) // och här...'else'...???
{
Hen++;
Mtio=0;
}
else if(Hen==10) // tjatigt men....'else'
{
Htio++;
Hen=0;
}
else if(Htio==2) // Har sagt det eller hur?? Jupp, 'else'...
{
Htio=0;
}
}
Mitt förslag till en enkel och välfungerande uppräkning:
Kod: Markera allt
SIGNAL(SIG_OVERFLOW2)//interuppt triggas på overflow
{
PORTA |= _BV(PA3); // OK, den tror jag på
PORTA |= _BV(PA0); // Samma här
_delay_loop_1(10); // Öhhhh...delay i en interrupt????
PORTA &= ~_BV(PA0); // Nåväl, någon anledning är det väl...
if(++Sen >= 10) // Räkna upp sekund-ental
{ // Hoppla, 10 eller mer
Sen = 0; // Nolla sekund-ental
if(++Stio >= 6) // Räkna upp sekund-tiorna
{ // Hoppla, sekund-tiotal är 6 eller mer
Stio = 0; // Nolla sekund-tiotal
if(++Men >= 10) // Räkna upp minut-ental
{ // Oj då, mer än 9 minuter på entalen
Men = 0; // Nolla minut-ental
if(++Mtio >= 6) // räkna upp minut-tiotal
{ // Jaha...overflow här med...
Mtio = 0; // Nolla den då...
if(++Hen >= 10) // Räkna upp timme-ental
{ // Ojsan, det är mer än 9 timmer på entalen...det går inte
Hen = 0; // Nolla timme-ental
if(++Htio >= 2) Htio = 0; // Räkna upp timme-tiotal, om mer än 2 ska den nollas
}
}
}
}
}
}
Postat: 23 januari 2006, 19:08:48
av matseng
Icecap skrev:Du har ingen pull-down motstånder till dina tryckknappar, 2K2 - 10K borde duga fint.
Ja, jag vet att man inte ska citera, med eftersom det är off-topic i den här tråden så gör jag det allfall.
Jo, pullmotstånd saknas, men i det stora hela har han ca 109 motstånd för mycket i schemat.
Hade han valt ett shiftreg med lite bättre drivförmåga än en i cmos-serien så hade han kunnat hoppa över alla basmotstånd genom att koppla emittrana till shiftregistret och alla basarna till ett gemensamt motstånd mot +5. (kräver dock att man invertera datat in i shiftregistret så att mnan har en 0'a för den siffra som ska vara tänd). Sen så man kan oxo använda bara ett enda anodmotstånd istället för tio separata katodmotstånd.
Fast tycker man om att borra och löda motstånd så är ju originalschemat bra..... :-)