Forum: Mikrocontroller und Digitale Elektronik veränderliches Blinklicht (Assembler)


von Christian H. (Firma: CSC) (chris-h) Benutzerseite


Lesenswert?

Hallo Forum!

Hier mein erstes eigenes "Programm" (Atmga8):
- an PORTB sollen die LEDs blinken
- mit Tastern an INT0 und INT1 (PD2; PD3) soll die Frequenz verändert 
werden

Der erste Teil funktioniert (über Timer-Overflow mit Teiler 3 und einem 
Zählregister, das jedes 7. Mal eins höher zählt - ist vermutlich nicht 
sehr elegant, aber ich wollte beide Möglichkeiten kombinieren, aus 
Trainingsgründen).

Der zweite Teil macht gar nix (Änderung des Teilers für den 
Timer-Overflow). Ich wüsste auch nicht, wie man das im AtmelStudio 
simulieren könnte...

Hier der Code:
1
.include "m8def.inc"
2
 
3
.def temp = r16
4
.def leds = r17
5
.def count = r18
6
7
.org 0x0000
8
        rjmp    main                  ; Reset Handler
9
.org INT0addr   
10
    rjmp  int0_handler            ; External Interrupt0 Vector Address
11
.org INT1addr   
12
    rjmp int1_handler        ; External Interrupt1 Vector Address
13
.org OVF0addr
14
        rjmp    timer0_overflow       ; Timer Overflow Handler
15
 
16
main:
17
        ; Stackpointer initialisieren
18
        ldi     temp, HIGH(RAMEND)
19
        out     SPH, temp
20
        ldi     temp, LOW(RAMEND)     
21
        out     SPL, temp
22
 
23
        ldi     temp, 0xFF            ; Port B auf Ausgang
24
        out     DDRB, temp
25
     
26
        ldi     leds, 0xFF
27
28
        ldi     count, 3        ; CS00 setzen: Teiler 3 (Startwert von count)
29
        out     TCCR0, count
30
 
31
        ldi     temp, (1<<TOIE0)      ; TOIE0: Interrupt bei Timer Overflow
32
        out     TIMSK, temp
33
 
34
        sei
35
36
    ldi    temp, 0
37
 
38
loop:   
39
    cpi    temp, 7
40
    breq  schalten        ; wenn 7. Overflow, dann umschalten
41
    rjmp    loop
42
    
43
schalten:
44
    out     PORTB, leds
45
        com     leds
46
    ldi    temp, 0
47
    rjmp  loop
48
     
49
timer0_overflow:                      ; Timer 0 Overflow Handler
50
    inc    temp          ; Zähler erhöhen
51
        reti
52
53
int0_handler:
54
    inc    count          ; Teiler erhöhen
55
    out     TCCR0, count
56
    reti
57
58
int1_handler:
59
    dec    count          ; Teiler verkleinern
60
    out     TCCR0, count
61
    reti

DANKE!
Chris

P.S.: Sorry, die Formatierung vom Code verzerrt sich beim Kopieren.

: Verschoben durch User
von Bernhard (Gast)


Lesenswert?

Der "timer0_overflow" wird immer ausgelöst, wenn der Zähler überläuft. 
Wenn du im int0 / int1 ein einziges mal "count" in den Zähler schreibst, 
dann zählt er das erste Mal vom Wert "count" bis er überläuft, danach 
aber immer wieder komplett durch.

Schreib in deinem "timer0_overflow" den Wert "count" in den Zähler 
TCCR0, damit er jedesmal von count startet.

von Bitflüsterer (Gast)


Lesenswert?

Externe Interrupt INT0 und INT1 müssen über das GIC-Register gültig 
gesetzt werden (2486X–AVR–06/10 - Seite 67)

Dazu wirst Du vermutlich das Problem haben, das die Taster prellen. Aber 
das ist ein anderes Thema.

von Karl H. (kbuchegg)


Lesenswert?

Das hier

>         ldi     count, 3        ; CS00 setzen: Teiler 3 (Startwert von count)
>        out     TCCR0, count

macht aber nicht, was du denkst bzw. was du dir davon erhoffst.

Das ist kein Teiler 3.

Da werden die Bits 0 und 1 im TCCR0 gesetzt. Die Namen der Bits sind 
CS01 und CS00. Das ist ein Vorteiler von 64.
Man kann natürlich den Vorteiler eines Timers im laufenden Betrieb 
verändern. Ob du das willst, ist allerdings eine andere Sache. Denn: so 
viele Vorteiler gibt es nicht und die sind dann auch noch recht grob 
abgestuft. Es gibt die Vorteiler: 1, 8, 64, 256 und 1024. Das wars dann 
schon, dann ist Ende der Fahnenstange. Mit jeder Stufe wird dein Blinken 
also 8 mal langsamer. Die Sonderfälle 0 und externer Takt mal aussen vor 
gelassen.


Guter Rat:
Studier das AVR-Tutorial. Da scheint mir mit deinem Verständnis von 
Timern einiges im argen zu liegen.

Tasten am externen Interrupt: kann man machen, muss man nicht machen. 
Wenn man es aber macht, dann muss man den Interrupt auch freigeben.
Und ja, man kann das im Simulator auch simulieren. Nur weil ein externer 
Interrupt an einem Pin freigegeben wurde, bedeutet das nicht, dass der 
Simulator das Setzen bzw. Rücksetzen eines Pins im I/O View verhindern 
würde. Klickst du dort mit der Maus den zugehörigen Pin an und setze den 
Pin auf 1 oder 0, dann wird selbstverständlich der zugehörige Interrupt 
im Simulator je nach Konfiguration des Interrupts auch ausgelöst und die 
Simulation verzweigt in den Interrupt Vektor. Ein dort platzierter 
Haltepunkt spricht dann an.

: Bearbeitet durch User
von Christian H. (Firma: CSC) (chris-h) Benutzerseite


Lesenswert?

Danke soweit einmal! Ich werde das über Ostern durcharbeiten. Jedenfalls 
macht es wirklich Spass --- vor allem mit der Unterstützung in dem 
Forum.

Wirklich: Es ist super, dass man sich auch nicht auskennen und Fehler 
machen darf, ohne dumme Kommentare zu hören.

Danke und schöne Ostern!
Chris

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.