Forum: Mikrocontroller und Digitale Elektronik Attiny44 Timer funktioniert nicht ?


von Dennis G. (dennis9819)


Lesenswert?

Guten Tag,
ich habe gestern einen Hüllkurverngenerator für einen ATMEGA2560 
geschrieben, der wie erwünscht funktioniert. Jetzt möchte ich diesen auf 
einen ATTiny44 sortieren, was aber nicht wirklich funktioniert.
Es scheint so als ob die ISR Vom Compare-Match des TIMER0 nicht 
aufgerufen wird.
Ich sitze jetzt schon länger dran und finde den Fehler nicht.
Hier mein nicht ganz so schöner Code :
1
#include <stdio.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
6
const int ADP_A = 0x01;
7
const int ADP_D = 0x02;
8
const int ADP_S = 0x03;
9
const int ADP_R = 0x04;
10
const double FCPU = 8000000;
11
const double TMINT = 0.0;
12
const float CALC_SEC = 1.5625;
13
const float CALC_PER = 0.09765625;
14
15
int pot_attack = 0;
16
int pot_decay = 0;
17
int pot_sustain = 0;
18
int pot_release = 0;
19
20
double t_attack = 0;
21
double t_decay = 0;
22
double t_release = 0;
23
double l_sustain = 0;
24
25
float c_attack = 0;
26
float c_decay = 0;
27
float c_release = 0;
28
29
int h_status = 0;
30
double h_output = 0;
31
32
int h_gate = 0;
33
34
void h_tick(){
35
    switch(h_status){
36
        case 0:
37
            h_output += c_attack;
38
            if(h_output >= 100){
39
                h_output = 100;
40
                h_status++;
41
            }
42
            break;
43
        case 1:
44
            h_output -= c_decay;
45
            if(h_output <= l_sustain){
46
                h_output = l_sustain;
47
                h_status++;
48
            }
49
            break;
50
            
51
        case 3:
52
            h_output -= c_release;
53
            if(h_output <= 0){
54
                h_output = 0;
55
                h_status++;
56
            }
57
            break;
58
    }
59
}
60
ISR(TIMER0_COMPA_vect){
61
    PORTA|= (1<<PA7);
62
    pot_attack  = IO_GETADC(ADP_A);
63
    pot_decay   = IO_GETADC(ADP_D);
64
    pot_sustain = IO_GETADC(ADP_S);
65
    pot_release = IO_GETADC(ADP_R);
66
    
67
    t_attack = (pot_attack/4) * CALC_SEC;
68
    t_decay = (pot_decay/4) * CALC_SEC;
69
    t_release = (pot_release/4) * CALC_SEC;
70
    l_sustain = (pot_sustain) * CALC_PER;
71
    
72
    c_attack = 100 / t_attack;
73
    c_decay = (100-l_sustain) / t_decay;
74
    c_release = l_sustain / t_release;
75
    
76
    if(PINB & (1<<PB1)) {
77
        h_gate = 0;
78
    }else{
79
        if(h_gate == 0){
80
            h_gate = 1;
81
            h_status = 0;
82
        }
83
    }
84
    if((!h_gate)&&(h_status < 3)){h_status = 3;}
85
    
86
    h_tick();
87
    
88
    OCR1A = (h_output*2.55);
89
    
90
   
91
}
92
93
void IO_INITTIMER(){
94
    TCCR0A = 0;
95
    TCCR0B = 0;
96
    OCR0A = 156; //ca 10ms
97
    
98
    TCCR0B |= (1 << WGM12);
99
    
100
    TCCR0B |= (1 << WGM02);
101
    
102
    TCCR0B |= (1 << CS00);
103
    TCCR0B |= (1 << CS02);
104
    
105
    
106
    TIMSK0 = (1<<OCIE0A);
107
    
108
    DDRA=(1<<PA6)|(1<<PA7);
109
    ICR1 = 255;
110
    TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
111
    TCCR1B = (1<<WGM13)|(1<<WGM12) | (1<<CS10);
112
    
113
}
114
void IO_INITPIN(){
115
    DDRB = 0x00;
116
117
    
118
}
119
void IO_INITADC(){
120
    ADMUX = 0x00;
121
    ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
122
    ADCSRA |= (1<<ADEN);
123
    
124
    ADCSRA |= (1<<ADSC);
125
    while (ADCSRA & (1<<ADSC) ) {
126
    }
127
    int DUM = ADCL + (ADCH<<8);
128
}
129
130
int IO_GETADC(int PIN){
131
    int ADPIN = PIN & 0x1F;
132
    ADMUX &= 0b11100000;
133
    ADMUX |= ADPIN;
134
    ADCSRA |= (1<<ADSC);
135
    while (ADCSRA & (1<<ADSC) ) {
136
    }
137
    return ADCL + (ADCH<<8);
138
}
139
140
int main(void) {
141
    cli();
142
    IO_INITPIN();
143
    IO_INITADC();
144
    IO_INITTIMER();
145
    sei();
146
    
147
    while(1){
148
        
149
    }
150
    
151
    
152
    return 0;
153
}

