Forum: Mikrocontroller und Digitale Elektronik Problem mit asm Routine


von Bruno M. (brumay)


Lesenswert?

Ich verzweifle bei einer relativ einfachen asm - Routine.

Hintergrund: Ein kleines Programm für eine Funkfernsteuerung mit RFM12. 
Es werden immer 7 Bytes übertragen, wobei das erste als Startbyte "S" 
angesehen wird. Die restlichen 6 Bytes sind einstellbar. Diese Bytefolge 
wird zweimal gesendet und bei richtigem Empfang soll ein Befehl 
ausgeführt werden. So weit die Theorie.

Grundsätzlich macht das Programm auch das, was es machen soll, 
allerdings nur dann, wenn ich in der Vergleichschleife eine UART Ausgabe 
anspringe. Lasse ich die weg, spielt das Programm verrückt. Dabei ist es 
auch egal an welcher Stelle dieser Vergleichschleife ich den Sprung 
einbaue.
1
;Empfänger abfragen
2
receive:
3
  ldiw  Y, Eingang          ;Y -Pointer auf 1. Byte
4
  ldi    datacnt, 10          ;Anzahl Datenbytes +4
5
  rcall  rf12_rxdata_rec        ;10 empfangene Bytes werden im SRAM abgelegt
6
;prüfen, ob Startbyte = S
7
S_test:
8
  ldiw  Y, Eingang          ;Y - Pointer wieder auf Anfang setzen
9
S_test_loop:  
10
  ld    temp, Y+          ;Y - Byte laden und auf nächstes Byte stellen
11
  nop
12
  cpi    temp, 'S'
13
  breq  Vergleich          ;wenn S, dann die übrigen 6 Byte vergleichen
14
  inc    cnt
15
  cpi    cnt, 3            ;S muß in den ersten 3 Bytes enthalten sein
16
  breq  main
17
rjmp    S_test_loop
18
19
;weitere 6 Bytes überprüfen
20
Vergleich:
21
  clr    cnt
22
  ldi    ZL, LOW(Befehl_2*2)      ;Z - Pointer auf Befehlsmuster
23
  ldi    ZH, HIGH(Befehl_2*2)
24
Ver_loop:
25
  inc    cnt
26
  ldi    temp, '0'
27
  add    temp, cnt
28
  rcall  uart_transmit            ;!!!!hier liegt das Problem!!!
29
  cpi    cnt, 7            ;6 Bytes müssen verglichen werden
30
  breq  Ver_loop_exit
31
  lpm                  ;Z - Byte laden und Register erhöhen
32
  adiw  ZL, 1              
33
  ld    temp, Y+          ;Y - Byte laden und auf nächstes Byte stellen
34
  cp    r0, temp          ;Y mit Z vergleichen
35
  breq  Ver_loop          ;wenn gleich, nächstes Byte
36
  rjmp  Fehler
37
  ;rjmp  Vergleich_2            
38
Ver_loop_exit:
39
  clr    cnt
40
  inc    OKcnt_1            ;Zähler für erfolgreichen Vergleich
41
  rjmp  Clear            ;Daten im SRAM löschen
42
rjmp    main

Kann sich darauf jemand einen Reim machen?

von PIC kundiger (Gast)


Lesenswert?

Also PIC und MPASM ist es wahrscheinlich nicht. Ich muss passen.
Kann sonst jemand aus dem bloßen Aussehen des Quellcodes erraten, um 
welchen Mikrocontroller es geht?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sieht nach AVR aus. Aber da gibts auch einige...

von Bruno M. (brumay)


Lesenswert?

PIC kundiger schrieb im Beitrag #4251165:
> Also PIC und MPASM ist es wahrscheinlich nicht. Ich muss passen.
> Kann sonst jemand aus dem bloßen Aussehen des Quellcodes erraten, um
> welchen Mikrocontroller es geht?

Sorry, aber durch das lange Suchen und Testen bin ich schon etwas 
betriebsblind. Es ist ein ATMega48.

von S. Landolt (Gast)


Lesenswert?

> spielt das Programm verrückt
Wie äußerst sich das?

