Hallo,
kann mir jemand weiterhelfen?
Ich versuche auf dem Attiny84 ein PWM-Signal mit einstellbarer Frequenz
zu erzeugen.
Dazu benutze ich den 8-bit Timer der über Timer Interrupts beim Compare
Register A einen Port anschaltet und beim Compare Register B wieder aus.
Zusätzlich wird dann noch der Timer zurückgesetzt.
1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 |
|
4 | int main(void)
|
5 | {
|
6 | DDRA=0xFF;
|
7 | sei();//enable global interrupts
|
8 | TIMSK0|=(1<<OCIE0A);//enable OCR0A interrupt
|
9 | TIMSK0|=(1<<OCIE0B);//enable OCR0A interrupt
|
10 | //TCCR0B|=(1<<CS00);//no prescaler
|
11 | TCCR0B|=(1<<CS01);//prescaler 8
|
12 | OCR0A=50;//offtime
|
13 | OCR0B=200;//ontime+offtime
|
14 |
|
15 | while (1)
|
16 | {
|
17 | }
|
18 |
|
19 | }
|
20 |
|
21 | ISR(TIM0_COMPA_vect)//compare register A interrupt
|
22 | {
|
23 | PORTA=0xFF;//turn on Port A
|
24 | }
|
25 |
|
26 | ISR(TIM0_COMPB_vect)//compare register A interrupt
|
27 | {
|
28 | PORTA=0x00;//Turn off Port A
|
29 | TCNT0=0;//reset Timer 1
|
30 | }
|
Das funktioniert auch ohne Probleme, jedoch reicht für meine Anwendung
die Auflösung nicht, weshalb ich jetzt versuche das ganze über den
16-Bit Timer zu realisieren. Dazu verwende ich einen ähnlichen Code mit
angepassten Registern.
1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 |
|
4 | int main(void)
|
5 | {
|
6 |
|
7 | DDRA=0xFF;//Port A output
|
8 |
|
9 | OCR1AL=0xFF;//offtime low bit
|
10 | OCR1AH=0x01;//offtime high bit
|
11 |
|
12 | OCR1BL=0xFF;//ontime+offtime low bit
|
13 | OCR1BH=0xFF;//ontime+offtime high bit
|
14 |
|
15 | //TCCR1B|=(1<<CS10);//no prescaler
|
16 | TCCR1B|=(1<<CS11);//prescaler 8
|
17 |
|
18 | TIMSK1|=(1<<OCIE1A);//enable OCR1A interrupt
|
19 | TIMSK1|=(1<<OCIE1B);//enable OCR1B interrupt
|
20 |
|
21 | sei();//enable global interrupts
|
22 |
|
23 | while (1)//wait
|
24 | {
|
25 | }
|
26 |
|
27 | }
|
28 |
|
29 | ISR(TIM1_COMPA_vect)//compare register A interrupt
|
30 | {
|
31 | PORTA=0xFF;//turn Port A on
|
32 | }
|
33 |
|
34 | ISR(TIM1_COMPB_vect)//compare register B interrupt
|
35 | {
|
36 | PORTA=0x00;//turn Port A off
|
37 | cli();//disable global interrupts just to be sure
|
38 | TCNT1L=0;//reset counter1 low bit
|
39 | TCNT1H=0;//reset counter1 high bit
|
40 | sei();//enable global interrupts just to be sure
|
41 | }
|
Dieser Code funktioniert allerdings nicht. Egal welche Werte ich
einstelle bekomme ich immer etwa 50% PWM.
Ich vermutete das Problem bei den 16-Bit Vergleichsregistern also lies
ich mir deren Werte über LEDs ausgeben.
Es scheint, als würden die High Register nicht funktionieren. OCR1AH ist
immer 0 und OCR1BH ist immer 0b01000011 egal welchen Wert ich in die
Vergleichsregister schreibe. Die Interrupts werden natürlich auch zum
falschen Zeitpunkt ausgelöst.
Liebe Grüße und Danke schonmal im Voraus,
Max