Forum: Compiler & IDEs UART Programm (Umwandlung von Assembler zu C)


von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

hallo,
ich mach der Übersichtlichkeit mal nen Neuen Thread auf. Ich wandle 
gerade mein ASM Script in C um...Jetzt kommt wider mal eine Warnung von 
Inkompatiblen Typen in der Funktion Transmit0.


Codes im Anhang

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

und hier der ASM Code

von Uhu U. (uhu)


Lesenswert?

Wie wärs denn, wenn du dich etwas präziser äußern würdest, wie die 
Warnung genau lautet und wo sie erzeugt wird?

von Flo S. (tuxianer)


Lesenswert?

Ist sonst alles korrekt?

chmod 755 GTR.elf
-------- end --------

    GTR.c:46: warning: implicit declaration of function 'Transmit0'
    GTR.c: At top level:
    GTR.c:64: warning: conflicting types for 'Transmit0'
    GTR.c:46: warning: previous implicit declaration of 'Transmit0' was 
here
Build succeeded (3 warnings)

von Johannes M. (johnny-m)


Lesenswert?

Eine Funktion muss bei ihrem Aufruf bekannt sein. Transmit0 wird in der 
ISR aufgerufen, aber erst nach der ISR definiert. Deshalb kennt der 
Compiler beim Aufruf von "Transmit0" keine Funktion dieses Namens und 
vermutet, dass der Aufruf eine implizite Deklaration sein soll.
Lösung:
Entweder die Definition von Transmit0 vor dem ersten Aufruf oder am 
Anfang eine Prototypen-Deklaration.

von Flo S. (tuxianer)


Lesenswert?

OK Vielen Dank! Ist das mir dem Return richtig um aus der Interrupt 
routine raus zu kommen?

von Flo S. (tuxianer)


Lesenswert?

hier der Aktuelle...könnt ihr bitte schauen, ob alles passt? Fehler und 
Warnungen kommen keine. Wie setzt ich das Wait aus dem ASM in C um?

von Johannes M. (johnny-m)


Lesenswert?

Florentin S. wrote:
> OK Vielen Dank! Ist das mir dem Return richtig um aus der Interrupt
> routine raus zu kommen?
Nö. Eine Funktion, die keinen Wert zurückgibt, braucht auch kein return. 
Das Ende der Funktion ist die schließende Klammer "}". Wenn die Funktion 
Transmit0 beendet ist, gehts mit der "}" am Ende zurück in die ISR und 
aus der dann mit der entsprechenden Klammer zurück ins Programm.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

...

von Flo S. (tuxianer)


Lesenswert?

