www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik noch probleme mit attiny 12


Autor: Jürgen Kreutz (jk2010)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi !

nachdem mir hier etliche Hilfestellung und Beispiele gegeben haben, hier 
mal mein Beispielprog.

Es funktioniert bis auf die Interruptroutine.
Möchte, wenn ein gültiges Signal (0,7 bis 2,3 ms) anliegt, eine Lampe 
(im Text search auf pb4) schalten.
Aber es funktioniert net.

Vielleicht seid ihr so nett und schaut mal über den Quältext ;))) (Ist 
mein erstes Prog in Assembler seit der 64er Ära)
.NOLIST
.INCLUDE "tn12def.inc"
.LIST

;Konstanten

.equ clock=1200000      ;Taktfrequenz 1,2MHz
.equ irqfreq=10000      ;Interruptfrequenz 10kHz
.equ Tail=pb0        ;Portpin Heckleuchte
.equ impuls=pb1        ;Portpin ImpulsRC_eingang
.equ U_canopy=pb2      ;Portpin Kanzel oben
.equ L_canopy=pb3      ;Portpin Kanzel unten
.equ search=pb4        ;Portpin Suchscheinwerfer
.equ RC_min=13        ;minimal gültige Impulsbreite (0,7ms)
.equ RC_max=43        ;maximal gültige Impulsbreite (2,3ms)
.equ RC_aus=26        ;Schaltschwelle aus 1,3ms
.equ RC_ein=30        ;Schaltschwelle ein 1,7ms
.equ RC_neutral=28      ;neutralstellung fällt hier aus, da nur an oder aus


.equ RISING   = 0x03    ;steigende Flanke
.equ FALLING   = 0x02    ;fallende Flanke


;berechnete Konstanten

;.equ tim0zu=clock/irqfreq  ;Zählumfang Timer0

.def NULL    =r0
.def saveSREG  =r16  
.def Timer1    =r17
.def Timer2    =r18
.def Timer3    =r19
.def temp     =r20     ;Tempregister
.def puls     =r21     ;Pulslänge
.def highLow   =r22     ;High oder Low Flanke
.def LED_Port  =r23     ;Status sichern





;Angeschlossene LED´s
;PB0 Tail
;PB2 upper canopy
;PB3 lower canopy
;PB4 Suchscheinwerfer

;PB1 Input Funke



;******************************************************************
.cseg              ;CODE segment
.org 0
  rjmp  init        ;resethandler
.org INT0addr
  rjmp  EXT_INT_handler        ;Interrupthandler



.org $6
init:   
;Kalibrierung interne RC
  ldi   ZL, low(flashend*2)
  ldi   ZH, high(flashend*2)
  lpm
  ser   ZL
  cpse   r0, ZL
  out   OSCCAL, r0
;Kalibrierungsende

  in    NULL, 0x00

  ldi    LED_Port,0b111101
  out    DDRB,LED_Port       ;set portb as output Pin 1 is in
  ldi    LED_Port, 0b111111
  out    PORTB, LED_Port      ;set portb outputs all off PB1 Pull_up active
  ldi   highLow, RISING     ;highLow initialisieren. 1. Flanke ist eine HIGH
  out   MCUCR, highlow
  ldi   temp, (1<<INT0)       ;Enable externen Interrupt
  out   GIMSK, temp
 
                  ;Konfiguriere externen Interrupt

  
  ldi    temp, (1<<CS01) | (1<<CS00)  ;teiler 64
  out    TCCR0,temp
  out    TCNT0, NULL

  sei               ;Enable Interrupts