> rcall  uart_transmit            ;!!!!hier liegt das Problem!!!
Die Routine wird nicht mitgeliefert, dafür sieben Ausrufezeichen.

Und das von jemandem, der seit über sechs Jahren dabei ist.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Bruno M. schrieb:
> Lasse ich die weg, spielt das Programm verrückt.
Wie äussert sich das?
Was erwartest du und was passiert stattdessen?
Hast du mal statt der UART Geschichte einfach nur etwa gleich viel Zeit 
verplempert?

: Bearbeitet durch Moderator
von Bruno M. (brumay)


Lesenswert?

S. Landolt schrieb:
> Die Routine wird nicht mitgeliefert, dafür sieben Ausrufezeichen.

Die Routine ist Standard und selbst auch nicht das Problem, sondern ein 
fehlender Sprung dahin (wie beschrieben).
1
uart_transmit:                  ;temp wird ausgegeben
2
  cli
3
  lds    r10, UCSR0A
4
  sbrs  r10, UDRE0
5
  rjmp  UART_Transmit
6
  sts    UDR0, temp
7
exit_usart_transmit:
8
  ret

von Bruno M. (brumay)


Lesenswert?

Lothar M. schrieb:
> Wie äussert sich das?
> Was erwartest du und was passiert stattdessen?

Die empfangenen Zeichen werden nicht als richtig erkannt, obwohl sie es 
sind und daher Sprung in die Fehlerroutine.

von S. Landolt (Gast)


Lesenswert?

Wie sind temp und cnt definiert?

von Bruno M. (brumay)


Lesenswert?

Lothar M. schrieb:
> Hast du mal statt der UART Geschichte einfach nur etwa gleich viel Zeit
> verplempert?

Ja daran habe ich auch schon gedacht, und auch versucht. Allerdings habe 
ich die Taktzahl noch nicht genau nachgehalten. Das will ich aber mal 
machen.

von Bruno M. (brumay)


Lesenswert?

S. Landolt schrieb:
> Wie sind temp und cnt definiert?

temp ist r16 und cnt ist r19

von Nase (Gast)


Lesenswert?

Bruno M. schrieb:
> uart_transmit:                  ;temp wird ausgegeben
>   cli
>   lds    r10, UCSR0A
>   sbrs  r10, UDRE0
>   rjmp  UART_Transmit
>   sts    UDR0, temp
> exit_usart_transmit:
>   ret

Es ist ungewöhnlich, in einer Unterroutine das I-Flag zu löschen (cli), 
aber nicht wieder zu restaurieren.

von Bruno M. (brumay)


Lesenswert?

Nase schrieb:
> Es ist ungewöhnlich, in einer Unterroutine das I-Flag zu löschen (cli),
> aber nicht wieder zu restaurieren.

Danke für den Hinweis. Das gehört da nicht hin, da ich keinen interrupt 
verwende.

von Nase (Gast)


Lesenswert?

Bruno M. schrieb:
> S_test:
>   ldiw  Y, Eingang          ;Y - Pointer wieder auf Anfang setzen
> S_test_loop:
>   ld    temp, Y+          ;Y - Byte laden und auf nächstes Byte stellen
>   nop
>   cpi    temp, 'S'
>   breq  Vergleich          ;wenn S, dann die übrigen 6 Byte vergleichen
>   inc    cnt
>   cpi    cnt, 3            ;S muß in den ersten 3 Bytes enthalten sein
>   breq  main
> rjmp    S_test_loop

Wird "cnt" auch mal initialisiert?

von c-hater (Gast)


Lesenswert?

Bruno M. schrieb:

> Die Routine ist Standard

Bestimmt nicht. Die ist so verbuggt, wenn das Standard wäre...

Erstmal sperrt sie die Interrupts (gibt sie aber niemals wieder frei). 
Einen tiefgreifenderen Eingriff in das System kann man sich schon fast 
nicht mehr vorstellen...

Des Weiteren ist sie blockierend, also de facto ein Delay mit der Größe 
einer Bytedauer. Jedenfalls ab dem dritten zu sendenden Byte...

