Forum: Mikrocontroller und Digitale Elektronik Wartezeit für nächstes Zeichen oder Abbruch - sichere Software Uart AVR Tiny Assembler


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Frank (Gast)


Bewertung
0 lesenswert
nicht lesenswert
An einem Tiny48 hängt ein serieller Funkchip, wenn was auf dem Äther los 
ist löst PCINT5 das einlesen aus.

Funktionierte früher gut als ich noch Handys ausgelesen habe, geht jetzt 
im Test auch solange ich am Ende ein ccr setze.

Sollte aber irgenwie kein ccr gesendet werden oder nicht erkannt werden 
wegen Störung, Reichweite oder fremden Sender -> Endlosschleife bei 
getchar1

Was mache ich jetzt? Timer oder Delay-Counter setzen um ne halbe Sekunde 
zu warten ob noch ein Buchstabe kommt?

Grüße, Frank



UART_in füllt eine Adresse im Sram - ccr ist Abbruch:
1
UART_in:        ; lesen komplett, aber schreibt  
2
  push  r16            ; nur bis Puffer voll in Speicher!
3
  clr    r16
4
UART_in2:
5
  rcall  upUartIn
6
  cpi    uart,  ccr  ; Ende erreicht?
7
  breq  last_in_char
8
  cpi    uart,  clf  ; clf ignore
9
  breq  UART_in2
10
  cpi    r16,  25
11
  brge  UART_in2
12
  inc    r16
13
  st    y+,  uart
14
  rjmp  UART_in2          ;ueberspringen:  
15
last_in_char:
16
  clr    r16
17
  st    y,  r16
18
  pop    r16
19
  ret

upUartIn holt die Zeichen rein:
1
upUartIn:    
2
  push  r17
3
  ldi     r17,9    ; 8 data bit + 1 stop bit
4
getchar1:   
5
  sbic    PINA,5    ; Wait for start bit
6
  rjmp    getchar1
7
  rcall  UART_delay  ; 0.5 bit delay
8
getchar2:   
9
  rcall  UART_delay  ; 1 bit delay
10
  rcall  UART_delay
11
  clc      ; clear carry
12
  sbic    PINA,5    ; if RX pin high
13
  sec      ; set carry
14
  dec     r17    ; If bit is stop bit
15
  breq    getchar3  ; return
16
;else
17
  ror     uart    ; shift bit into uartbyte
18
  rjmp    getchar2  ; go get next
19
getchar3:   
20
   pop    r17
21
  ret

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Du brauchst "drumrum" einen "Timeout-Zähler", der in einem 
Timerinterrupt eine Variable herunterzählt und wenn die 0 ist brichst du 
den Empfang ab. Und bei jedem empfangenen Zeichen setzt du den Zähler 
auf einen Wert, der einer halben Sekunde entspricht.

Oder viel, viel besser: du stellst deinen Programmierstil auf eine 
Automatenschreibweise um.
Die Hauptschleife wird dauernd möglichst schnell durchlaufen. Und pro 
Durchlauf wird geschaut, ob was an der seriellen Schnitte angekommen 
ist. Wenn ja: verarbeiten. Wenn nein: weiter. "Weiter" bedeutet z.B. 
Tastenabfrage, Zähler verwalten, Abläufe koordinieren. Auf diese Art 
wird der Controller nicht durch das "Warten" auf irgendwas blockiert, 
weil ja nie "gewartet" wird...

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Oder viel, viel besser: du stellst deinen Programmierstil auf eine
> Automatenschreibweise um.

Oder man macht die SW-UART als Interrupt.
Oder man nimmt einfach den ATmega48 mit HW-UART.

von Frank (Gast)


Bewertung
0 lesenswert
nicht lesenswert
soldele danke für die schnellen Antworten ;)

habe jetzt ein Sekundendelay eingesetzt das prüft ob ein Zeichen 
empfangen wird und dann sofort beendet.

Kein Zeichen -> eine Sekunde warten und rausspringen
Start-Bit -> delay abbrechen und Zeichen einlesen
1
upUartIn:    
2
  push  r23
3
  ldi     r23,9        ; 8 data bit + 1 stop bit
4
5
  rcall  uartin_dly
6
7
  sbic    PINA,5        ; Wait for start bit
8
  rjmp  upUartIn_abbruch
9
10
  rcall  UART_delay      ; 0.5 bit delay
11
 
12
getchar2:   
13
  rcall  UART_delay      ;  1 bit delay
14
  rcall  UART_delay
15
  clc              ;  clear carry
16
  sbic    PINA,5        ;  if RX pin high
17
  sec              ;  set carry
18
  dec     r23          ;  If bit is stop bit
19
  breq    getchar3      ;   return
20
;else
21
  ror     uart        ;   shift bit into uartbyte
22
  rjmp    getchar2      ;   go get next
23
24
getchar3:   
25
   pop    r20
26
   pop    r23
27
  ret
28
29
upUartIn_abbruch:
30
  ldi     uart, ccr
31
   pop    r23
32
  ret


Ihr habt natürlich recht man könnte das auch Interrupt oder 
Hardware(interrupt) steuern.

Bei dem Projekt ist das aber nicht notwendig, ein mal im Jahr verbindet 
sich jemand mit dem System um Daten auszulesen und Einstellungen zu 
ändern.
In der kurzen Zeit muss das System dann nichts anderes machen. Hier wird 
eh nur alle 60 Sekunden der Taupunkt bestimmt und evtl. ein Relais 
geschaltet.

So ich werde jetzt einen schönen alten AT Befehlsatz für die 
Kommunikation aufbauen - war mal wieder schön in die niederen Gefilde 
der Uart zu kucken ;)

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]
  • [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.