Zegar na wyświetlaczach 7-segmentowych - Obsługa Timera
Ustawiłeś preskaler na 256 - OK
Ustawiłeś tryb CTC (mode 4) dla OCR1A -OK
Włączyłeś przerwania od porównania OCR1B, a powinieneś włączyć od OCR1A.
Patrz tabelka ustawiania trybów: Table 47. Waveform Generation Mode Bit Description
oraz: Figure 40. 16-bit Timer/Counter Block Diagram
Z tego samego powodu wektor przerwania ma być od porównania A a nie B.
--------
Dlaczego ustawiasz wartość początkową licznika na 31250?
Z tego wynika, że niestety nie rozumiesz trybu CTC.
W tym trybie licznik ma liczyć od zera w górę.
Dochodząc do momentu w którym licznik zrówna się z OCR1A, nastąpi jego wyzerowanie i wygenerowanie przerwania.
Zamiast tego w przerwaniu ustawiasz wartość licznika, który właśnie się wyzerował i zgłosił przerwanie.
Ustawiłeś tryb CTC (mode 4) dla OCR1A -OK
Włączyłeś przerwania od porównania OCR1B, a powinieneś włączyć od OCR1A.
Patrz tabelka ustawiania trybów: Table 47. Waveform Generation Mode Bit Description
oraz: Figure 40. 16-bit Timer/Counter Block Diagram
Z tego samego powodu wektor przerwania ma być od porównania A a nie B.
--------
Dlaczego ustawiasz wartość początkową licznika na 31250?
Z tego wynika, że niestety nie rozumiesz trybu CTC.
W tym trybie licznik ma liczyć od zera w górę.
Dochodząc do momentu w którym licznik zrówna się z OCR1A, nastąpi jego wyzerowanie i wygenerowanie przerwania.
Czyli OCR1A musi mieć wartość przy której ma to nastąpić. A u Ciebie jest ciągle wartość domyślna, wynikająca z ustawienia bitów w tym rejestrze podczas włączenia mikrokontrolera.In CTC mode the counter is cleared to zero when
the counter value (TCNT1) matches either the OCR1A (WGM13:0 = 4) or the ICR1 (WGM13:0 = 12). The OCR1A or ICR1 define the top value for the counter, hence also its resolution.
Zamiast tego w przerwaniu ustawiasz wartość licznika, który właśnie się wyzerował i zgłosił przerwanie.
Kod: Zaznacz cały
#include <avr/io.h>
#define F_CPU 8000000
#include <util/delay.h>
#include<avr/interrupt.h>
#define A (1<<PA0)
#define B (1<<PA1)
#define C (1<<PA2)
#define D (1<<PA3)
#define E (1<<PA4)
#define F (1<<PA5)
#define G (1<<PA6)
#define DP (1<<PA7)
#define timer_start 200
volatile uint8_t cnt=0;
volatile char flaga;
volatile int wysw, godz=0, min=0;
volatile unsigned char liczba_LED[10] = {A|B|C|D|E|F, E|F, D|E|G|B|A, D|E|G|F|A, C|G|E|F, D|C|G|F|A, D|C|B|A|F|G, D|E|F, A|B|C|D|E|F|G, C|D|E|G|F|A};
ISR (TIMER1_COMPA_vect)
{
//TCNT1 = 65223;
TCNT1 = 31250;
cnt++;
switch(wysw)
{
case 0:
PORTD &= ~(1<<4);
PORTD |= (1<<5); //wlacz wyswietlacz drugi
PORTA = liczba_LED[min]; //liczba na wyswietlacz +
min++;
wysw++;
break;
case 1:
PORTD &= ~(1<<5); //wlacz wyswietlacz pierwszy
PORTD |= (1<<4);
PORTA = liczba_LED[godz]; // zapal segmenty dla odpowiednij liczby
wysw = 0;
break;
default:
break;
}
cnt=0;
if(min>9)
{
min=0;
godz++;
if(godz>5)
{
godz=0;
min=0;
}
}
}
int main(void)
{
//ustaw kierunki transmisji
DDRD |= (1<<4) | (1<<5);
DDRA = 0xFF;
//TIMSK |= (1<<TOIE1); // zezwolenie na przerwania od przepelnienia
//TCCR1B |= (1<<CS02); // preskaler 256
//TCNT1 = 65223; // 65536 - 31250 = 34286
TIMSK |= (1<<OCIE1A); // zezwolenie na przerwanie od porownania
TCCR1B |= (1<<WGM12); // tryb CTC Timer1
TCCR1B |= (1<<CS12); // prescaler 256
sei();
while(1);
return 0;
}
Nie rozumiem tylko dlaczego w TIMSK ustawiam przerwania od "trybu" A a prescaler i tryb CTC ustawiam w "trybie" B ?? Czemu to jest takie zagmatwane? no chyba że to jest źle i powinno byc TCCR1A, ale w tym rejestrze nie można ustawić prescalera...
OK, co dalej?
Czyli muszę ustawić na sztywno OCR1A = 31250, a TCNT1 inkrementować ??OCR1A ustawiam w main tak? a co z TCNT1? czy wystarczy że w obsłudze przerwania będzie tylko cnt++ ?
Wklejam kod:
Wklejam kod:
Kod: Zaznacz cały
#include <avr/io.h>
//#define F_CPU 8000000
#include <util/delay.h>
#include<avr/interrupt.h>
#define A (1<<PA0)
#define B (1<<PA1)
#define C (1<<PA2)
#define D (1<<PA3)
#define E (1<<PA4)
#define F (1<<PA5)
#define G (1<<PA6)
#define DP (1<<PA7)
#define timer_start 200
volatile uint8_t cnt=0;
volatile char flaga;
volatile int wysw, godz=0, min=0;
volatile unsigned char liczba_LED[10] = {A|B|C|D|E|F, E|F, D|E|G|B|A, D|E|G|F|A, C|G|E|F, D|C|G|F|A, D|C|B|A|F|G, D|E|F, A|B|C|D|E|F|G, C|D|E|G|F|A};
ISR (TIMER1_COMPA_vect)
{
//TCNT1 = 65223;
//TCNT1 = 31250;
//cnt++;
switch(wysw)
{
case 0:
PORTD &= ~(1<<4);
PORTD |= (1<<5); //wlacz wyswietlacz drugi
PORTA = liczba_LED[min]; //liczba na wyswietlacz +
min++;
wysw++;
break;
case 1:
PORTD &= ~(1<<5); //wlacz wyswietlacz pierwszy
PORTD |= (1<<4);
PORTA = liczba_LED[godz]; // zapal segmenty dla odpowiednij liczby
wysw = 0;
break;
default:
break;
}
if(min>9)
{
min=0;
godz++;
if(godz>5)
{
godz=0;
min=0;
}
}
//cnt=0;
}
int main(void)
{
//ustaw kierunki transmisji
DDRD |= (1<<4) | (1<<5);
DDRA = 0xFF;
//TIMSK |= (1<<TOIE1); // zezwolenie na przerwania od przepelnienia
//TCCR1B |= (1<<CS02); // preskaler 256
//TCNT1 = 65223; // 65536 - 31250 = 34286
TIMSK |= (1<<OCIE1A); // zezwolenie na przerwanie od porownania
TCCR1B |= (1<<WGM12); // tryb CTC Timer1
TCCR1B |= (1<<CS12); // prescaler 256
OCR1A = 31250;
sei();
while(1);
return 0;
}