Sida 1 av 2
Interruptproblem med Timer1 på ATMega168
Postat: 26 april 2009, 23:29:18
av Malm
Tänkte dra igång ett nytt elektronikprojekt och satte mig glatt vid datorn och började programmera. Tråkig nog tog det inte lång stund innan min skaparglädje förstördes av ett irriterande fel som jag av någon anledning inte kan avhjälpa själv.
Jag försöker implementera en funktion som orsakar ett avbrott en gång varje millisekund. Detta körs på en ATMega168 som arbetar med frekvensen 18,432 MHz. Så långt inga konstigheter.
Så här ser min kod ut:
Kod: Markera allt
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "../bits.h"
int main (void) {
// Sätt alla IO-portar till utgångar, logiknivå hög
DDRB = 0xFF;
DDRC = 0xFF;
DDRD = 0xFF;
PORTB = 0xFF;
PORTC = 0xFF;
PORTD = 0xFF;
// Väck logikanalysator
PORTC = 0x00;
_delay_ms(1);
PORTC= 0xFF;
// Ställ in TIMER1 för 1ms-interrupts
TCCR1B |= (1<<WGM12) | (1<<CS10);
TIMSK1 |= (1<<OCIE1A);
TCNT1 = 0;
OCR1A = 18432;
sei();
while(1) {
asm volatile("nop" "\n\t");
asm volatile("nop" "\n\t");
}
}
SIGNAL(TIMER1_COMPA_vect) {
PORTB = 0x00;
_delay_us(10);
PORTB = 0xFF;
}
Tyvärr ser det ut så här i logikanalysatorn:
Båda signalerna är periodiska med 2 ms.
Jag tycker inte att detta stämmer alls med vad jag bett processorn att göra, men troligtvis har jag missat något/tänkt fel. Frågan är bara vad.
Tack på förhand!
Re: Interruptproblem med Timer1 på ATMega168
Postat: 26 april 2009, 23:50:46
av bearing
Testa att sätta registrena ordentligt, alltså att inte lita på standardvärdena.
Kod: Markera allt
TCCR1A = 0;
TCCR1B = (1<<WGM12) | (1<<CS10);
TIMSK1 = (1<<OCIE1A);
Re: Interruptproblem med Timer1 på ATMega168
Postat: 26 april 2009, 23:55:56
av Malm
Det gör tyvärr ingen skillnad om jag sätter TCCR1A till noll

Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 00:09:06
av bearing
Observera att jag bytt |= till = på raderna under. Det finns visst ett -C register också.
Min teori var att timern hamnat i PWM-läge, och att den därför drev PB1/OC1A. Men om nollat -A register inte hjälpte så var det nog inte fallet.
Hur kommer det sig att PC4 rör sig?
Är du säker på att du flashar rätt hex-fil?
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 10:18:27
av Malm
Nu har jag testat att sätta både A, B och C utförligt, men det gör ingen skillnad.
Som du säkert ser i koden så används PORTC bara i initieringen av analysatorn, och i min värld borde det verkligen inte finnas en periodisk signal på PC4. Jag är helt säker på att jag flashar rätt fil och att mina ändringar kompileras till denna fil. Om jag exempelvis tar bort sei() så ser allt normalt ut, dvs. det kommer en 1 ms lång puls på PC4 och sedan händer inget mer.
Jag kan tillägga att processorn beter sig som förväntat de första 15 millisekunderna, men sedan ser det ut som i bilden ovan. Kan det vara delay-funktionerna som inte tycker om att bli kallade från interrupts? Kompilatoroptimering som spökar?
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 10:28:47
av SvenW
Vet inte, men möjligen är det watchdog-timer som spökar.
Pröva med att antingen stänga av den eller att sätta dit
wdt_reset() med jämna mellanrum.
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 10:36:14
av Malm
Antar att du menar instruktionen WDR? Watchdog är inte påslagen i fuses, men jag testade att stoppa in den instruktionen i koden utan resultat. Samma konstiga vågformer :/
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 10:46:20
av sodjan
> Jag kan tillägga att processorn beter sig som förväntat de första 15 millisekunderna,
Efter vadå ?
> Kan det vara delay-funktionerna som inte tycker om att bli kallade från interrupts?
Att ha delay funktioner i interruptkoden är ett "fel" i sig.
Designa om applikationen så att du inte behöver det.
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 10:54:23
av Malm
De första 15 sekunderna efter att processorn startat. Bifogar en bild över förloppet.

Vågformen efter de första 15 millisekunderna är, om man zoomar in, identisk med den jag visade i första inlägget.
Jag använder delayfunktionen för att skapa en puls på ett enkelt sätt. Det är bara en tillfällig grej för att verifiera att det verkligen sker ett avbrott. Har nu testat att slänga in ett gäng NOP istället och det gör ingen skillnad. Allting ser helt rätt ut i början, men sedan spårar det ur och vad jag gör i interruptrutinen verkar inte ha någon betydelse, det ser likadant ut efter 15 ms ändå.
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 10:57:26
av sodjan
> De första 15 sekunderna efter att processorn startat.
Både efter power-on och efter en soft-reset ?
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 11:01:56
av Malm
Nej, om jag bryter strömmen så fungerar det inte ens i 15 ms, då uppstår det konstiga beteendet så fort den har kommit igång. Enda gången jag får det att fungera är alltså omedelbart efter programmering.
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 11:16:07
av sodjan
> ...och efter en soft-reset ?
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 11:21:29
av sodjan
Jag skulle skriva om det utan delay och med invertering av PORTB i interruptrutinen.
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 13:26:32
av vfr
Mmm. Invertering av en signal är väldigt bra sätt att se om något händer. Det är då betydligt mindre risk att missa något p.g.a korta pulser. Oavsett så får man alltid minst ett omslag, som i sig är relativt synligt oberoende av hur ofta/sällan som det inträffar.
Re: Interruptproblem med Timer1 på ATMega168
Postat: 27 april 2009, 15:38:36
av Malm
Suck. Nu upptäckte jag att det av någon anledning saknades externt pullup-motstånd på RESET-pinnen

Ryckte det nog när jag rev förra uppkopplingen.
Med den lilla korrigeringen funkar allt. Den är känslig med det där, ATMegan
Tack för hjälpen hur som helst