start:
; LED_Port ist noch $FF also alle Lichter aus!
  cbr   LED_Port, (1<<Tail) | (1<<U_Canopy)     ; Tail + Upper_Canopy
  out    PORTB,LED_Port              ; write to port
  rcall   wait_70ms      
  sbr    LED_Port, 1<<U_Canopy
  out    PORTB,LED_Port      ;write to port
  rcall   wait_200ms      
  cbr   LED_Port, (1<<U_Canopy) | (1<<Tail) ;set LED_Port bits  tail and upper-canopy
  out    PORTB,LED_Port      ;write to port
  rcall   wait_70ms
  sbr    LED_Port, (1<<Tail) | (1<<U_Canopy) ; set LED_Port bits off 
  out    PORTB,LED_Port      ;write to port
  rcall   wait_200ms
  rcall   wait_200ms
  rcall   wait_70ms        

  cbr    LED_Port, 1<<L_Canopy   ;set LED_Port bit lower_canopy
  out    PORTB,LED_Port      ;write to port
  rcall   wait_70ms

  sbr    LED_Port, 1<<L_Canopy   ;set LED_Port bits off
  out    PORTB,LED_Port      ;write to port
    rcall   wait_200ms
  rcall   wait_200ms  
  rcall   wait_70ms
  
rjmp  start

EXT_INT_handler:
  in     saveSREG, SREG
  out   TCNT0, NULL        ;Counter resetten
  cpi   highLow, RISING     ;Der Puls ist eine steigende Flanke
  brne   FALLING_EDGE       ;Wenn eine fallende Flanke, spring zur Routine
  ldi   highLow, FALLING     ;Nächster Puls ist eine Fallende Flanke
  out   MCUCR, highlow
  out   SREG, saveSREG
reti

FALLING_EDGE:
  in     saveSREG, SREG
  ldi    puls, TCNT0
  cpi    highlow, FALLING
  brne  Fehler_Flanke
  
  ldi   highLow, RISING     ;Nächser Puls ist eine Steigende Flanke
  out   MCUCR, highlow
  rcall   checkPuls         ;auswertung der Pulslänge
  
Fehler_Flanke:
  out   SREG, saveSREG
reti


checkPuls:
    cpi     puls, RC_min      ;kleiner als Schaltschwelle ->raus
    brlo    Fehler
  cpi    puls, RC_max      ;größer als max ->raus
  brsh  Fehler
  cbr   LED_Port, 1<<search      ;OK, dann Scheinwerfer an und raus
ret                           
 
Fehler:
  sbr LED_Port, 1<<search
ret    



wait_200ms:
          ldi  Timer1, $02
WGLOOP0:  ldi  Timer2, $C6
WGLOOP1:  ldi  Timer3, $C9
WGLOOP2:  dec  Timer3
          brne WGLOOP2
          dec  Timer2
          brne WGLOOP1
          dec  Timer1
          brne WGLOOP0
; ----------------------------- 
; delaying 18 cycles:
          ldi  Timer1, $06
WGLOOP3:  dec  Timer1
          brne WGLOOP3
      ret
; ============================= 

wait_70ms:  
; ============================= 
;    delay loop generator 
;     84000 cycles:
; ----------------------------- 
; delaying 83997 cycles:
          ldi  Timer1, $99
WGLOOP4:  ldi  Timer2, $B6
WGLOOP5:  dec  Timer3
          brne WGLOOP5
          dec  Timer1
          brne WGLOOP4
; ----------------------------- 
; delaying 3 cycles:
          ldi  Timer1, $01
WGLOOP6:  dec  Timer1
          brne WGLOOP6
      ret
; ============================= 
; ----------------------------
; wait subroutine 
; ----------------------------
;wait:    
;  ldi  count1,155    

;d1:
;  ldi  count2,155    

;d2:
;  dec  count2      
;  brne  d2  
;  dec    count1      
;  brne   d2      
;  ret
; ----------------------------        

Grüße
Jürgen

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Jürgen,

beim schnellen Drüberlesen fällt mir erstens auf, dass Du TCNT0 in 
Deiner Interrupt-Routine auf NULL setzt, ohne vorher den Zähler-Inhalt 
zu lesen. Ein paar Zeilen weiter versuchst Du (sollte statt ldi auch 
in heißen!!), den Zähler-Inhalt zu lesen, der dürfte dann aber (bei 
etwa 5,3ms/Zähler-Tic) noch Null sein!

EXT_INT_handler:
  ...
  out   TCNT0, NULL        ; ????
  ....
  reti

