Forum: Mikrocontroller und Digitale Elektronik "TCNT0" funktioniert nicht (AVR)


von Paul M. (antony-train)


Lesenswert?

moin,

ich brauche mal hilfe bei einem Problem:

Ich habe ein Programm geschrieben, dass ein PWM-Signal zum Steuern eines 
Servos ausgeben soll. Allerdings funktioniert das nicht. Zum überprüfen 
habe ich den Ausgang mal an einen schallwandler angeschlossen. Dadurch 
kann ich höhren, ob es sich verändert.

Ich habe das Gefühl, dass der Befehl "TCNT0 = 209" nicht funktioniert. 
Egal, wie ich ihn verändere bleibt das ausgegebene Signal gleich.

Ich habe das gleiche Programm auch in Assembler programmiert, mit dem es 
komischerweise geht.

Es wäre toll, wenn mir jemand helfen könnte.

Hier der Code:
1
//-----------------------------------------------------------------------------
2
// Title      : AVR C Grundgerüst für ATmega8
3
//-----------------------------------------------------------------------------
4
// Funktion   : ...
5
// Schaltung  : ...
6
//-----------------------------------------------------------------------------
7
// Prozessor  : ATmega8
8
// Takt       : 3,6864 MHz
9
// Sprache    : C
10
// Date       : ...
11
// Version    : ...
12
// Autor      : ...
13
//-----------------------------------------------------------------------------
14
#define F_CPU 3686400
15
#include <avr/io.h>
16
#include <avr/interrupt.h>
17
#include <inttypes.h>
18
//-----------------------------------------------------------------------------
19
int time = 0;
20
21
ISR(TIMER0_OVF_vect)
22
{
23
    time += 1;
24
25
    if (time == 15)
26
    {
27
      PORTB = 0x00;
28
    }
29
    else if (time == 200)
30
    {
31
      PORTB = 0xFF;
32
      TCNT0 = 209;
33
      time = 0;
34
    }
35
}
36
37
38
39
int main (void)
40
{
41
   DDRB = 0xFF;      //PortB = Ausgang
42
   DDRD = 0x00;      //PortD = Eingang
43
   PORTD = 0xFF;    //PortD = PullUp
44
   TCCR0 = 0b00000010;    //Vorteiler = 8bit
45
   TIMSK = 0b00000001;    //TC_0 Enable
46
   
47
   sei();      //interrupts zulassen
48
   
49
   while (true)          // Mainloop
50
   {
51
   }
52
return 0;
53
}
54
//-----------------------------------------------------------------------------


Und hier der assemblercode: (die Codes sind unabhängig voneinander 
entstanden und wurden nicht maschinell konvertiert)
1
;+-----------------------------------------------------------------------------
2
;| Title                            : Assembler Grundgerüst für ATmega8
3
;+-----------------------------------------------------------------------------
4
;| Funktion                         : ...
5
;| Schaltung                        : ...
6
;+-----------------------------------------------------------------------------
7
;| Prozessor                        : ATmega8
8
;| Takt                             : 3,6864 MHz
9
;| Sprache                          : Assembler
10
;| Datum                            : ...
11
;| Version                          : ...
12
;| Autor                            : ...
13
;+-----------------------------------------------------------------------------
14
.include        "AVR.H"
15
;------------------------------------------------------------------------------
16
begin:    rjmp  main      ;  RESET External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
17
    reti          ;  INT0 External Interrupt Request 0
18
    reti          ;  INT1 External Interrupt Request 1
19
    reti          ;  TIMER2 COMP Timer/Counter2 Compare Match
20
    reti          ;  TIMER2 OVF Timer/Counter2 Overflow
21
    reti          ;  TIMER1 CAPT Timer/Counter1 Capture Event
22
    reti          ;  TIMER1 COMPA Timer/Counter1 Compare Match A
23
    reti          ;  TIMER1 COMPB Timer/Counter1 Compare Match B
24
    reti          ;  TIMER1 OVF Timer/Counter1 Overflow
25
    rjmp  onTC0      ;  TIMER0 OVF Timer/Counter0 Overflow
26
    reti          ;  SPI, STC Serial Transfer Complete
27
    reti          ;  USART, RXC USART, Rx Complete
28
    reti          ;  USART, UDRE USART Data Register Empty
29
    reti          ;  USART, TXC USART, Tx Complete
30
    reti          ;  ADC ADC Conversion Complete
31
    reti          ;  EE_RDY EEPROM Ready
32
    reti          ;  ANA_COMP Analog Comparator
33
    reti          ;  TWI 2-wire Serial Interface
34
    reti          ;  SPM_RDY Store Program Memory Ready
35
;------------------------------------------------------------------------------
36
main:    ldi    r16,hi8(RAMEND)  ; Main program start
37
    out    SPH,r16      ; Set Stack Pointer to top of RAM
38
    ldi    r16,lo8(RAMEND)
39
    out    SPL,r16
40
41
    sbi    DDRB,0
42
    ldi    r16, 0b00000010
43
    out    TCCR0, r16
44
    ldi    r16, 0b00000001
45
    out    TIMSK, r16
46
    ldi    r16, 0
47
    sei      
48
;------------------------------------------------------------------------------
49
mainloop:  rjmp  mainloop
50
;------------------------------------------------------------------------------
51
onTC0:    inc    r16
52
    cpi    r16, 15
53
    breq  t15
54
    cpi    r16, 200
55
    breq  t200
56
ende:    ldi    r17, 209
57
    out    TCNT0, r17
58
    reti
59
60
t15:    ldi    r18, 0b00000000
61
    out    PORTB, r18
62
    rjmp  ende
63
64
t200:    ldi    r18, 0b00000001
65
    out    PORTB, r18
66
    ldi    r16, 0
67
    rjmp  ende

Vielen Dank

Antony Train

von Stefan E. (sternst)


Lesenswert?

> Ich habe das gleiche Programm auch in Assembler programmiert, mit dem es
> komischerweise geht.

ASM- und C-Code sind keinesfalls gleich. Im ASM-Code wird TCNT0 bei 
jedem Überlauf mit 209 vorgeladen, beim C-Code nur bei jedem 
zweihundersten.

von Paul M. (antony-train)


Lesenswert?

Vielen Dank!!!!!!!

Dass mir das nicht selbst aufgefallen ist.

Jetzt Funktioniert es!  :D

Danke!!!

von Flo (Gast)


Lesenswert?

Mach eine Servoansteuerung lieber über den Outputcompare-Interrupt, da 
du so eine feste Frequenz hast und nur das Puls-Pausen-Verhältnis über 
das OCR-REgister veränderst.

PS.: Falls du beim Overflow-Interrupt den Timer wieder mit einem Wert 
vorladen willst, sollte das ganz am Anfang des Interrupts geschehen, da 
sonst die unterschiedlichen Laufzeiten des Interrupts zu Problemen 
führen können.

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.