mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Port wird nicht angesteuert - in der Simulation schon!


Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche mit einem Tiny15 das PWM-Signal auf drei LED zu 
multiplexen.

In der Simulation macht auch alles schön das, was es soll. Aber im 
Controller passiert am Pin PB0 gar nichts.
Durch rumexperimentieren habe ich festgestellt, dass wenn ich den Code 
isoliere (LED_MUX) wird es ausgeführt; im Gesamtkonstrukt aber nicht.
Eine echte Logik konnte ich aber nicht entdecken.

Also interessant ist die Subroutine LED_MUX, da stimmen Simulation und 
Wirklichkeit nicht überein.

Haut es da irgend ein Register/Stack durcheinander??`


Kann mir jemand helfen??

Danke vorab!


Nachtrag: Ich habe gerade nochmal das Signal mit dem Scope angeschaut: 
Der Pin hängt auf ca. UB/2 ?! (ist dabei herausgebogen, also mit nichts 
verbunden). Andere Tiny machen das gleiche => HW-Fehler ausgeschlossen

Der Code
;  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
;
;       Farbansteurung mit RGB-LED
;
;      ein PWM-Signal im Multiplexingbetrieb aus 3 LED
;
;  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
;
;
;
;     Belegung Tiny15
;    ---------------
; PB0  Ausgang MUX b
; PB1    Ausgang PWM
; PB2  Ausgang MUX a
; PB3  Eingang Taster
; PB4    Eingang Poti-ADC
; PB5  RESET




.include "tn15def.inc"

.def WRegister      =    R16
.def LEDNr        =    R17
.def RDummy        =    R18
.def RDummy2    =  R19
.def RHelligkeit0    =    R20
.def RHelligkeit1    =  R21
.def RHelligkeit2    =    R22
.def fPWM_LED1    =  R23
.def fPWM_LED2    =  R24
.def fPWM_LED3    =  R25
.def RStore      =  R26

; Vorgaben für Ausgangshelligkeit
.equ Vorgabe_fPWM_LED1  =  0x80
.equ Vorgabe_fPWM_LED2  =  0x80
.equ Vorgabe_fPWM_LED3  =  0x80


; Vorgaben für Tasterentscheid
; 0= beide gedrückt  0xA7=Taster2 gedrückt 0xF2= Taster1 gedrückt
.equ Vorgabe_T1_high  =  0xE9
.equ Vorgabe_T1_low    =  0xDC
.equ Vorgabe_T2_high  =  0xDC
.equ Vorgabe_T2_low    =  0x8C
.equ Vorgabe_T12_high  =  0x64





.org  $000

rcall Init
rjmp Main

    .org $003  ;Timer1 Compare Match
      nop  
    .org $004  ;Timer1 Overflow handler
      rjmp TIM1_OVF
    .org $005  ;Timer0 Overflow handler
      nop


.org $009

Init:


    ldi    RDummy,0x74    ; Oszillator kalibrieren
    out    OSCCAL,RDummy
      
    ldi   WRegister,0x00|(1<<PB0)|(1<<PB1)|(1<<PB2)|(00<<PB3)  ; PB1 als Ausgang
      out   DDRB,WRegister

      ldi   WRegister,(0<<OCIE1A)|(1<<TOIE1)|(0<<TOIE0) ;Interruptregister schalten
      out   TIMSK,WRegister

    ;PWM einstellen

      ;ldi   WRegister,(1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10)|(1<<PWM1)|(1<<COM1A1)|(1<<COM1A0)|(0<<CTC1)  ; invertierte PWM einsschalten -> Geschwindigkeit CK
      ldi   WRegister,(0<<CS13)|(1<<CS12)|(0<<CS11)|(1<<CS10)|(1<<PWM1)|(1<<COM1A1)|(1<<COM1A0)|(0<<CTC1)  ; invertierte PWM einsschalten -> Geschwindigkeit CK
      out   TCCR1,WRegister
  
    out   OCR1B,WRegister
      ldi   WRegister,0xFF  ;PWM-Frequenz

      ldi   WRegister,0x80  ;Pulsweite einstellen
      out   OCR1A,WRegister

    ;ADC
    
      ldi    WRegister,(1<<ADEN)|(1<<ADSC)|(1<<ADFR)|(0<<MUX2)|(1<<MUX1)|(0<<MUX0)
      out    ADCSR,WRegister

    
    sei        ; Interrupt aktivieren
    ret            ;zurückspringen

Main:
    rjmp   Main



TIM1_OVF:



Helligkeit_Einstellen:  ;
    ldi    WRegister,(0<<MUX2)|(1<<MUX1)|(1<<MUX0)|(1<<ADEN)|(1<<ADSC)|(1<<ADFR)
    out   ADMUX,WRegister ; ADC auf Potieingang stellen
    in    RDummy,ADCH  
    out   OCR1A,RDummy
    
    rcall  LED_MUX
  



    sei
    reti          ;Rücksprung aus Interrupthandler







; ############################################################################
;
;        SUB-ROUTINEN
;
; ############################################################################

; -------------------LED muxen ---------------------------
LED_MUX:
    inc   LEDNr      ; auf nächste LED schalten
    cpi   LEDNr,3  ; wenn LED>> 2 dann auf 0 rücksetzen
    BRLO   LED_Out
    ldi   LEDNr,00
LED_Out:

    clr    RDummy      ; Register auf Default setzen
    sbrc  LEDNr,0      ;ist LEDNr[0]=1 -> nein, dann überspringen
    SBR    RDummy,(1<<PB0)
    sbrc  LEDNr,1      ;ist LEDNr[1]=1 -> nein, dann überspringen
    SBR    RDummy,(1<<PB2)


    out   PORTB,RDummy  ; ausgeben
    ret          ;Rücksprung 
; --------------------------------------------------------


Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast mehrere Interrupts freigegeben, für die kein Handler existiert. 
Wenn z.B. der Timer 0 Overflow auftritt, gibts nen kompletten Reset, 
weil hinter dem nop im Vektor nicht ausführbarer Code steht!

>   sei
>   reti          ;Rücksprung aus Interrupthandler
Das sei hat da nichts zu suchen, das steckt im reti schon mit drin!

EDIT:
sehe grad, dass die Interrupts nicht freigegeben sind. War durch die 
(blödsinnige) Schreibweise mit dem "0 << TOIE0" durcheinander 
gekommen...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier

>    out   OCR1B,WRegister
>      ldi   WRegister,0xFF  ;PWM-Frequenz

ist erst mal die Reihenfolge vertauscht. Könnte mitschuld
an deinem Problem haben.


Das hier

> .org  $000
>
> rcall Init
> rjmp Main

ist keine gute Idee. Das rjmp Main steht bereits an einer
Stelle, an der eigentlich ein Interrupt Vektor im Speicher
steht. Kein AHnung welcher. Das müsste man im Datenblatt
nachsehen. Gut. Momentan wird dieser Interrupt Vektor nicht
benutzt und ist somit kein Problem. Aber wie du eine rcall
ausführen willst, ohne zuvor den Stackpointer gesetzt zu haben
ist mir nicht klar. Oder hat der Tiny15 auch dieses besch...
3 Stackadressen Spezialfeature, wie es der Tiny12 hat?
(muss gleich mal nachsehen)


Das macht mich jetzt etwas stutzig
In der Init
>    ;ADC
>      ldi 
WRegister,(1<<ADEN)|(1<<ADSC)|(1<<ADFR)|(0<<MUX2)|(1<<MUX1)|(0<<MUX0)
>      out    ADCSR,WRegister

in der Helligkeit_einstellen:
>    ldi    WRegister,(0<<MUX2)|(1<<MUX1)|(1<<MUX0)|(1<<ADEN)|(1<<ADSC)|(1<<ADFR)
>    out   ADMUX,WRegister ; ADC auf Potieingang stellen

Beides mal sind es dieselben Bits. Aber einmal schreibst du sie
ins ADCSR Register und das andere mal ins ADMUX. Was stimmt denn
nun?

>    out   ADMUX,WRegister ; ADC auf Potieingang stellen
>    in    RDummy,ADCH

So schnell ist der ADC nun auch wieder nicht. Man sollte schon
auch abwarten, bis der ADC ein Wandlerergebnis fertig hat.

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stackpointer habe ich auch schon vermutet, aber wie funzt das...

Die OCR1B initialisierung habe ich angepasst, erwartungsgemäß hat sich 
nichts geändert. Es wäre halt nur eine falsche Freqeunz eingestellt, 
wobei dies zweitrangig ist.

@Johannes
was spricht gegen die "0 << TOIE0"-Schreibweise? Auf einen Blick sieht 
man sofort, ob und wie das Bit gesetzt ist?!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timo wrote:

> was spricht gegen die "0 << TOIE0"-Schreibweise? Auf einen Blick sieht
> man sofort, ob und wie das Bit gesetzt ist?!

Die Zeilen werden so lang, dass du vor lauter Ausdrücken erst recht
nicht mehr siehst, welche denn jetzt zu einem 1 Bit führen.

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups, zu schnell...

    ;ADC

      ldi    WRegister,(1<<REFS1)|(1<<REFS0)|(1<<ADLAR) ;mit ADLAR links 
reicht das HB zur Steuerung aus
      out    ADCSR,WRegister

so muß es heißen.
Aber der ADC ist momentan nicht in Gebrauch (kommt noch...) und sollte 
doch auch ein anderes Schlachtfeld sein.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timo wrote:
> ups, zu schnell...
>
>     ;ADC
>
>       ldi    WRegister,(1<<REFS1)|(1<<REFS0)|(1<<ADLAR) ;mit ADLAR links
> reicht das HB zur Steuerung aus
>       out    ADCSR,WRegister
>
> so muß es heißen.
> Aber der ADC ist momentan nicht in Gebrauch (kommt noch...) und sollte
> doch auch ein anderes Schlachtfeld sein.

Ist schon klar.
Ist mir nur beim drüberlesen aufgefallen. Bis jetzt habe ich
das Programm nur noch formalen Gesichtspunkten untersucht ohne
gross auf die Funktionalität oder Logik zu achten.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du sicher, dass dieser PWM Modus einen Overflow
Interrupt auslöst. Da das ganze doch auf den OCR Registern
basiert, sollte das doch eigentlich ein Compare Match Interrupt
sein.

Hilft nichts, muss ich mir doch mal das Datenblatt zum Tiny15
holen.

PS: Dem Simulator darfst du in solchen Dingen nicht unbedingt
trauen. Der hat gerade bei Timern und PWM so seine Eigenheiten.

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also mit der PWM-Erzeugung habe ich jetzt weniger Zweifel, das dies an 
sich funktioniert - das Signal wird ja ausgegben. Nur eben PB0 macht mir 
Sorgen...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timo wrote:
> Also mit der PWM-Erzeugung habe ich jetzt weniger Zweifel, das dies an
> sich funktioniert - das Signal wird ja ausgegben. Nur eben PB0 macht mir
> Sorgen...

<Noch mal nachgelesen>
ooops. Da hab ich deine Frage misverstanden.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AN PB0 liegt das MOSI Signal.
Den ISP Brenner hast du abgezogen?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Stackpointer habe ich auch schon vermutet, aber wie funzt das...
Der Tiny15 hat (wie von Karl Heinz vermutet) einen Hardware-Stack.

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ISP-Programmer ist abgezogen.

Wenn es einen HW-Stack gibt, dann brauche ich mich ja darum nicht zu 
kümmern!?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timo wrote:
> ISP-Programmer ist abgezogen.
Gut.

> Wenn es einen HW-Stack gibt, dann brauche ich mich ja darum nicht zu
> kümmern!?
Richtich! Allerdings schon isofern, als dass es nur drei Stack Level 
gibt und dementsprechend geschachtelte Funktionen (inkl. Interrupt 
Handler!) sehr wohl-überlegt eingesetzt werden sollten. Dürfte in Deinem 
Fall allerdings noch problemlos gehen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um ehrlich zu sein: Ich bin mit meinem Latein am Ende.
Auch das Datenblatt gibt nicht mehr her.

Ohne einen Tiny15 hier zu haben, wird das wohl nichts mit
der weiteren Fehlersuche.

Einen hab ich noch: Schmeiss mal das ganze Gerödel mit dem ADC
raus. Ich weiss schon, an PB0 liegt eigentlich der Analog
Comperator, sollte daher nichts mit dem ADC zu tun haben.
Aber um Fehlersuche zu betreiben hilft wohl nur noch konsequentes
Abspecken des Codes.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Um ehrlich zu sein: Ich bin mit meinem Latein am Ende.
> Auch das Datenblatt gibt nicht mehr her.
Nicht nur Du...

@Timo:
Hast Du mal versucht, den Pin (ohne den ganzen Timer-Kram) mal 
anzusprechen?

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tja...

ich habe abgespeckt und alles was mit dem ADC zu tun hat 
rausgeschmissen.

Damit funktioniert die Multiplexerfunktion.
Die Ursache hat wohl was mit dem ADC zu tun, was den Simulator aber 
offensichtlich nicht stört.

Das "was" ist allerdings noch offen! Da muß doch noch irgend wo ein 
Fehler sein?


Der Code ohne jegliche ADC-Unterstützung sieht damit jetzt so aus
;  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
;
;       Farbansteurung mit RGB-LED
;
;      ein PWM-Signal im Multiplexingbetrieb aus 3 LED
;
;  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
;
;
;
;     Belegung Tiny15
;    ---------------
; PB0  Ausgang MUX b
; PB1    Ausgang PWM
; PB2  Ausgang MUX a
; PB3  Eingang Taster
; PB4    Eingang Poti-ADC
; PB5  RESET




.include "tn15def.inc"

.def WRegister      =    R16
.def LEDNr        =    R17
.def RDummy        =    R18
.def RDummy2    =  R19
.def RHelligkeit0    =    R20
.def RHelligkeit1    =  R21
.def RHelligkeit2    =    R22
.def fPWM_LED1    =  R23
.def fPWM_LED2    =  R24
.def fPWM_LED3    =  R25
.def RStore      =  R26

; Vorgaben für Ausgangshelligkeit
.equ Vorgabe_fPWM_LED1  =  0x80
.equ Vorgabe_fPWM_LED2  =  0x80
.equ Vorgabe_fPWM_LED3  =  0x80


; Vorgaben für Tasterentscheid
; 0= beide gedrückt  0xA7=Taster2 gedrückt 0xF2= Taster1 gedrückt
.equ Vorgabe_T1_high  =  0xE9
.equ Vorgabe_T1_low    =  0xDC
.equ Vorgabe_T2_high  =  0xDC
.equ Vorgabe_T2_low    =  0x8C
.equ Vorgabe_T12_high  =  0x64





.org  $000

rcall Init
rjmp Main

    .org $003  ;Timer1 Compare Match
      nop  
    .org $004  ;Timer1 Overflow handler
      rjmp TIM1_OVF
    .org $005  ;Timer0 Overflow handler
      nop


.org $009

Init:


    ldi    RDummy,0x74    ; Oszillator kalibrieren
    out    OSCCAL,RDummy
      
    ldi   WRegister,0x00|(1<<PB0)|(1<<PB1)|(1<<PB2)|(00<<PB3)  ; PB1 als Ausgang
      out   DDRB,WRegister

      ldi   WRegister,(0<<OCIE1A)|(1<<TOIE1)|(0<<TOIE0) ;Interruptregister schalten
      out   TIMSK,WRegister

    ;PWM einstellen

            ldi   WRegister,(0<<CS13)|(1<<CS12)|(0<<CS11)|(1<<CS10)|(1<<PWM1)|(1<<COM1A1)|(1<<COM1A0)|(0<<CTC1)  ; invertierte PWM einsschalten -> Geschwindigkeit CK
      out   TCCR1,WRegister
  

      ldi   WRegister,0xFF  ;PWM-Frequenz
    out   OCR1B,WRegister


      ldi   WRegister,0x80  ;Pulsweite einstellen
      out   OCR1A,WRegister
    ;ADC



    
    sei        ; Interrupt aktivieren
    ret            ;zurückspringen

Main:
    rjmp   Main



TIM1_OVF:



Helligkeit_Einstellen:  ;
  
    rcall  LED_MUX
  


    reti          ;Rücksprung aus Interrupthandler







; ############################################################################
;
;        SUB-ROUTINEN
;
; ############################################################################

; -------------------LED muxen ---------------------------
LED_MUX:
    inc   LEDNr      ; auf nächste LED schalten
    cpi   LEDNr,3  ; wenn LED>> 2 dann auf 0 rücksetzen
    BRLO   LED_Out
    ldi   LEDNr,00
LED_Out:

    clr    RDummy      ; Register auf Default setzen
    sbrc  LEDNr,0      ;ist LEDNr[0]=1 -> nein, dann überspringen
    SBR    RDummy,(1<<PB0)
    sbrc  LEDNr,1      ;ist LEDNr[1]=1 -> nein, dann überspringen
    SBR    RDummy,(1<<PB2)


    out   PORTB,RDummy  ; ausgeben
    ret          ;Rücksprung 
; --------------------------------------------------------


Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch wenn's daran wahrscheinlich nicht liegt: Die MUX-Bits stehen 
nicht im ADCSR, sondern im ADMUX...

Autor: Timo R. (tire)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe noch spasseshalber den Schaltplan angehängt, damit 
(hoffentlich) klar wird, wozu die ADCs benötigt werden.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bildformate!
Ein Schaltplan als 300K-JPEG ist die denkbar schlechteste Variante! Und 
dann auch noch mit schwarzem Hintergrund. Schlimmer gehts nimmer.

Autor: Timo R. (tire)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

sorry für's Bildformat - ich dachte ich tu was gutes....

Ich habe den "Fehler" gefunden.
Nachdem ich alle ADC-Anweisungen rausgeschmissen hatte, ging es ja. Da 
habe ich mir die Registerwerte nochmal genauer angesehen und korrigiert 
- und siehe da, es geht!

Ich finde es nur komisch, wie durch falsche Initialisierung ganz andere 
Stellen des Controllers beeinflusst werden -zumal das eine mit dem 
anderen scheinbar nichts zu tun hat.

Der Komplettcode nochmals im Anhang.

Gruß

Timo

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.