Forum: Mikrocontroller und Digitale Elektronik Probleme mit Counter auf Atmega8


von Philipp C. (noxkiller)


Lesenswert?

Ich habe jetzt schon alles was mir einfiel versucht, das Datenblatt hin 
und her gewälzt aber ich komme nicht drauf. Assembler auf dem Atmega 
mache ich jetzt allerdings auch nicht jeden Tag sondern nur bei Bedarf, 
bin also für Anmerkungen zum Code offen. Der Ausschnitt ist Teil eines 
größeren Programms, aber hier liegt irgendwo ein Fehler von mir. Es 
sollen eigentlich nur alle Pins auf einem Port high gesetzt werden und 
dann nach einer definierten Zeit der Reihe nach ausgehen. Im Debugger 
alles kein Problem, es funktioniert wie ich will aber in real sieht es 
anders aus. Bleibt der Atmega an der ISP Schnittstelle nach dem 
Programmieren hängen geht alles, nehm ich die Schnittstelle ab sehe ich 
die LEDs erst gar nicht angehen. Als ob der Prescaler nicht richtig 
gesetzt ist und ich mit maximalen internen Takt (für mich nicht 
sichtbar) alle LEDs ausgeschaltet werden. Der Atmega soll übrigens mit 
1MHz internem Takt laufen.
1
.include "m8def.inc"
2
3
.def temp = r18
4
.def counter0 = r19
5
.def wait0 = r20
6
.def wait1 = r21
7
8
.org 0x0000
9
     rjmp     init_ports                   
10
11
.org OVF0addr
12
    rjmp     timer0_overflow
13
14
init_ports:
15
      ldi temp,0xFF  ;Port D0...7 Ausgang
16
          out ddrd,temp
17
      ldi temp,0xFF  ;Pullups aktiv
18
          out portd,temp
19
20
21
      ldi     temp, 0b00000101       ; Prescaler 1024
22
          out     TCCR0, temp
23
24
      ldi    temp, 0b00000001    ; Timer Interrupt erlauben
25
      out   TIMSK, temp
26
27
      ldi    counter0, 0x0B      
28
      out   TCNT0, counter0
29
30
      sei
31
32
start:    cpi    wait1, 1
33
      brlo  start
34
    
35
  wait_8:  cbi    PORTD, 0
36
      cpi    wait1, 2
37
      brlo  wait_8
38
39
  wait_7:  cbi    PORTD, 1
40
      cpi    wait1, 3
41
      brlo  wait_7
42
43
  wait_6:  cbi    PORTD, 2
44
      cpi    wait1, 4
45
      brlo  wait_6
46
47
  wait_5:  cbi    PORTD, 3
48
      cpi    wait1, 5
49
      brlo  wait_5
50
51
  wait_4:  cbi    PORTD, 4
52
      cpi    wait1, 6
53
      brlo  wait_4
54
55
  wait_3:  cbi    PORTD, 5
56
      cpi    wait1, 7
57
      brlo  wait_3
58
59
  wait_2:  cbi    PORTD, 6
60
      cpi    wait1, 8
61
      brlo  wait_2
62
63
  wait_1:  cbi    PORTD, 7
64
      cpi    wait1, 9
65
      brlo  wait_1
66
67
rjmp start
68
69
timer0_overflow:
70
71
         push    temp
72
        in      temp,sreg
73
        push    temp
74
75
      inc   wait0
76
      cpi   wait0, 10
77
      brlo  timer0_overflow_out
78
      ldi    wait0, 0x00
79
      inc   wait1
80
    
81
      timer0_overflow_out:
82
        pop     temp
83
        out     sreg,temp
84
        pop     temp
85
86
reti

von Hubert G. (hubertg)


Lesenswert?

Wenn es mit angestecktem Programmer funktioniert sieht es eher nach 
einem HW-Fehler aus.
Spannung vorhanden?
Reset auf high?

von Karl H. (kbuchegg)


Lesenswert?

Die Initialisierung des Stack Pointers fehlt. Der Pop bzw. Return aus 
dem Interrupt geht damit in die Hose.

von Karl H. (kbuchegg)


Lesenswert?