FALLING_EDGE:
  ...
  ldi    puls, TCNT0
          ; Du hast Deinen Zähler doch gerade genullt!
          ;  ... zudem müsste es in heißen!

Drittens ist mir nicht klar, wieso Du für EXT_INT_handler und für 
Falling_Edge das gleiche Register ("saveSREG") zum Sichern des 
Status-Regs benutzt.

Viertens: Statt
          in NULL, 0x00
                 meinst Du sicher clr NULL
                            oder  /ldi reghigh, 0/
                                  /mov NULL,reghigh/

Wie gesagt, ich habe nur ganz schnell über Deinen Code gesehen, es 
können durchaus noch mehr Käfer drin sein!

Gruß

Fred

Autor: Jürgen Kreutz (jk2010)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi !

dank Dir für die Antwort.
Wenn ich mich nicht verrechnet habe sind
1,2MHz    1 clk  0,000000833s  ~0,83µs

prescale 64

1,2MHz / 64   1 clk  0,000053333s  ~53µs  ~0,053ms

Den Timer setze ich bei steigender Flanke auf null, weil ich die Länge 
des Impulses messen möchte. Bei der Funke von 0,7ms minimum bis 2,3ms 
maximum
Liegt der puls dazwischen ist er gültig. Dann LED an.


__|TCCR0=0 ----|__lesen TCCR0 für die Länge

Vielleicht bin ich ja betriebsblind. habe ich etwas übersehen oder einen 
Denkfehler ??


Habe das gleiche Register zum Sichern gewählt, weil ja der Puls 
unterschiedlich lang sein kann. Vor verlassen der jeweiligen Routine 
wird SREG ja wieder restauriert.


Grüße

Jürgen

Autor: fubu1000 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
du dec in der Schleife Timer3 der nit gesetzt ist, müsste wohl eher 
Timer2 sein.


wait_70ms:
; =============================
;    delay loop generator
;     84000 cycles:
; -----------------------------
; delaying 83997 cycles:
          ldi  Timer1, $99
WGLOOP4:  ldi  Timer2, $B6
WGLOOP5:  dec  Timer3               <--------------- Fehler
          brne WGLOOP5
          dec  Timer1
          brne WGLOOP4
; -----------------------------
; delaying 3 cycles:
          ldi  Timer1, $01
WGLOOP6:  dec  Timer1
          brne WGLOOP6
      ret
; =============================


GRUSS fubu

Autor: Jürgen Kreutz (jk2010)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Fubu !

Dank Dir, Du hast recht, ist wohl beim tippern verunglückt.

Gruß

Jürgen

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jürgen,

Deine TimerTic-Länge stimmt, ich habe mich versehen.

Aber:
> __|TCCR0=0 ----|__lesen TCCR0 für die Länge
Was Du damit meinst, verstehe ich nicht.

Du springst aus Deinem INT0-Handler, wo Du TCNT0 auf 0 gesetzt hast, 
nach FALLING_EDGE, wo Du TCNT0 nach "puls" einlesen willst (falsche 
Syntax!). Dann wertest Du "puls" aus. "puls" ist dann aber höchsten 
eins!

Ich bin nicht sicher, ob Du nicht ein grundsätzliches Problem mit dem 
Verständnis der Syntax hast; Du verwechselst mehrmals in mit ldi 
usw.

Gruß

Fred

Autor: Jürgen Kreutz (jk2010)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi !

Also, wie beschrieben, mein erstes Assemblerprogramm seit der Steinzeit.
ldi ist für Register R16-R31 load immediately.
in bzw. out für SFR Register. Liege ich da richtig?

Fällt mir noch ein bisschen schwer, der Wiedereinstieg.


Deshalb, Danke für Euer Engagement.

Grüße und schönen Sonntag vom

Käfersuchenden

Jürgen


@fred:   wenn die steigende Flanke kümmt, TCNT0=0
         wenn fallende, Impuls ende, TCNT0 auslesen

zulässiger Bereich 0,7 bis 2,3 ms

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.