Forum: Mikrocontroller und Digitale Elektronik mein erster Test mit PWM


von Rolf H. (flash01)


Lesenswert?

Hallo Leute,
habe mir aus dem AVR-Tutorial eine Quelldatei ausgesucht,
um rein aus Interesse in die Pulsweiten-Modulation
einzusteigen.
Habe sie zu Beginn auf den Tiny2313 zugeschnitten. Aber ich
komme trotz beiliegenden Buch in Deutsch nicht weiter.
Nach "Build" kommen Mengen von Fehler, die immer wieder auf
Makro hinweisen.
An der ISR habe ich noch nichts verändert.
Bevor ich jetzt einsetze

push   r2
in     r2,SREG

und am Ende
out    SREG,r2
pop    r2
möchte ich erst mal Eure Meinung hören

Aber gerade da müssen die Fehler herkommen, denn schneide ich
den Inhalt der ISR aus, ist alles Fehlerfrei.
Mit den neuen Befehlen wie cp  brlo und ori muß ich mich noch
auseinander setzen.

Grüße

Rolf

; Projekt: Projekt01          Datum: 02.06.2012

; Datei: PWM02-test.asm


                 ; r18=Helligkeitswert Led1: 0 .. 127
                 ; r19=Helligkeitswert Led2: 0 .. 127
                 ; r20=Helligkeitswert Led3: 0 .. 127
                 ; r21=Helligkeitswert Led4: 0 .. 127
                 ; r22=Helligkeitswert Led5: 0 .. 127
                 ; r23=Helligkeitswert Led6: 0 .. 127


       .INCLUDE "tn2313def.inc"
       .EQU      takt = 1200000

        rjmp    reset             ; Reset Handler
       .ORG OVF0addr
        rjmp    TIMER0_OVF  ; Timer Overflow Handler

reset:
        ldi     r16, LOW(RAMEND); Stackpointer initialisieren
        out     SPL, r16

        ldi     r16, 0xFF       ; Port B auf Ausgang
        out     DDRB,r16

        ldi     r18, 0        ; r18
        ldi     r19, 1        ; r19
        ldi     r20, 10       ; r20
        ldi     r21, 20       ; r21
        ldi     r22, 80       ; r22
        ldi     r23, 127      ; r23

        ldi     r16,1<<CS00    ; CS00 setzen: Teiler 1
        out     TCCR0B,r16

        ldi     r16,1<<TOIE0   ; TOIE0: Interrupt bei Timer Overflow
        out     TIMSK,r16

        sei

loop:   rjmp    loop

timer0_OVF:                  ; Timer 0 Overflow Handler
        inc     r17          ; den PWM Zähler von 0 bis
        cpi     r17, 128     ; 127 zählen lassen
        brne    WorkPWM
        clr     r17
WorkPWM:
        ldi     r16, 0b11000000  ; 0 .. Led an, 1 .. Led aus

        cp      r17,r18     ; Ist der Grenzwert für Led 1 erreicht
        brlo    OneOn
        ori     r16, 0x01

OneOn:  cp      r17,r19     ; Ist der Grenzwert für Led 2 erreicht
        brlo    TwoOn
        ori     r16, 0x02

TwoOn:  cp      r17,r20     ; Ist der Grenzwert für Led 3 erreicht
        brlo    ThreeOn
        ori     r16, 0x04

ThreeOn:cp      r17,r21    ; Ist der Grenzwert für Led 4 erreicht
        brlo    FourOn
        ori     r16, 0x08

FourOn: cp      r17,r22     ; Ist der Grenzwert für Led 5 erreicht
        brlo    FiveOn
        ori     r16, 0x10

FiveOn: cp      r17,r23     ; Ist der Grenzwert für Led 6 erreicht
        brlo    SetBits
        ori     r16, 0x20

SetBits:                            ; Die neue Bitbelegung am Port 
ausgeben
        out     PORTB,r16

        reti

Würde man die LEDs anstatt direkt an einen Port

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Rolf Hegewald schrieb:
> Würde man die LEDs anstatt direkt an einen Port

Ja? Da fehlt was :P
Im Prizip ist es gute Praxis, alle Register, die in der ISR benutzt 
werden zu retten und wenn dein Hauptprogramm etwas anderes macht, als 
die o.a. Schleife, musst du SREG auf jeden Fall retten. Wenn du sicher 
bist, das die in der ISR benutzten Register nirgendwo anders benutzt 
werden, kannst du dir das Retten aber sparen.
Poste mal bitte die Fehlermeldungen des Assemblers.

von spess53 (Gast)


Lesenswert?

Hi

>Nach "Build" kommen Mengen von Fehler, die immer wieder auf
>Makro hinweisen.

Wieso? Dein Programm lässt sich doch fehlerfrei assemblieren.

MfG Spess

von Rolf H. (flash01)


Lesenswert?

Hallo Spess,


nun bin ich aber fertig!

11 Fehler kommen bei mir wie