ok ich denk ich hab mich dumm ausgedrückt...es geht um die Stelle:
1
ISR(USART0_RXC_vect) 
2
{  
3
4
  //Interrupt Routine für UART0
5
  if (UDR0 != 0x15) {
6
    //Wen Handshake nicht 0x15 war...
7
    return;  
8
      
9
  }else{
10
    //Wenn Handshakebyte 0x15 war...

wenn das empfangene Byte nicht 0x015 war soll es das interrupt 
verlassen. Im Asm ist das durch ret gelöst.

von Flo S. (tuxianer)


Lesenswert?

ok die For Schleifen waren schon mahl falsch..statt < muss hin <=...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Florentin S. wrote:
> ISR(USART0_RXC_vect)
> {
>
>   //Interrupt Routine für UART0
>   if (UDR0 != 0x15) {
>     //Wen Handshake nicht 0x15 war...
>     return;
> ...
> wenn das empfangene Byte nicht 0x015 war soll es das interrupt
> verlassen. Im Asm ist das durch ret gelöst.

In ASM wirklich ret und nicht reti? Ich sehe keinen Fehler bei der 
C-Variante.

Tipp: Du kannst dir das erzeugte Assemblerlisting ansehen. Mit dem 
korrigierten Makefile aus deinem anderen Thread wird ein GTR.lss erzeugt 
- da ist C-Code und produzierter Assemblercode sichtbar.

von Flo S. (tuxianer)


Lesenswert?

also in asm wars mit reti. Wie trag ich das denn ins makefile ein, das 
es den ASM Coder erzeugt?

hier der Ausschnitt aus asm:
1
Receive0_int:
2
    
3
     in data, sreg
4
     push data
5
       in Data, UDR0                       ; Empfangenes Byte in Data speichern
6
       cpi  Data, 0x15
7
     breq header_init
8
     pop data
9
     out sreg, data
10
     reti                               ; zur�ck zum Hauptprogramm
wie realisiere ich nun die Waitschleife wie im ASM?


Edit mit dem Ret habe ich mich verschrieben. Jetzt verstehe ich, was du 
meinst...

von Johannes M. (johnny-m)


Lesenswert?

Florentin S. wrote:
> wenn das empfangene Byte nicht 0x015 war soll es das interrupt
> verlassen. Im Asm ist das durch ret gelöst.
Die Abfrage an sich ist nicht sonderlich sinnvoll. Dreh sie doch einfach 
um, dann kannste Dir das "else" komplett sparen.
1
if (UDR0 == 0x15)
2
    Transmit0(0x13);
Im Falle von "UDR0 != 0x15" soll ja sowieso nichts gemacht werden, außer 
die ISR wieder zu verlassen...

von Flo S. (tuxianer)


Lesenswert?

ok ich war mir nicht sicher, ob er die schleife verlässt, wenn ich das 
nicht festlege. Ich habe noch keine Große Erfahrung mit C!

von Johannes M. (johnny-m)


Lesenswert?

Florentin S. wrote:
> ok ich war mir nicht sicher, ob er die schleife verlässt, wenn ich das
> nicht festlege. Ich habe noch keine Große Erfahrung mit C!
Wo ist denn da eine Schleife? "if" ist nur eine Abfrage (Verzweigung, 
bedingte Ausführung)! Hat mit einer Schleife überhaupt nichts zu tun. 
"while" und "for" sind Schleifen...

von Flo S. (tuxianer)


Lesenswert?

sorry hatte mich versprochen...meinte natürlich verzweigung. Wie setze 
ich das Wait um? Im Momment läuft der Code nämlich noch nicht...

von Flo S. (tuxianer)


Lesenswert?

irgend was stimmt nicht...an den Seriellen schnitstellen fliest gar kein 
Strom. beim ASM tut es das.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

hier nochmal der Aktuelle Code:

von Flo S. (tuxianer)


Lesenswert?

also bei der ASM Variante liegen an G und TX 5V an...bei C 0 Strom...

von Johannes M. (johnny-m)


Lesenswert?

Wenn Du den kompletten Inhalt von main auskommentierst, dann wird auch 
nichts initialisiert. Abgesehen davon willst Du doch wohl nicht 
ernsthaft erzählen, dass Du den Strom an der Schnittstelle misst, 
oder? Ich hoffe, der Unterschied zwischen Strom und Spannung ist Dir 
geläufig...

von Flo S. (tuxianer)


Lesenswert?

Oh...das war noch der Code, den Stefan korrigiert hatte. In meinem 
Editor, wird das nicht deutlich gemacht. Ja ich hab die Spannung 
gemessen. Natürlich nicht den Strom ^

von Flo S. (tuxianer)


Lesenswert?

da wäre auch geklärt, warum die Fehler weg waren...jetzt kommt wieder:


    GTR.c:25: error: 'USR1C' undeclared (first use in this function)
    GTR.c:25: error: 'URSEL' undeclared (first use in this function)
    GTR.c:25: error: 'USBS' undeclared (first use in this function)
    GTR.c:25: error: 'UCSZ1' undeclared (first use in this function)
    GTR.c:25: error: 'UCSZ0' undeclared (first use in this function)
    GTR.c:26: error: 'USR0C' undeclared (first use in this function)
    GTR.c:29: error: 'RXCIE' undeclared (first use in this function)
    GTR.c:29: error: 'RXEN' undeclared (first use in this function)
    GTR.c:29: error: 'TXEN' undeclared (first use in this function)
Build failed (9 errors)

von Johannes M. (johnny-m)


Lesenswert?

Dann hast Du vermutlich im Makefile bzw. AVRStudio den Controllertyp 
nicht angegeben...

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

doch aber die Namen waren falsch is es so ok?

von Flo S. (tuxianer)


Lesenswert?

so jetzt liegt Spannung an...ist nur noch das Problem mit dem wait...

von Johannes M. (johnny-m)


Lesenswert?

Normalerweise haben Aufrufe von Senderoutinen u.ä. nichts in einem 
Interrupt Handler zu suchen. Das kann zu Kollisionen und Datenverlust 
führen!

Zu den Wartezeiten: Schau Dir in der libc-Doku mal die Funktionen aus 
der util/delay.h an. Da könnte was für Dich dabei sein.

von Flo S. (tuxianer)


Lesenswert?

anders gehts leider nicht. Also irgendwie bekomme ich am Zielgerät 
(Taschenrechner) immer einen Com Error. Irgendwas muss aner der Anzah 
oder so falsch sein...

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

ich hab auch schon mit verschiedenen wartewerten gespielt...

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

gibts keinen, der ASM und C kann und mir sagen kann, wo der Unterschied 
zwischen den beiden Programmen liegt?

Hier nochmal die Verkürzte ASM Variante. Soweit, wie ich in C bin:

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Nochmal der Tipp vorn mir: Lass dir beim Übersetzen das Listingfile 
GTR.lss erzeugen (dein Makefile aus der anderen Diskussion macht das 
schon) und vergleiche den erzeugten Code selbst. Du scheinst ja 
ASM-KEnntnisse zu haben.

Im Moment fehlt deinem main() nach der UART-Initialisierung die 
Endlosschleife. Möglicherweise harmlos, wenn der C-Startupcode (der Code 
von der Library, der vor main() ausgeführt wird) nach Verlassen von 
main() selbst eine Endlosschleife ausführt.

Wenn du wie in deinem Code keine Funktionsprototypen benutzt (was nicht 
empfohlen ist), solltest du die Funktionen im Code definieren bevor sie 
verwendet werden. Statt pauschalem int (2 Bytes Speicherbedarf) solltest 
du den kleinstmöglichen Datentyp (hier char, wenn du Vorzeichen willst. 
Ansonsten besser unsigned char) benutzen. Spart auch heftig Speicher bei 
den beiden Puffern.

Deine Assemblersource funktioniert so nicht. Es soll das Label 
header_init angesprungen werden und das fehlt in der Source. Ebenso das 
Label Datarequest0, das Label data_receive, das Label Transmit, ...

Mir sieht die ASM-Routine header_init0 derzeit ziemlich vergurkt aus. Es 
ist nicht sinnvoll, daraus eine genauso vergurkte C-Source zu machen.

Bringe vielleicht zuerst die ASM-Source in Ordnung oder erzähle was in 
deinem Protokoll gemacht werden soll. Wann kommen die Handshakebytes, 
wann und vorallem warum wird vorm Senden eine halbe µC-Ewigkeit 
(0,5s!!!) gewartet.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

Der asm Code war der Falsche sorry. Der andere Funktioniert.  (Anhang). 
Was soll ich am Assembler noch optimieren? Das warten ist so lange, da 
das Ziel (Taschenrechner) ziemlich lahm ist. Eine lss wird erzeugt aber 
sie sieht komisch aus, also der Inhalt.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

LSS:

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

und der Aktuelle C code:


hier das Taschenrechner Protokoll:
http://www.frangenberg.info/zeug/GTRprotokoll.pdf

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die Wartezeit ist wohl ein empirischer Wert, den ich so in dem PDF nicht 
finde. In deinem Assemblercode komme ich auf ca. 4,35 ms Wartezeit in 
der Transmit0 Funktion und nicht auf ca. 500 ms wie in deinem C-Code.

Bitte prüfe die Wartezeit z.B. mit einer blinkenden LED. Ein 
Frequenzunterschied von 2 Hz (1/500ms beim C-Code) und 230 Hz (1/4,35ms 
beim ASM_Code) sollte man mit nacktem Auge sehen.

Wenn ich richtig liege, könnte man statt der Schleife direkt 
_delay_ms(4.35) benutzen.

Den Restcode habe ich nicht genauer analysiert. Der ASM-Code hat 
wesentlich mehr Funktionen als der C-Code. Hier kann man sich erst 
weiter machen, wenn obiges geklärt ist. Funktioniert ein ASM-Code, der 
nur die Funktionalität des abgespeckten C-Codes hat oder muss im C-Code 
mehr als bisher programmiert werden (abgesehen davon dass richtig 
programmiert werden muss)?

Programmtechnisch ist die Auswertung des Protokolls innerhalb der 
Interruptroutine sehr schlechter Programmierstil.

Man muss das anders machen z.B. Protokollführung innerhalb der while(1) 
Schleife von main und die Interruptroutine nur verwenden, um die Daten 
beim Empfang zu schaufeln und zu signalisieren, dass Daten da sind, die 
in main ausgewertet werden können. Insbesondere wenn noch mehr 
Funktionen aus dem PDF umgesetzt werden sollen bist du derzeit rasch in 
der Sackgasse.

Deine Denkweise mit dem C-Interrupt ist übrigens auch eine essentielle 
Quelle fürs Nichtfunktionieren: Der Interrupt wird bei JEDEM empfangenem 
Zeichen angesprungen und nach dem Auslesen von UDR0 ist UDR0 futsch. 
D.h. durch den Vergleich mit dem 0x15 gehen alle anderen Zeichen 
verloren. Im ASM-Code wird UDR0 vor dem Vergleich in eine globale 
Variable Data umkopiert, das funktioniert dann.

Und in Verbindung mit 500ms warten... da hat der GTR ist schon die paar 
Bytes auf die Leitung gepackt und auf dem µC ist es bereits in dem 
ISR-Gulli.

Ein besserer C-Code sähe so aus:
1
// Vorspann wie gehabt
2
3
volatile unsigned char ucUDR = 0;        // 1 Byte Puffer
4
volatile unsigned char ucUDR_valid = 0;  // Anzeige ob Puffer gefüllt oder leer
5
volatile unsigned int uiVerloreneZeichen;
6
7
ISR(USART0_RXC_vect) 
8
{  
9
  if (ucUDR_valid)
10
  {
11
     uiVerloreneZeichen++;
12
     // Die Auswertung dieser Zahl kann später helfen, wenn man den 
13
     // 1 Byte Puffer in einen Mehrbyte-Puffer nach dem FIFO Prinzip 
14
     // umrüsten will. Damit kann man eine Abschätzung der günstigen
15
     // Puffergrösse vornehmen.
16
  }
17
18
  ucUDR = UDR0;
19
  ucUDR_valid = 1;
20
  // Nicht mehr!
21
}
22
23
int Receive0(void) 
24
{
25
  while (!ucUDR_valid)
26
  {
27
  }
28
  ucUDR_valid = 0;
29
  return ucUDR;
30
}
31
32
int main(void)
33
{
34
   // UART init wie gehabt...
35
36
   while(1)
37
   {
38
      if (Receive0() == 0x15) 
39
      {
40
         // hier kommt der Rest aus der alten ISR
41
         Transmit0(0x13);     //Header Init 0
42
    
43
         // Header Rrecieve 0
44
         for (Count=0; Count < 50; Count++) 
45
         {
46
            //Header speichern
47
            Header[Count] = Receive0();
48
         }
49
    
50
         // Handshakebyte
51
         Transmit0(0x06);
52
    
53
         // Data Receive
54
         for (Count=0; Count < 16; Count++) 
55
         {
56
            Content[Count] = Receive0();
57
         }
58
    
59
         // Handshakebyte
60
         Transmit0(0x06);
61
    
62
         // Endheader lesen aber dann verwerfen
63
         for (Count=0; Count < 50; Count++) 
64
         {
65
            Receive0();
66
         }
67
    
68
         // Handshakebyte
69
         Transmit0(0x06);
70
      }
71
   }
72
}
73
74
// Rest wie gehabt

von Flo S. (tuxianer)


Lesenswert?

Vielen Dank ich werde deinen Code bei Gelegenheit umsetzen. Das mit dem 
Wait habe ich geändert. Allerdings funktioniert es immer noch nicht. Die 
korrekte Auswertung des Protokolls ist erstmal Nebensache. Das kommt 
später. Erstmal müssen die Handshakebytes an der richtigen stelle 
kommen. Und das tuen sie im Moment nicht.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

so ich habe jetzt nochmal deinen Code als Grundlage genommen. Jetzt muss 
ich ihn nur noch verstehen. Aber Es kommt trotzdem noch ein Com Error.

von Flo S. (tuxianer)


Lesenswert?

noch was. Wie mache ich das, wenn ich die beiden Schnittstellen brauche?

von Flo S. (tuxianer)


Lesenswert?

So wie ich das verstanden habe wird nach jedem Empfangenen Zeichen ein 
Interrupt ausgelöst. Also liefert die Receive Schleife erst das Byte 
zurück. wenn was empfangen wurde.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> Aber Es kommt trotzdem noch ein Com Error.

Also dem GTR stinkt was an der Übertragung.

Das kann eine falsche Einstellung sein (nicht 9600 Baud 8N2 wie im PDF 
genannt). Oder es kann falscher Anlauf der Übertragung sein.

Benutzt du die gleiche Hardware für das C-Programm wie für das 
ASM-Programm und flashst jeweils das Versuchsobjekt? Anders gefragt: 
kann es an einem Unterschied an der µC Taktung (z.B. unterschiedliche 
Fuses-Einstellung) liegen, dass die Baudrate nicht stimmt?

Ich würde hingehen und die Übertragung mit einem PC und einem 
PC-Terminalprogramm testen. Sehr hut dafür ist das Br@y-Terminal 
geeignet, welches im RS232-Artikel aufgeführt ist.

Zu beantwortende Fragen:

1/ Stimmt 9600 8N2 seitens des GTR? Stimmt 9600 8N2 seitens des µC? wenn 
2/ und 3/ die erwarteten Hexzeichen bringen, kann man das bejahen.

2/ Was schickt der GTR bei manuellem Ausführen der Protokollsequenz zum 
PC? Ist die Sequenz überhaupt zeitkritisch? Der PC simuliert den µC.

3/ Was schickt der µC bei manuellem Ausführen der Protokollsequenz zum 
PC? Ist die Sequenz zeitkritisch? Der PC simuliert den GTR.

Alles andere ist Fischen im Trüben.

von Flo S. (tuxianer)


Lesenswert?

ja mit dem PC habe ich mir auch schon gedacht. Aber das wird etwas 
kompliziert. Die Platine ist fertig gelötet. Und ich bräuchte ja noch 
einen Pegelwandler, den Ich so ja nicht drauf bekomme.

Und ja ich benutze für ASM und für C das gleiche Zielobjekt. Dara kann 
es also nicht liegen. Es muss irgendwo ein Fehler im Code sein.

von Flo S. (tuxianer)


Lesenswert?

braucht der Pegelwandler das Gleiche VCC wie der µC? Sonst bau ich den 
auf nen Steckbrett mit extra Netzteil...da hab ich aber nur 4.5V da 
reicht das?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Florentin S. wrote:
> So wie ich das verstanden habe wird nach jedem Empfangenen Zeichen ein
> Interrupt ausgelöst. Also liefert die Receive Schleife erst das Byte
> zurück. wenn was empfangen wurde.

Lass es mich so sagen:

Dein alter C-ISR Code frisst Zeichen weg, wenn der Vergleich mit 0x15 
gemacht wird. Die alte Receive-Schleife in C funktioniert überhaupt 
nicht, weil du noch im ISR steckst. Solange du im ISR bist, sind alle 
Interrupts gesperrt. Da geht nix.

Dein ASM-ISR Code frisst Zeichen weg, macht aber vorher eine Kopie. Die 
alte Receive-Schleife in ASM funktioniert, weil du dich inzwischen mit 
Rumspringen mit rjmp und den vielen eingestreuten reti Blöcken aus der 
ISR herausgewuschtelt hast.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Florentin S. wrote:
> braucht der Pegelwandler das Gleiche VCC wie der µC? Sonst bau ich den
> auf nen Steckbrett mit extra Netzteil...da hab ich aber nur 4.5V da
> reicht das?

Kommt auf den Pegelwandler an. Die Kenndaten stehen im Datenblatt. Ein 
normaler MAX232 für Vcc=5V müsste auch mit 4,5V funktionieren. 4,5V ist 
der untere Wert bei den recommended operation conditions.

Hast du keinen anzapfbaren Pegelwandler auf der Platine, um an den GTR 
zu gehen? Sind dort direkte TTL-Pegel auf der Leitung? OK, ja so ist es, 
ich sehe es gerade bei http://www.lamepage.de/hardware/casio/index.html

von Flo S. (tuxianer)


Lesenswert?

mist mein max232 ist glaube kaputt...selbst it dem Rechner bekomme ich 
kein Signal.

von Flo S. (tuxianer)


Lesenswert?

der Fehler scheint aber ziemlich am Anfang zu sitzen. Denn er kommt fast 
unmittelbar nach dem Senden.

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.