UART Programm (Umwandlung von Assembler zu C)

OP #703931
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)
#703932
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.
#703949
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.
OP #703951
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.
Persönliche Seite #703971
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.
OP #703978
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...
#703985
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...
#703987
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...
OP #704027
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)
Persönliche Seite #704203
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.
Persönliche Seite #704310
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
OP #704319
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.
Persönliche Seite #704337
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.
OP #704340
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.
Persönliche Seite #704347
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.
Persönliche Seite #704349
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren