www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega8: Counter1 tut nicht so, wie ich will


Autor: Frank Muen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte gerne den Abstand zwischen zwei mal (entprellter) Taster 
drückn (angeschlossen an PORTB.0) messen:
.include  "AVR.H"
;------------------------------------------------------------------------
;Reset and Interruptvectoren  ;VNr.  Beschreibung
begin:  rjmp  main  ;1     POWER ON RESET
  reti    ;2     Int0-Interrupt
  reti    ;3     Int1-Interrupt
  reti    ;4     TC2 Compare Match
  reti    ;5     TC2 Overflow
  rjmp  on_ICP  ;6     TC1 Capture
  reti    ;7     TC1 Compare Match A
  reti    ;8     TC1 Compare Match B
  rjmp  on_TC1  ;9     TC1 Overflow
  reti    ;10    TC0 Overflow
  reti    ;11    SPI, STC Serial Transfer Complete
  reti    ;12    UART Rx Complete
  reti    ;13    UART Data Register Empty
  reti    ;14    UART Tx Complete
  reti    ;15    ADC Conversion Complete
  reti    ;16    EEPROM Ready
  reti    ;17    Analog Comperator
  reti    ;18    TWI (I²C) Serial Interface
  reti    ;19    Store Program Memory Ready
;------------------------------------------------------------------------


;Start, Power ON, Reset
main:  ldi  r16,lo8(RAMEND)
  out  SPL,r16  ;Init Stackpointer LO
  ldi  r16,hi8(RAMEND)
  out  SPH,r16  ;Init Stackpointer HI

  sbi  UCSRB,4  ;UCR=UCSRB=0x0B RXEN=Bit4 RX aktivieren
  sbi  UCSRB,3  ;UCR=UCSRB=0x0B UDRE=Bit3 TX aktiv
  ldi  r16,3686400/(38400*16)-1  ;Baudrate 38400 einstellen
  out  UBRRL,r16

  ldi  r16,0b00000001
  out  DDRB,r16
  ldi  r16,0b00000001
  out  PORTB,r16

  ldi  r16,0
  out  TCCR1A,r16
  ldi  r16,0b01000001
  out  TCCR1B,r16  ;Timer1 setup Clock
  ldi  r16,0b00100100
  out  TIMSK,r16  ;Interrupt Timer1 bei overflow

  ldi  r26,0
  ldi  r27,hi8(RAMEND)
  subi  r27,2
  ldi  r28,0
  ldi  r29,hi8(RAMEND)
  subi  r29,2
  sei    ;erlaube Interrupts
;------------------------------------------------------------------------
mainloop:  wdr

  rjmp  mainloop
;------------------------------------------------------------------------
putChar:  sbis  UCSRA,5  ;USR Bit5 =  UDRC
  rjmp  putChar  ;warten, bis UDR bereit
  out  UDR,r16
  ret    ;zurück zum Hauptprogramm
;------------------------------------------------------------------------
on_TC1:  cli
  push   r16
  ldi  r16,129
  rjmp   putChar
  pop  r16
  sei
  reti

;------------------------------------------------------------------------
on_ICP:  cli
  push  r16
  ldi  r16,ICR1L
  rjmp   putChar
  ldi  r16,ICR1H
  rjmp  putChar
  pop  r16
  sei
  ret
Meine Idee ist:
Bei jedem Overflow des Counter1 wird ein Interrupt ausgeführt, dieser 
gibt 0h81 an die serielle Schnittstelle aus. Das scheint auch ganz gut 
zu funktionieren.

Wenn der Taster gedrückt wurde (ich würde hier gerne auf die steigende 
Flanke triggern), soll der aktuelle Wert des Counters ausgegeben werden. 
Hier hakt es jedoch und der µC gibt nur Mist aus (meist nur ein Wert, 
und zwar 0h26). Kann mir da jemand helfen?

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was mir beim schnellen durchsehen aufgefallen ist ;)
> rjmp   putChar
"rcall putChar" ist bestimmt besser...

in den ISRs solltest du das SREG sichern, kannst ja z.B. eins der 
Register r2-r15 entbehren:
.def sreg_bak = R2
;...
on_TC1:  
    ; cli, sei  sind in den ISR i.d.R. unnoetig!
    IN sreg_bak, SREG
    push   r16
    ldi  r16,129
    RCALL   putChar
    pop  r16
    OUT SREG, sregbak
    reti
- ich hab die Zugriffsreihenfolge bei den 16-Bit Registern (TCNT1, ICR1, 
etc.) grad nicht im Kopf, schau das lieber nochmal nach ;)
> sbis  UCSRA,5
"sbis UCSRA, UDRE " liest sich besser, benutz das ruhig bei allen 
I/O-Registern

hth. Jörg

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

Bewertung
0 lesenswert
nicht lesenswert
> ldi  r16,ICR1L
> rjmp   putChar
> ldi  r16,ICR1H
Du weißt, was ldi macht? Dann weißt Du vermutlich auch, dass ldi hier 
sicher nicht das macht, was Du willst. Versuch es mal mit
in r16, ICR1L

Übrigens: ICR1L hat die Adresse 0x26. Jetzt weißt Du auch, wo die 26 
herkommt...

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

Bewertung
0 lesenswert
nicht lesenswert
> on_TC1:  cli
> ...
> on_ICP:  cli
Das cli kannste Dir sparen. Das macht der Controller automatisch beim 
Einsprung in den Interrupt-Vektor.

> sei
> ret
Und das ebenfalls unsinnig. Dafür gibts reti.

Also: Das I-Bit im SREG wird beim Sprung in einen Interrupt-Vektor 
automatisch von der Hardware gelöscht. Zum Rücksprung aus dem Interrupt 
Handler gibt es den Befehl reti, der im Unterschied zu ret (ohne i) 
dafür sorgt, dass beim Rücksprung das I-Bit wieder gesetzt wird.

Autor: Frank Muen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich danke euch!!! Er macht jetzt das, was ich will! VIELEN DANK!

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.