mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik IR-FB-Empfänger, mal drüber schauen bitte


Autor: Ben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

MEIN AUFBAU:
-STK 500
-Mega8 4mHz ext. Oszillator (PB6)
-USB FTDI 232BM Schnittstelle (PD0/PD1)
-IR-Empfänger TSOP 1738 (PB0)


FUNKTIONSBESCHREIBUNG:
Habe mir einen Code geschrieben der per
Input Capture die abstände zwischen den flanken messen soll,
hierzu habe ich den Timer1 verwendet mit einem 1/64 Prescaler.

Das Hauptprogramm prüft ledeglich zwei flags und gibt dessen status an 
portC auf LEDs aus. Abhängig von den Flags schiebt es daten aus zwei 
registern auf den stack oder fängt an zuvor auf dem stack abgelegte 
daten über usb zu senden.

Der Input-Capture-Interrupt sichert den MEsswert in
zwei registern, toggelt die Flanke, stellte den timer auf null und setzt 
ein StatusFlag um zu signalisieren das sich die werte in den besagten 
zwei registern geändert haben. Sobald der Interrupt abgearbeitet ist
schiebt das hauptprogramm den inhalt der register auf den Stack (hierbei 
wird für jedes PUSH ein zähler um eins erhöht) und löscht das Flag 
wieder.

Der Timer-Overflow-Interrupt setzt lediglich ein zweites status Flag
das signalisiert das der IR-Code vorbei ist (da zu viel zeit 
verstrichen)
und die MEsswerte vom Stack per USART/FTDI-USB an den rechenr gesendet 
werden können (für jedes POP wird der zähler wieder um eins veringert).
Es wird so lange gesendet bis der zähler auf null ist.


MEIN PROBLEM:
erstens kommen die Daten nicht alle am PC an, probleme mit dem FTDI 
konnte ich auschliessen da über den RS232-Spare das selbe passiert.
zweitens toggelt mein Flag zum Senden der Daten in unregelmässigen 
abständen jedoch deutlich sichtbar.

Denke mal das ich irgendwo im Programm einen denkfehler mache und 
irgendwas nicht so funktionieren kann....bin dankbar für 
verbesserungsvorschläge die das ganze zum laufen bringen


MEIN uC PROGRAMM:
(denke es ist ausreichen kommentiert)
.include "m8def.inc"

.def temp   = r16  ;Allgemeines Arbeitsregister
.def edge   = r17  ;register für Flankenwechsel
.def ICLow  = r18  ;register für LowByte von ICR1
.def ICHigh = r19  ;register für HighByte von ICR1
.def state  = r20  ;Flag register
.def count  = r21   ;Datenzähler


; BAUDRATE BERRECHNEN
.equ F_CPU = 4000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
.equ UBRR_VAL   = ((F_CPU+(BAUD+600)*8)/((BAUD+600)*16)-1)  ; clever runden
;DIE 600 IST EIN KORREKTURWERT wegen des Quarz

.org 0x000 rjmp start     ;Reset sprungpunkt
.org 0x005 rjmp TIC_Handle  ;Input-Capture-Interrupt Handle
.org 0x008 rjmp TO_Handle  ;Timer-Overflow-Interrupt Handle


start:

;STACK-INIT
ldi temp, LOW(RAMEND)
out SPL,  temp
ldi temp, HIGH(RAMEND)
out SPH,  temp


; Baudrate einstellen
ldi temp,  HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp,  LOW(UBRR_VAL)
out UBRRL, temp