von Walter S. (avatar)


Lesenswert?

Dennis G. schrieb:
> Es scheint so als ob die ISR Vom Compare-Match des TIMER0 nicht
> aufgerufen wird.

scheinen hilft nicht weiter, prüf es nach

von S. Landolt (Gast)


Lesenswert?

> ISR(TIMER0_COMPA_vect)
Vielleicht mal mit TIM0_COMP_vect versuchen; zumindest im Datenblatt 
steht "10  0x0009  TIM0_COMPA  Timer/Counter0  Compare Match A".

von Erwin D. (Gast)


Lesenswert?

Dennis G. schrieb:
> Es scheint so als ob die ISR Vom Compare-Match des TIMER0 nicht
> aufgerufen wird.

Kuck doch mal, ob der Name der ISR stimmt. Ich hab gerade keine 
Unterlagen zur Hand, aber bei den AVR's ist das manchmal so, daß z.B.
ISR(TIMER0_COMPA_vect) bei anderen Prozessortypen dann
ISR(TIM0_COMPA_vect) heißen (oder so ähnlich). Schau mal die 
Definitionen an.

von S. Landolt (Gast)


Lesenswert?

Ja eben, TIM0_COMPA_vect meinte ich.

von Karl M. (Gast)


Lesenswert?

Hallo,

Wie erreicht man double auf einen Atmel AVR?

Das hat meines Wissens doch nur der Keil C Compiler.

von Karl M. (Gast)


Lesenswert?

Ob das immer funktioniert ?

int DUM = ADCL + (ADCH<<8);

von Stefan E. (sternst)


Lesenswert?

> TCCR0B |= (1 << WGM12);

???

von Walter S. (avatar)


Lesenswert?

Karl M. schrieb:
> Wie erreicht man double auf einen Atmel AVR?
>
> Das hat meines Wissens doch nur der Keil C Compiler.

der gcc auch, ist nur leider das gleiche wie float

von Karl M. (Gast)


Lesenswert?

Walter S. schrieb:
> Karl M. schrieb:
>> Wie erreicht man double auf einen Atmel AVR?
>>
>> Das hat meines Wissens doch nur der Keil C Compiler.
>
> der gcc auch, ist nur leider das gleiche wie float

Danke, ja das weis ich, die frage ist nur, ober der TE das wusste.

von Dennis G. (dennis9819)


Lesenswert?

S. Landolt schrieb:
> Vielleicht mal mit TIM0_COMP_vect versuchen; zumindest im Datenblatt
> steht "10  0x0009  TIM0_COMPA  Timer/Counter0  Compare Match A".

Danke. Jetzt geht zumindest die ISR.
PWM geht aber leider immer noch nicht. Ist da auch was groß anders im 
Gegensatz zum MEGA2560 ?

Karl M. schrieb:
> int DUM = ADCL + (ADCH<<8);

Bis jetzt schon. Hat noch keine Probleme damit.

Karl M. schrieb:
> Hallo,
>
> Wie erreicht man double auf einen Atmel AVR?
>
> Das hat meines Wissens doch nur der Keil C Compiler.

Wird meines Wissens nach vom avr-gcc genauso wie float behandelt. 
(32-bit)