> Bleibt der Atmega an der ISP Schnittstelle nach dem Programmieren
> hängen geht alles, nehm ich die Schnittstelle ab sehe ich die LEDs
> erst gar nicht angehen. Als ob der Prescaler nicht richtig gesetzt ist

.... so als ob es ein Problem mit dem Reset Pin gibt
.... so als ob es ein Problem mit der Spannungsversorgung gibt

von oldmax (Gast)


Lesenswert?

Hi
Nun, ein Setzen des Stackpointers ist beim Atmega8 nicht unbedingt 
erforderlich, da der SP beim Start auf 0 steht und durch PUSH erst dec. 
und dann beschrieben wird. Dennoch kommen die paar Befehle auch bei mir 
grundsätzlich vor dem ersten CALL in das Programm:
1
LDI  Reg_A ,high(RAMEND)  ; Stack Pointer setzen 
2
OUT  SPH, Reg_A    ; "RAMEND" ist in m8def.inc festgelegt
3
LDI  Reg_A, low(RAMEND)  
4
OUT  SPL,Reg_A
Soviel zum Stack. Der Fehler liegt vermutlich in der Hardware, obwohl 
genug am Programm zu meckern gibt.
Wenn du einen Timer mit Interrupt benutzt, dann arbeite anders:
Im Timer- Interrupt zählst du deine Variable hoch. Dann vergleichst du 
den Wert mit einer Konstanten und bei Übereinstimmung setzt du ein Bit 
(Job-Flag). Dieser Programmteil hat mit deiner Programmschleife 
überhaupt nix zu tun und läuft dann autark.
Nun zum Job-Flag. Soll bei einem bestimmten Zählerstand eine Bearbeitung 
stattfinden, so kannst du natürlich auch außerhalb der ISR den Wert 
vergleichen. Das erfolgt unter Umständen aber mehrmals mit positivem 
Ergebnisin der Programmschleife (Zykluszeit < Bearbeitung im Timer). 
Nicht immer ist das erwünscht und wenn dieses Ereignis nur einmal 
bearbeitet werden soll, nimmt man ein Job-Flag. Ist dieses gesetzt, dann 
führst du die beabsichtigten Schritte durch und setzt anschließend das 
Job-Flag zurück. Nun wird dieses Programm erst wieder aufgerufen, wenn 
im Timer das Bit gesetzt wird. Dein Programm läuft also immer durch alle 
Abfragen und bleibt nicht wie beim vorgestellten Code in einer 
Unterschleife hängen. So ist es niemals über normale Eingänge bedienbar 
und du wärest gezwungen, bei Tastereingaben z.B. mit einer ISR zu 
arbeiten. Schau mal über die Suchmaschine, ob du irgend welche Beiträge 
zu Jobflags findest. Dann wird dir vermutlich auch deutlich, welche 
Struktur du beim Programmieren, grad in Assembler, dir angewöhnen 
solltest.
Ansonsten schau mal zur Konkurenz AVR-Praxis.de. Dort ist in der Rubrik 
FAQ ein Beitrag "keine Angst vor Assembler" mit hoffentlich 
interessanten Hinweisen.
Sie mal nach, ob vom Reset-Pin ein Widerstand von ca. 10 KOhm nach VCC 
geht. Auch evtl. die GND-Leitung überall richtig verschaltet ist.
Gruß oldmax

von Philipp C. (noxkiller)


Lesenswert?

So, an RESET, VCC und AVCC liegen saubere 5V DC. An 8 und 22 sauberer 
Ground. Der Rest des Programms nach dem oberen Codeauszug funktioniert 
ja auch, der Fehler sollte demnach im Programm liegen. Versorgung beim 
Programmieren kommen auch aus der Schaltung. Es wird also nichts 
fremdgespeist, weshalb es nur mit angeschlossenem ISP funktioniert. 
Initialisieren des Stack Pointers werde ich dann auch mit aufnehmen. 
Arbeiten mit Job Flags kenne ich, werde dann das Programm gleich mal 
umstricken.

von Philipp C. (noxkiller)


Lesenswert?

Zur Info, es lag am Programm, wo genau kann ich nicht sagen, mit 
Job-Flags gehts.

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.