D:\Tiny2313\PWM02-test.asm(82): error: Port: Unknown instruction or 
macro

vor dem letzten unvollständigen Satz fehlte ein ;
da muß ich nochmals in Tutorial schauen, was das Ende anbetrifft.

Grüße

Rolf

von spess53 (Gast)


Lesenswert?

Hi

Hänge mal dein asm-File als Anhang an. Ich habe mir deinen Programmtext 
in ein Testprojekt geladen und assembliert.

Eine Zeile 82 habe ich dort allerdings nicht. Deshalb kann ich deine 
Fehlermeldung nicht nachvollziehen.

MfG Spess

von Rolf H. (flash01)


Lesenswert?

Hallo Spess,
jetzt habe ich einen PC mit Win7 angeschmissen und es läuft.
Heute Morgen war es ein Laptop mit Vista..aber daran kann es nicht
liegen.

Ein Fehler machte mich stutzig:

L:\Tiny2313\PWM02-test.asm(82): error: Invalid character: 'ü' (0xfc)

und ich erkannte, daß in dem Text am Ende das ";" fehlte.

Würde man die LEDs anstatt direkt an einen Port

dies erzeugte sagenhafte 11 Fehler.

Die Befehle cp  brlo und ori sind äußerst kompliziert zu
verstehen, mal sehen,ob ich das packe.
Sollte man denn all die verwendeten Arbeitsregister von r16
bis r23 zu Beginn der ISR mit push retten und danach mit pop
vom Stack zurück holen?
Morgen werde ich an PortB Leds hängen..mal sehen, was da abläuft.
Habe einen interessanten Quelltext (Thema PWM) für den Tiny 2313
entdeckt und mußte erkennen, daß sich die ganze Periode ver-
änderte. Eigentlich wollte ich ja das Impuls/Pausenverh. ändern.
Interessant, was ich auf dem Skop entdecken konnte.
Werde berichten!

Danke nochmal

Rolf

von spess53 (Gast)


Lesenswert?

Hi

>Sollte man denn all die verwendeten Arbeitsregister von r16
>bis r23 zu Beginn der ISR mit push retten und danach mit pop
>vom Stack zurück holen?

Nein. In der obigen Interruptroutine nur r16. r17 soll ja den neuen Wert 
behalten und r18...r23 werden nicht verändert.

>Die Befehle cp  brlo und ori sind äußerst kompliziert zu
>verstehen, mal sehen,ob ich das packe.

cp ist eigentlich nur eine Subtraktion, bei der der Minuend erhalten 
bleibt. Die Flags werden wie bei einer Subtraktion gesetzt.

brlo ist identisch (gleicher Op-Code) mit brcs. Deshalb benutze ich auch 
letzteres. Solange keine negativen Zahlen ins Spiel kommen kann man fast 
alles mit brcc, brcs, breq und brne erschlagen.

MfG Spess

von Rolf H. (flash01)


Lesenswert?

Hallo Spess,
so sieht jetzt die ISR aus, habe ich das richtig
gemacht??

timer0_OVF:                  ; Timer 0 Overflow Handler
        push    r16
        push    r17
        in      r16,SREG
        in      r17,SREG

        inc     r17          ; Increment (Inhalt r17+1)
        cpi     r17, 128     ; vergleiche Inhalt r17 mit 128
                             ; Inhalt von r17 bleibt erhalten
        brne    WorkPWM      ; Verzweigung bei Z = 0
        clr     r17          ; alle Bits von r17 löschen
WorkPWM:
        ldi     r16, 0b11000000  ; 0 .. Led an, 1 .. Led aus

        cp      r17,r18     ; Ist der Grenzwert für Led 1 erreicht
        brcs    OneOn       ; Verzweigung bei C = 1
        ori     r16, 0x01   ; Verknüpfung r16 mit der Konstanten
                            ; durch ein logisches ODER

OneOn:  cp      r17,r19     ; Ist der Grenzwert für Led 2 erreicht
        brcs    TwoOn
        ori     r16, 0x02

TwoOn:  cp      r17,r20     ; Ist der Grenzwert für Led 3 erreicht
        brcs    ThreeOn
        ori     r16, 0x04

ThreeOn:cp      r17,r21     ; Ist der Grenzwert für Led 4 erreicht
        brcs    FourOn
        ori     r16, 0x08

FourOn: cp      r17,r22     ; Ist der Grenzwert für Led 5 erreicht
        brcs    FiveOn
        ori     r16, 0x10

FiveOn: cp      r17,r23     ; Ist der Grenzwert für Led 6 erreicht
        brcs    SetBits
        ori     r16, 0x20

SetBits:                    ; Die neue Bitbelegung am Port ausgeben
        out     PORTB,r16

        out     SREG,r16
        out     SREG,r17
        pop     r16
        pop     r17
        reti
        .EXIT

von Thomas P. (topla)


Lesenswert?