Wenn "rf12_rxdata_rec" genauso Scheiße prgrammiert ist, braucht man sich 
über nichts mehr zu wundern. Aber auch das hast du uns ja 
vorenthalten...

von Nase (Gast)


Lesenswert?

c-hater schrieb:
> Des Weiteren ist sie blockierend, also de facto ein Delay mit der Größe
> einer Bytedauer. Jedenfalls ab dem dritten zu sendenden Byte...
Und das ist verboten?

von c-hater (Gast)


Lesenswert?

Nase schrieb:

> Und das ist verboten?

Natürlich nicht. Man muß eben bloß dafür sorgen, dass andere 
Programmfunktionen dadurch nicht gestört werden.

Und das fällt auf Dauer am leichtesten, indem man sich auf blockierenden 
Code erst garnicht einläßt.

Entweder man macht's interruptgesteuert oder man pollt. Aber man 
blockiert niemals, wenn es sich irgendwie vermeiden läßt. Und bei einer 
USART-Ausgabe läßt es sich nun wirklich völlig problemlos vermeiden.

von (prx) A. K. (prx)


Lesenswert?

Nase schrieb:
>> Des Weiteren ist sie blockierend, also de facto ein Delay mit der Größe
>> einer Bytedauer. Jedenfalls ab dem dritten zu sendenden Byte...
> Und das ist verboten?

In Verbindung mit Interrupts ist es das.

von Tcf K. (tcfkao)


Lesenswert?

Also das Programm "spielt verrückt" wenn nicht eine Routine aufgerufen 
wird (egal wo), die die Interrupts sperrt... vielleicht sollte man da 
mal gucken...

von Thomas (kosmos)


Lesenswert?

Poste den ganzen Quellcode, der ist bestimmt nicht so gut das ihn dir 
jemand wegnimmt.

von Carl D. (jcw2)


Lesenswert?

> Poste den ganzen Quellcode

als Attachment!

von Bruno M. (brumay)


Angehängte Dateien:

Lesenswert?

Carl D. schrieb:
>> Poste den ganzen Quellcode
>
> als Attachment!

Das mache ich natürlich gerne, ich dachte ich könnte Euch das ersparen.
Den Sprung in den 2. Vergleich habe ich zum Testen entfernt.

An der Zeit liegt es übrigens nicht! An cli auch nicht, das habe ich 
entfernt.

Und so sehen die UART-Ausgaben aus:

Mit einem Sprung in die UART-Routine sowohl in der S-test Schleife als 
auch in der Vergleichschleife:

SYYBYYB7SYYBYYBAuftrag 1 ausfuehren!!!<\n><\r>

und so, wenn ich den UART-Sprung aus der Vergleichschleife nehme.

@?SVergleichs-Fehler!!<\n><\r>?/SVergleichs-Fehler!!<\n><\r>

von Tcf K. (tcfkao)


Lesenswert?

Ich bin nicht fit in AVR-Assembler... aber: Du verwendest überall nur 
eine Hilfsvariable "temp", obwohl Du weitere temp1, temp2 definiert 
hast.
Überschreibst Du Dir da nicht etwas?

von Bruno M. (brumay)


Lesenswert?

Bruno M. schrieb:
> An der Zeit liegt es übrigens nicht!

Ich muß mich korrigieren! Es scheint doch ein timing Problem zu sein.
1
Vergleich:
2
  clr    cnt
3
  ldi    ZL, LOW(Befehl_2*2)      ;Z - Pointer auf Befehlsmuster
4
  ldi    ZH, HIGH(Befehl_2*2)
5
Ver_loop:
6
  inc    cnt
7
  cpi    cnt, 7            ;6 Bytes müssen verglichen werden
8
  breq  Ver_loop_exit
9
  rcall  wait
10
  rcall  wait
11
  lpm                  ;Z - Byte laden und Register erhöhen
12
  adiw  ZL, 1              
13
  ld    temp, Y+          ;Y - Byte laden und auf nächstes Byte stellen
14
  ;rcall  uart_transmit
15
  cp    r0, temp          ;Y mit Z vergleichen
16
  breq  Ver_loop          ;wenn gleich, nächstes Byte
17
  rjmp  Fehler