; Frame-Format: 8 Bit
ldi temp,  (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp            

; TX aktivieren 
ldi  temp,  1<<TXEN
out UCSRB, temp  


;TIMER init & starten
ldi temp,   (1<<TICIE1)|(1<<TOIE1)        ;Input-Capture & Overflow INTERRUPT
out TIMSK,  temp
ldi temp,   (1<<CS10)|(1<<CS11)|(1<<ICES1)    ;Prescaler 1/64 - Input-Capture L-H Flanke
out TCCR1B, temp

;PortB -> EINGANG
ldi temp, 0x00
out DDRB, temp

;PortC -> AUSGANG
ldi temp, 0xFF
out DDRC, temp

ldi state, 0x00    ;Flags löschen
ldi count, 0x00    ;Datenzähler auf NULL setzen


;GLOBAL-INTERRUPT-ENABLE
sei 





;HAUPTPROGRAMM
main: 
  ;Flags an PortC per LEDs sichtbar machen
  out  PortC, state 

  ;Prüfen ob Flag für neuen Messwert gesetzt
  sbrc state, 0
  rjmp save

  ;Prüfen ob Flag für Code-Ende gesetzt
  sbrc state, 1
  rjmp send

  ;von vorn das ganze
  rjmp main


;Daten auf Stack sichern  
save:
  push ICLow    ;ICLow auf stack schieben
  inc   count    ;Datenzähler um eins erhöhen

  push ICHigh    ;ICHigh auf stack schieben
  inc  count    ;Datenzähler um eins erhöhen

    ldi  state, 0x00  ;Flags Löschen

  rjmp main ;zurück zum anfang

send:

  cpi  count, 0x00  ;Prüfen ob Messdaten vorhanden
  breq main      ;wenn nicht dann zum Anfang springen
  

SO2:
  sbis UCSRA, UDRE  ;Prüfen ob USART bereit
  rjmp SO2

  ;Daten senden...
  pop  temp      ;Messwert vom stack holen
  out  UDR,   temp  ;Messwert senden
  dec  count      ;Datenzähler um eins veringern

  ldi  state, 0x00  ;Flags löschen

  rjmp send      ;nächstes Byte...



;INTERRUPT-HANDLES

;Timer/Counter1 Input-Capture-Interrupt
;Flanke hat gewechselt
TIC_Handle:

  ;TCNT1 auf Null stellen
  ldi  temp,   0x00
  out  TCNT1H, temp
  out  TCNT1L, temp

  ;Input-Capture-Fklanke wechseln
  ;(messung von Flanke zu Flanke
  ldi  temp,   1<<ICES1
  in   edge,   TCCR1B 
  eor  edge,   temp
  out  TCCR1B, edge

  ;Input-Capture Messwert sichern
  ;register "ICLow" und "ICHigh"
  in   ICLow,  ICR1L
  in   ICHigh, ICR1H  

  ;Daten zum sichern bereit
  ;bit 0 register "state"
  ldi  state, 1<<0

  reti


;Timer/Counter1 Overflow-Interrupt
;Code ist vorbei
;Signal zum senden geben 
;bit 1 register "state"
TO_Handle:
  ldi  state, 1<<1 
  reti

Hoffe ich habs mit der beschreibung nicht übertrieben und mit den
Komentaren und so...

gruß und besten dank im vorraus
der Ben

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>stellte den timer auf null

Da hat jemand ICP nicht richtig verstanden:
Beim ICP lässt man den Timer durchlaufen.
Sobald der ICP-Interrupt auftritt sichert man den Timerwert (der im ICR 
steht) in einer Variable. Um die Zeit zwischen zwei Flanken zu 
errechnen, muss man dann nur den älteren Wert vom neueren subtrahieren. 
Den Timer lässt man schon in Ruhe weiter laufen.

Da ich von ASM wenig Ahnung habe, habe ich mir dein Programm nicht 
angeguckt.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@STK500-Besitzer (Gast):
>Da hat jemand ICP nicht richtig verstanden:
>Beim ICP lässt man den Timer durchlaufen.

naja, man muß nicht alles gleich zum Dogma erheben. ;-)
Wenn die zeitlichen Verhältnisse es zulassen, spricht auch nichts gegen 
seine Lösung.
Allerdings würde ich mir dann in jedem Fall erstmal den Capturewert 
besorgen, bevor ich am Timer rumprogrammiere und vielleicht damit einen 
Captureinterrupt erzeuge.
Vor verlassen der IRQ-Routine würde ich deshalb auch das dessen 
Interruptflag vorsichtshalber löschen.

Das vermutlich wichtigste aber: Du sicherst SREG nicht, veränderst aber 
mit eor die Flags...

Gruß aus Berlin
Michael

Autor: Ben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

habe zum ersten mal was mit dem ICP gemacht, deswegen
hab ich das hier auch reingestellt.....um die fehlenden lücken zu 
füllen^^

Zeitlich müsste alles hinkommen, habe den prescaler so gewählt das ich
die längste vorgesehene zeitspanne messen kann und ebenso die 
kleinste...

@Michael
muss ich das SREG immer sichern bei interrupts?
habe das auch noch nicht ganz durchblickt...
Die Flags sind ja von mir selbst also nicht aus dem SREG
sonder r20....vielleicht hab ich ja generell bei
der registerwahl einen fehler gemacht

danke schonmal
für die infos

gruß ben

Autor: Ben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wäre echt toll wenn da noch ein
paar antworten mehr kämen....

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.