von Peter II (Gast)


Lesenswert?

Dennis G. schrieb:
> Karl M. schrieb:
>> int DUM = ADCL + (ADCH<<8);
>
> Bis jetzt schon. Hat noch keine Probleme damit.

ist aber nicht sauber. Die Reihenfolge wie ADCL und ADCH ist nicht 
definiert. Das braucht man aber zum richtigen auslesen.

es geht eh viel einfacher:
1
int DUM = ADCLW;

oder noch kürzer:
1
ADCLW;

von S. Landolt (Gast)


Lesenswert?

>PWM geht aber leider immer noch nicht.
>    TCCR0B |= (1 << WGM12);
>    TCCR0B |= (1 << WGM02);
Also bei mir steht im Datenblatt
1
"Mode WGM02 WGM01 WGM00"
2
"4      1     0     0    Reserved"
WGM12 und WGM02 haben dieselbe Bitnummer.

von Erwin D. (Gast)


Lesenswert?

S. Landolt schrieb:
> WGM12 und WGM02 haben dieselbe Bitnummer.

Der Tiny44 hat kein WGM12.

von Erwin D. (Gast)


Lesenswert?

Erwin D. schrieb:
> S. Landolt schrieb:
>> WGM12 und WGM02 haben dieselbe Bitnummer.
>
> Der Tiny44 hat kein WGM12.

Dazu kommt noch, daß WGM1 und WGM0 im TCCR0A liegen und WGM2 im TCCR0B.

von S. Landolt (Gast)


Lesenswert?

> Der Tiny44 hat kein WGM12.
Wirklich? Ich finde WGM12 unter "12.11.2 TCCR1B – Timer/Counter1 
Control Register B" (8183F–AVR–06/12).

von Erwin D. (Gast)


Lesenswert?

S. Landolt schrieb:
>> Der Tiny44 hat kein WGM12.
> Wirklich? Ich finde WGM12 unter "12.11.2 TCCR1B – Timer/Counter1
> Control Register B" (8183F–AVR–06/12).

Timer0! Du bist jetzt bei Timer1 :-)

von S. Landolt (Gast)


Lesenswert?

Schon klar, ist trotzdem dieselbe Bitnummer.

von Erwin D. (Gast)


Lesenswert?

S. Landolt schrieb:
> Schon klar, ist trotzdem dieselbe Bitnummer.

Stimmt, macht aber nichts, weil zweimal der gleiche Wert zugewiesen 
wird. Die Zeile mit WGM12 ist nur überflüssig.

von S. Landolt (Gast)


Lesenswert?

> zweimal der gleiche Wert zugewiesen
Genau, und deshalb ist zu vermuten, dass Dennis sich da irgendwo 
verschrieben hat, schließlich wollte er ja eine PWM.

von Erwin D. (Gast)


Lesenswert?

Was ich mich gerade frage, woher kommt das WGM12? Vom 2560 kann es nicht 
kommen, dessen Timer hat auch nur WGM0, 1 und 2.

@Dennis: Du mußt dir mal beide Datenblätter nehmen (2560 und t44) und 
die Register der Timer miteinander vergleichen. Irgendwas hast du da 
verwechselt.

von Dennis G. (dennis9819)


Angehängte Dateien:

Lesenswert?

So jetzt läuft. Vielen Dank!

Erstmal vielen Dank für eure Hilfe!

Folgendes habe ich gemacht:
- Die Waveform Generation Mode Bits vom Timer0 richtig gesetzt. (habe 
sehr lange gebraucht um das heraus zu finden.
- Den Takt vom Timer0 angepasst
- Interrupt Vektor berichtigt
- Den Takt vom AD Wandler angepasst

Ich lade mal den neuen funktionierenden Code hoch und eine 
Bildschrimaufname vom Oszilloskop.

Nochmals vielen dank für eure Hilfe.
Einen schönen Abend!

von Erwin D. (Gast)


Lesenswert?

Dennis G. schrieb:
> So jetzt läuft. Vielen Dank!

Danke für die positive Rückmeldung.
Glückwunsch, schönen Abend!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.