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
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)
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.
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.
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.
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...
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...
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...
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 ^
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)
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.
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...
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:
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.
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.
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
volatileunsignedcharucUDR=0;// 1 Byte Puffer
4
volatileunsignedcharucUDR_valid=0;// Anzeige ob Puffer gefüllt oder leer
5
volatileunsignedintuiVerloreneZeichen;
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
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.
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.
> 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.
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.
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.
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