18
  ;rjmp  Vergleich_2            
19
Ver_loop_exit:
20
  clr    cnt
21
  inc    OKcnt_1            ;Zähler für erfolgreichen Vergleich
22
  rjmp  Clear            ;Daten im SRAM löschen
23
rjmp    main

So funktioniert es nämlich auch!

S??SAuftrag 1 ausfuehren!!!<\n><\r>

von S. Landolt (Gast)


Lesenswert?

> S??SAuftrag 1 ausfuehren!!!<\n><\r>
Woher kommen eigentlich die Fragezeichen? Liegt das an der unüblichen 
Baudrate?

von Bruno M. (brumay)


Lesenswert?

Es bestätigt sich!!

Wenn ich auch aus S_test nur die Warteschleifen einbaue, sieht es bei 
mehrfachem Versuch so aus.

Auftrag 1 ausfuehren!!!<\n><\r>Auftrag 1 ausfuehren!!!<\n><\r>Auftrag 1 
ausfuehren!!!<\n><\r>Auftrag 1 ausfuehren!!!<\n><\r>Auftrag 1 
ausfuehren!!!<\n><\r>

Jetzt würde mich nur noch die Ursache interessieren. Da ich den 
Vergleich mit Daten aus dem SRAM durchführe, kann es ja mit der 
Funkübertragung nichts zu tun haben.

von Bruno M. (brumay)


Lesenswert?

S. Landolt schrieb:
>> S??SAuftrag 1 ausfuehren!!!<\n><\r>
> Woher kommen eigentlich die Fragezeichen? Liegt das an der unüblichen
> Baudrate?

Diese Frage kann ich leider nicht beantworten.

von SeDa (Gast)


Lesenswert?

Schau mal was sich im SREG tut mit und ohne UART/Delay.
Ich wette fast drauf, dass du False-Poitives beim Vergleich bekommst, 
weil irgend was im SREG rummurkst.

von Bruno M. (brumay)


Lesenswert?

SeDa schrieb:
> Schau mal was sich im SREG tut mit und ohne UART/Delay.
> Ich wette fast drauf, dass du False-Poitives beim Vergleich bekommst,
> weil irgend was im SREG rummurkst.

Wie soll ich das machen? Der Debugger meckert ja nicht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Bruno M. schrieb:
> Wie soll ich das machen? Der Debugger meckert ja nicht.
Warum sollte er?
Sei dir sicher: das Programm macht im uC genau das, was du 
hingeschrieben hast.

Ich würde raten sagen, da funkt irgendein Interrupt dazwischen. Was 
anderes kann diese Routine ja nicht unterbrechen und an den Flags 
herumschrauben. Wie viele Interrupts hast du?

: Bearbeitet durch Moderator
von Bruno M. (brumay)


Lesenswert?

Lothar M. schrieb:
> Wie viele Interrupts hast du?

keinen!

Aus Interesse habe ich in der Zwischenzeit testweise das Programm so 
abgeändert, daß nicht der RFM12 das SRAM füllt, sondern das Programm 
selbst. Dann verhält es sich so wie erwartet, d.h. der Vergleich 
funktioniert auch ohne wait-Schleife.

Es muß also doch ein timing - Problem mit dem RFM12 sein. Was das ist, 
kann ich mir allerdings nicht erklären.

von Tcf K. (tcfkao)


Lesenswert?

Nochmal, Du verwendest dieselbe Hilfsvariable "temp" (r16) in 
verschiedenen Modulen an verschiedenen Stellen, bist Du sicher dass sich 
da nichts überschreibt?

von Bruno M. (brumay)


Lesenswert?

Tcf K. schrieb:
> Nochmal, Du verwendest dieselbe Hilfsvariable "temp" (r16) in
> verschiedenen Modulen an verschiedenen Stellen, bist Du sicher dass sich
> da nichts überschreibt?

ja, sonst hätte ich schon beim debuggen das Problem!

von S. Landolt (Gast)


Lesenswert?

Braucht das RFM12 (ich kenne es nicht) eine Pause zwischen den 
Übertragungen?
Oder besteht ein Kontaktproblem bei /CS?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.