timer0_OVF:                  ; Timer 0 Overflow Handler
        push    r16
        in      r16, SREG
        push    r16

        inc     r17          ; Increment (Inhalt r17+1)

....

        out     PORTB,r16

        pop     r16
        out     sreg, r16
        pop     r16
        reti

von Rolf H. (flash01)


Lesenswert?

zu Spess vom 02.06.2012
ich sollte etwas gewissenhafter Antworten lesen;
habe die ISR abgeändert wie:

timer0_OVF:
    push    r16
    in      r16,SREG

    inc     r17    ;usw.

    out     SREG,r16
    pop     r16
    reti
    .EXIT

Und jetzt evtl. was für Anfänger.

; Projekt-Name: Projekt01           Datum: 30.05.2012

; Datei: PWM01test.asm

; getestet mit Debugging (Hex-Inhalte in Klammern 0x00) nach ersten 
Durchlauf
; drücke Taste F11
; für Ablauf bis Ende sbrs geändert in sbrc!

; ATtiny2313  Timer0 variable Wartezeit nachladen
; Port B: Ausgabe PB3 umschalten als Frequenzausgabe

; Port D: Eingabe Wartezeit
; Konfiguration: interner Oszillator 1,2 MHz, externes RESET-Signal
        .INCLUDE "tn2313def.inc"   ; Deklarationen für Tiny2313
        .EQU    takt = 1200000  ; Systemtakt 1,2 MHz intern
        .DEF    akku = r16      ; Arbeitsregister

        rjmp    reset           ; Reset-Einsprung
        .ORG    OVF0addr        ; Interrupt-Vektor


reset:  ldi     akku,LOW(RAMEND); Stapel anlegen (0xDF)
        out     spl,akku

        ldi     akku,0x00
        out     DDRD,akku       ; PortD auf Input
        ldi     akku,0xFF
        out     PORTD,akku      ;Pull Up PortD



        ldi     akku,0x08       ; 0b0000 1000 (akku=0x08)
        out     DDRB,akku       ; PB3 als Ausgang (0x08)
        mov     r17,akku        ; kopiere Inhalt akku nach (r17=0x08)
                                ; akku-Inhalt bleibt erhalten

; Timer0 programmieren
        ldi     akku,1<<CS02|1<<CS00 ; Prescale=1024 (akku=0x05)
        out     TCCR0B,akku     ; Steuerregister Timer0

; Arbeitsschleife mit Überlaufkontrolle
loop:   in      akku,PIND       ; lade akku mit Inhalt vom Register PIND
        neg     akku            ; Ergebnis müßte aus 0x00 = 0x00 sein
                                ; im Register SREG ist Flag-Z gesetzt
        out     TCNT0,akku      ; Zähleranfangswert auf 0x00 gesetzt
warte:  in      akku,TIFR       ; lade akku mit Inhalt vom TIFR Register 
(0x00)
        sbrc    akku,TOV0       ; überspringe, wenn Bit0 (TOV0) im 
Register TIFR
                                ; gelöscht ist (0)
        rjmp    warte           ; warte auf Überlauf
        out     TIFR,akku       ; Überlaufbit wieder löschen (akku = 
0x00)
        in      akku,PORTB      ; akku = 0x00
        eor     akku,r17        ; komplementieren, (akku=0x08)
        out     PORTB,akku      ; PORTB,PB3 = 1 (0x08)
        rjmp    loop            ; Schleife neue Eingabe
       .EXIT                    ; Ende des Quelltextes

Ich hatte an PORTB,PB3 einen Skop hängen und bekam das Signal nicht
sauber getriggert. (Externe Trigg. brachte auch nichts)
Erst als ich intern Pullup aktiviert hatte,blieb das Signal
sauber stehen.
Impuls / Pausenverhältnis = 1:1
Dann habe ich einen Frequenzmesser an PB3 angelegt und siehe da:

alle Pins vom Register HIGH = 502 Hz
PD0 auf LOW = 507 HZ
PD1 auf LOW = 512 HZ
PD2 auf LOW = 522 HZ
PD3 auf LOW = 537 HZ
PD4 auf LOW = 577 HZ
PD5 auf LOW = 674 HZ
PD6 auf LOW = 1010 HZ
PD7 gibt es beim Tiny2313 nicht.
Finde ich interessant, weiß noch nicht, für was ich das mal
gebrauchen kann.
Nun suche ich nach einem Quelltext in Assembler geschrieben,
wie ich das Impuls / Pausenverhältnis verschieben kann.
In meinem Buch ist nichts, im Tutorial auch nicht...hat da
jemand was für mich?

Grüße

Rolf

von Rolf H. (flash01)


Lesenswert?

Hi,
habe bei Google "PWM servoansteuerung" eingegeben und es kam eine
Menge Infos heraus.
Unter anderem auch von Hannes Lux in einem Thread versteckt
Servoansteuerung mit Tiny 13 vom 26.08.2008... eine .asm Datei
t13serv1.asm
Da kommt ja was auf mich hinzu!

Grüße

Rolf

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.