Forum: Compiler & IDEs UART Problem (Assembler zu C) II


von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

hi,
ich hab mal der Übersicht halber nen neuen Zhread aufgemacht...alter: 
Beitrag "UART Programm (Umwandlung von Assembler zu C)"

ich hatte die Platine jetzt mal am PC. Und wenn ich 15 (Hexa) sende 
kommt nix
einmal hatte der µC "D3" gesendet, aber das war wohl nen Fehler...also
irgendwie reagiert er nicht auf den Interrupt.


noch was. Gleich am Anfang wird ja Receive1 aufgerufen:
1
int Receive0(void)
2
{
3
while (!ucUDR_valid)
4
{
5
}
6
ucUDR_valid = 0;
7
return ucUDR;
8
}


und dort hängt es ja die ganze Zeit fest, bis ein Interrupt ausgelöst
wurde. Das finde ich etwas ungünstig, da ich ja mit 2 Geräten an den µC
senden möchte.


Im Anhang nochmal der C Code

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

Und hier der ASM

von Flo S. (tuxianer)


Lesenswert?

ich kann das Programm leider auch nicht simulieren, da ich noch nix 
derartiges für einen Mac gefunden habe.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> Gleich am Anfang wird ja Receive1 [korr. Receive0] aufgerufen und
> dort hängt es ja die ganze Zeit fest, bis ein Interrupt ausgelöst wurde.

Genau, Receive0 wartet, bis ein Zeichen empfangen wurde. Das ist in 
deinem ASM-Code eigentlich genauso.

> Das finde ich etwas ungünstig, da ich ja mit 2 Geräten an den µC
> senden möchte.

Dann prüfe doch vor dem Aufruf von Receive0, ob ein Zeichen empfangen 
wurde.

Speck das Programm soweit ab, bis nur die reine Kommunikation auf UART0 
getestet werden kann. Ein einfaches ECHO-Programm wäre z.B.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <inttypes.h>
4
#include <util/delay.h>
5
6
#define BAUD 9600L                // Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
7
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille
11
12
int temp, Data, Count, activevar1, activevar0, i;
13
int Header[50];
14
int Content[16];
15
volatile unsigned char ucUDR = 0;        // 1 Byte Puffer
16
volatile unsigned char ucUDR_valid = 0;  // Puffer gefuellt oder leer?
17
volatile unsigned int uiVerloreneZeichen;
18
19
#ifdef STEFB
20
#define USART0_RXC_vect  USART_RXC_vect
21
#define UCSR0A    UCSRA
22
#define UCSR0B    UCSRB
23
#define UCSR0C    UCSRC
24
#define UDRE0    UDRE
25
#define UDR0    UDR
26
#define URSEL0    URSEL
27
#define USBS0    USBS
28
#define UCSZ10    UCSZ1
29
#define UCSZ00    UCSZ0
30
#define RXCIE0    RXCIE
31
#define RXEN0    RXEN
32
#define TXEN0    TXEN
33
#define UBRR0H    UBRRH 
34
#define UBRR0L    UBRRL 
35
#endif
36
37
ISR(USART0_RXC_vect)
38
{
39
  if (ucUDR_valid)
40
  {
41
     uiVerloreneZeichen++;
42
     // Die Auswertung dieser Zahl kann spaeter helfen, wenn man den
43
     // 1 Byte Puffer in einen Mehrbyte-Puffer nach dem FIFO Prinzip
44
     // umruesten will. Damit kann man eine Abschaetzung der guenstigen
45
     // Puffergroesse vornehmen.
46
  }
47
48
  ucUDR = UDR0;
49
  ucUDR_valid = 1;
50
  // Nicht mehr!
51
}
52
53
#ifndef STEFB
54
ISR(USART1_RXC_vect)
55
{
56
  // Derzeit unbenutzt.
57
  // Muss aber vorhanden sein, weil dieser Interrupt in main()
58
  // aktiviert wird
59
}
60
#endif
61
62
int Receive0(void)
63
{
64
  while (!ucUDR_valid)
65
  {
66
  }
67
  ucUDR_valid = 0;
68
  return ucUDR;
69
}
70
71
void Transmit0(int Senden) {
72
  //Senderoutine UART0
73
74
  //WARTESCHLEIFE!!!!!!!
75
  _delay_ms(4.35);
76
77
  //Warten bis gesendet werden kann
78
  while (!(UCSR0A & (1<<UDRE0)))
79
  {
80
  }
81
82
  UDR0 = Senden;
83
}
84
85
int main (void) {
86
87
  //Baudrate 9k6
88
  UBRR0H = UBRR_VAL >> 8;
89
  UBRR0L = UBRR_VAL & 0xFF;
90
91
#ifndef STEFB
92
  UBRR1H = UBRR_VAL >> 8;
93
  UBRR1L = UBRR_VAL & 0xFF;
94
#endif
95
96
  //Uebertragungsart
97
#ifndef STEFB
98
  UCSR1C |= (1<<URSEL1)|(1<<USBS1)|(1<<UCSZ11)|(1<<UCSZ01);
99
#endif
100
  UCSR0C |= (1<<URSEL0)|(1<<USBS0)|(1<<UCSZ10)|(1<<UCSZ00);
101
102
  //Interrupts, Senden und Empfangen aktivieren
103
#ifndef STEFB
104
  UCSR1B |= (1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
105
#endif
106
  UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
107
108
  sei();
109
110
  while(1)
111
  {
112
    if (ucUDR_valid)     // Laut ISR Zeichen an UART0 da?
113
    {
114
       unsigned char c;
115
       c = Receive0();   // ja! Dann holen...
116
       Transmit0(c);     // ...und als Echo zurueck
117
#if 0
118
       // Option: plus Debuginfo zurueck
119
       Transmit0(uiVerloreneZeichen >> 8);
120
       Transmit0(uiVerloreneZeichen & 0xFF);
121
#endif
122
    }
123
  }
124
125
}

Ich habe mir das mit dem Makro STEFB etwas zurecht gemacht, weil ich 
keinen Atmega162 zum Testen habe. Ich habe es auf einem Atmega32 (hat 
nur ein UART) @ 13,560 MHz laufen lassen. Da drauf läuft es bei 
Terminaleinstellung 9600,8N2

von Flo S. (tuxianer)


Lesenswert?

Ich hab grad auch noch was geschrieben für 2 Geräte...nur leider kommt 
bei der While Schleife nen Fehler (expectet ")" before "or")

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

Anhang:

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1
   
2
      while(!(ucUDR_valid0 OR ucUDR_valid1))

OR ;-)

Das logische ODER ist in C ein ||

Solange in nicht (UART0 gültig oder UART1 gültig) Däumchendrehen. Das 
ist auf Deutsch solange UART0 ungültig und UART1 ungültig.

Das ist zwar OK, aber ein unötiger Bugfix für den folgenden vermurksten 
if-Fall ;-)

Wenn (if) UART0 gültig dann
  prüfe UART0 auf 0x15, ...
andernfalls (else)
  prüfe UART1 auf 0x15, ...

Ich würde eher diese Programmstruktur als logisch ansehen:

Wenn UART0 gültig dann
  prüfe UART0 auf 0x15, ...

Wenn UART1 gültig dann
  prüfe UART1 auf 0x15, ...

Ansonsten im Rest steckt ein Schlampifehler:
1
   
2
      ucUDR1 = 0;
3
      
4
      if(ucUDR1 == 0x15)

von Flo S. (tuxianer)


Lesenswert?

Oh sorry hab mich schon gewundert, warum das nicht blau wurde im Editor 
^^. Jo der Fehler ist blöd...das muss einfach nen valid dahinter!

von Flo S. (tuxianer)


Lesenswert?

gehen tuts leider immer noch nicht...es kommt sofort, wenn ich was sende 
nen Error...irgendwie erkennt der den Interrupt nicht oder irgendwas 
geht da schief...wie gesagt ich kann leider nicht emulieren...

von Flo S. (tuxianer)


Lesenswert?

noch was beim Ersten mal senden Kommt der Error sofort...beim 2. Mal 
dauert es länger. D.h. beim ersten mal bekommt er schon irgendwie ne 
Antwort aber irgendwas ist falsch. Und beim 2. mal hängt er irgendwo und 
reagiert gar nicht mehr...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Sorry, da kann ich dir nicht helfen. Ich kann dir nur den Tipp geben, 
mit einem PC das Echo Programm vom µC zu testen.

Was passiert, wenn du den Casio an den PC anhängst und in einem 
Terminalprogramm für die serielle Schnittstelle die µC Seite von Hand 
emulierst?

> ich kann das Programm leider auch nicht simulieren, da ich noch nix
> derartiges für einen Mac gefunden habe.

Du hast keinen PC sondern einen Mac? Welchen? Hat der eine RS232 
serielle Schnittstelle? Dafür gibt es Programme...

http://homepage.mac.com/dalverson/zterm/
http://www.furrysoft.de/?page=goserial

Tipp: 0x06 ist CONTROL-E
http://www.cs.tut.fi/~jkorpela/chars/c0.html

von Flo S. (tuxianer)


Lesenswert?

Nein ich hab keine Serielle Schnittstelle. Also Rechner an PC ist nicht 
wirklich interessant...da weis ich ja wie es funktioniert und was 
passiert. Den µC hatte ich ja auch schon mal am Rechner (anderer PC). 
Und wenn ich da 0x15 gesendet habe ist nix passiert bei der ASM Variante 
schon. Also kann es eigentlich nur was formales am Code sein.

von Flo S. (tuxianer)


Lesenswert?

ich hab jetzt mla zum Debuggen 2 Pins auf high gesetzt an verschiedenen 
Stellen...

1
  while(1){
2
  
3
    while(!(ucUDR_valid0 || ucUDR_valid1))
4
    {
5
    }
6
    PORTA = 0x03; 
7
    
8
    if(ucUDR_valid0 == 1)
9
    {

der Port wird high, auch wenn ich noch gar nix gesendet habe. Da muss 
doch nen AND hin oder?

von Flo S. (tuxianer)


Lesenswert?

so ich hab den Fehler jetzt schonmal eingegrenzt...

1
int Receive0(void)
2
{
3
4
5
  while (!ucUDR_valid0)
6
  {
7
  }
8
  ucUDR_valid0 = 0;
9
  return ucUDR0;
10
}

wenn ich den Port nach cdUDR_valid0 = 0; auf high setze wird er high...

1
        // Header Rrecieve 0
2
        for (Count=0; Count < 50; Count++) 
3
        {
4
          //Header speichern
5
          Header0[Count] = Receive0();
6
        }
7
        
8
        PORTA = 0x03;


hinter diese schleife kommt er nicht mehr. Also hängt es da drinn!


Das: sbis UCSR0A, RXC habe ich doch noch gar nicht umgesetzt oder 
geschieht das automatisch durch den Interrupt?

von Flo S. (tuxianer)


Lesenswert?

es muss was beim Empfangen schiefgehen...der Controller geht zu schnell 
kann eigentlich nicht sein in ASM gehts auch ohne Wait...oder wie gesagt 
der µC wartet nicht, bis das byte empfangen wurde und der Rechner bricht 
dann ab...und er hängt in der Schleife fest und wartet darauf, das etwas 
gesendet wird...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> in ASM gehts auch ohne Wait...

Der Vergleich mit dem ASM-Programm nervt mich inzwischen etwas. Dann 
beschäftige dich mit deinem ASM-Programm. Ich versuche keinesfalls den 
kruden Mix aus Interrupt-Betrieb und Polling-Betrieb mit 
Kreuzundquersprüngen in einem so toll kommentierten ASM-Listing 
aufzudröseln. Ich helfe aber gerne die grundlegende Umsetzung auf einen 
sauberen Interruptbetrieb in C-Code zu zeigen (weil das etwas ist, was 
auch mich im Lernstoff "UART und Interrupts" weiter bringt). Wenn du 
damit Probleme hast, sag's und ich nerve dich nicht weiter.

Das "Hängen in der Schleife" ist in der derzeitigen C-Version fast 
unausweichlich. Ein Minimal-1-Byte-Puffer ist prädestiniert für 
verlorene Zeichen. Ich hatte dir eine Variable eingebaut, wo du prüfen 
kannst, ob Zeichen verloren gehen.

Da wie beschrieben Receive0() wartet bis ein Zeichen da ist und weil 
dein for() unbedingt 50 Zeichen für den Header haben will, hängt dein 
Programm, wenn der Casio keine 50 Zeichen sendet und/oder Zeichen 
verloren gegangen sind.

Ich kann auch gerne eine Variante aufzeigen, mit einem grösseren Puffer. 
Oder eine Variante mit einem Zähler für die empfangenen Zeichen. Hast du 
am kompletten PORTA Debug-LEDs (8 Stück?), so dass man da eine Zahl 
0..255 (verlorene Zeichen oder empfangene Zeichen) ausgeben kann?

von Flo S. (tuxianer)


Lesenswert?

Es tut mir ja leid mit dem ASM Vergleich, aber an irgend etwas muss ich 
mich ja orientieren. In C habe ich wie gesagt noch nicht soviel Praxis 
Erfahrung. Ich habe an PortA gar keine LED's leider ist das teil wie 
gesagt schon auf einer Platine. Ich habe aber mit einem Multimeter 
nachgemessen. Du kannst mir ja mal bitte deine Variante geben. Ich mess 
dann einfach den Kompletten Port durch.

von Karl H. (kbuchegg)


Lesenswert?

Florentin S. wrote:
> Es tut mir ja leid mit dem ASM Vergleich, aber an irgend etwas muss ich
> mich ja orientieren.

Ja. Du sollst dir aus dem Assembler Code rausholen, welche
Bytes in welcher Reihenfolge daherkommen. Eventuell kann
man aus dem Assembler Code auch noch die Auswertung studieren
und rausfinden was in welchem Fall gemacht werden muss.

Aber ansonsten: Vergiss den Assembler Code und setzte eine
ordentliche C Struktur auf.

Blöd ist natürlich, dass du keine vernünftigen Debug-
Möglichkeiten hast. Ein paar LED an einem Port sind
nicht wirklich ein Ersatz um die Kommunikation zu
überprüfen.

Ich würde mal folgendes machen:
Ein minimal UART Programm aufsetzen, das Interrupt getrieben
ist und beim Empfang eines Zeichens einen Port Pin auf
High (oder Low) setzt. Um das Handling zu vereinfachen einfach
mal mit ein paar Drähten eine Led (samt Vorwiderstand) an
besagtem Port Pin anlöten (wenn deine Platine schon soweit
fertig ist, dass du keine Led mehr einbauen kannst. Welcher
Teufel hat dich eigentlich geritten eine fertige Platine zu
machen, noch bevor ein Testaufbau auf einem Steckbrett oder
auf Streifenraster die grundsätzliche Funktionsweise nachgewiesen
hat).

Warteschleifen sind Mist!
Du willst sie nicht haben. Die einzige Warte/Endlosschleife ist
die Schleife in main.
1
....
2
3
ISR(USART0_RXC_vect)
4
{
5
  if (ucUDR_valid)
6
  {
7
     uiVerloreneZeichen++;
8
     // Die Auswertung dieser Zahl kann spaeter helfen, wenn man den
9
     // 1 Byte Puffer in einen Mehrbyte-Puffer nach dem FIFO Prinzip
10
     // umruesten will. Damit kann man eine Abschaetzung der guenstigen
11
     // Puffergroesse vornehmen.
12
  }
13
14
  ucUDR = UDR0;
15
  ucUDR_valid = 1;
16
  // Nicht mehr!
17
}
18
19
int main()
20
{
21
  ...
22
23
  sei();
24
25
  while( 1 ) {    // dies ist die einzige Schleife, die auf etwas
26
                  // wartet. Sie wartet auf Arbeit
27
28
    if( ucUDR_valid0 ) {   // Ein Zeichen ist auf UART 0 angekommen
29
      cli();
30
      c = ucUDR0;          // hier ist es
31
32
      PORTxxxx = .....     // Led ein
33
      ucUDR_valid0 = 0;
34
      sei();
35
    }
36
  }
37
}

ergänze mal die fehlenden Teile für Initialisierung und sieh nach,
ob deine LED eingeschaltet wird. Wenn ja, dann hat der Interrupt
ausgelöst.

von Flo S. (tuxianer)


Lesenswert?

ich werd das dann mal ausprobieren. Aber der Interrupt löst aus...das 
habe ich ja schon probiert es hängt definitiv in der Warteschleife in 
der Reveive Routine. Es müssten eigentlich Zeichen verloren gehen...denn 
die Anzhal in der Schleife stimmt laut Protokoll.

Die Platine ist fertig, weil das ASM Prog wie gesagt lief...und ich habe 
mich jetzt nur entschlossen, das nochmal in C zu schreiben, weil ich von 
ASM weg will und es mir zu kompliziert zu erweitern ist.

von Karl H. (kbuchegg)


Lesenswert?

Florentin S. wrote:
> habe ich ja schon probiert es hängt definitiv in der Warteschleife in
> der Reveive Routine.

Eine derartige Warteschleife willst du nicht haben.
Die ganze Funktion ist unnötig.

Dein Programm will nicht aktiv darauf warten, dass auf der
Seriellen Schnittstelle 50 Bytes eintrudeln.
Du musst deine Denkweise umstellen und anfangen Ereignis-
orientiert zu denken: Auf der UART ist ein Byte engetrudelt,
was mache ich damit?
Für diesen Gedankengang ist die adequate Programmierweise die
Hauptschleife in main(). Wenn ein Byte an der UART eintrudelt,
dann teilt die Interrupt Routine das dem Rest der Welt mit,
indem sie eine globale Variable (das berüchtigte ucUDR_valid)
auf 1 setzt. Und dein 'Eventdispatcher' (ein schönes Wort
für sowas einfaches) reagiert darauf, indem er im nächsten
Durchlauf diese 1 sieht und entsprechend reagiert.
Aber dein Programm wartet nirgends aktiv darauf, dass diese
Variable irgendwann 1 wird. Dein Programm prüft ständig in
einer Schleife ob irgendeine dieser Benachrichigungsvariablen
zu 1 geworden ist und behandelt dann diesen Fall (dieses Ereignis)
1
  while( 1 ) {     // diese Schleife ist dein 'Eventdispatcher'
2
3
    if( ucUDR_valid ) {    // und das ist der Event der aufgetreten
4
                           // ist. Wenn das hier auf 1 geht, dann
5
                           // ist das Ereignis: 'UART hat ein Byte
6
                           // empfangen' eingetreten. Jetzt heist
7
                           // es auf dieses Ereignis zu reagieren.
8
9
                           // reagieren kann zb heissen, dass das
10
                           // Byte in einem Buffer zwischengespeichert
11
                           // wird und geprüft wird ob das nicht schon
12
                           // das 50.te Byte war. Wenn es das 50.te
13
                           // Byte war, dann ist zb. der Header fertig
14
                           // empfangen worden und kann ausgewertet
15
                           // werden (nur so als Beispiel).
16
       ...
17
    }
18
  }

Das ist deine Grundstruktur. Für jedes Ereignis welches auftreten
kann, findet sich in dieser while Schleife eine if-Abfrage.
Der Code der dann ausgeführt wird, behandelt dieses Ereignis.
Nirends muss auf irgendwas gewartet werden (schon alleine
deshalb, weil es keine Warteschleifen mehr gibt) und quasi
zeitgleiche Ereignisse werden nacheinander so schnell wie möglich
abgearbeitet.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:
> Eine derartige Warteschleife willst du nicht haben.
> Die ganze Funktion ist unnötig.

Sag' doch so was nicht ;-)

Wenn unbedingt X Bytes eingelesen werden müssen, kann man das schon 
sinnvoll mit einer wartenden Funktion machen. Die Alternative zur 
Funktion wäre ja eine Latte Statements direkt im in Hauptcode. Und 
gewartet werden müsste ja trotzdem.

Ich gebe dir Karl heinz so weit Recht, als dass eine 
"Programm-muss-jetzt warten-bis-50-Bytes-angekommen-sind" Strategie in 
der Praxis ziemlich unglücklich ist. Aber das zu beheben, würde einen 
Programmablauf z.B. mit Timeoutbehandlung im Protokoll voraussetzen. So 
weit sind wir noch lange nicht ;-)

In the meantime... ist bloss nachzusehen ob bzw. sicherzustellen, dass 
beim Empfang keine Zeichen verloren gehen. Ich mache heute abend 
Beispielcode fertig.

Schade, dass Florentin immer noch keine Möglichkeit gefunden hat, um den 
Datenverkehr mit dem µC ohne den Casio zu testen. Es wäre einfacher, 
wenn man gleiche Testmöglichkeiten hat und auch abgespeckte Teilaspekte 
lösen kann, statt mit der Meldung "Error!" irgendwo in einem 
achtstufigen Protokoll stecken zu bleiben.

ADD: Karl heinz, ich sehe gerade, dass du die Antwort ergänzt hast. Der 
Ansatz gefällt mir gut. Es ist doch kein so grosser Schritt es gleich 
richtig zu machen.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

hi,
danke nochmal die Hinweise. Die Main habe ich jetzt so umgewandelt, dass 
die auch ohne die Schleife Funktioniert. Nur verstehe ich jetzt nicht 
ganz, was du meinst...soll ich die Receive Funktion jetzt komplett 
weglassen? Und alles in die Main integrieren? Im Anhang nochmal der 
Code. Soll ich einen Zähler machen, der die Bytes zählt? Oder wie?

Mit dem UART ist mist, das ich das nicht am PC testen kann...ich werde 
mir so einen USB RS232 Wandler besorgen, damit ich auch am Mac debuggen 
kann.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Entweder hast du den falschen Code hochgeladen oder du hast das Prinzip 
nicht verstanden.

Ich sehe im Moment nur, dass die Vorschläge von Karl heinz nicht 
realisiert sind und der wichtige Bugfix (cli()-sei()-Klammer um Zugriff 
auf gemeinsame Variablen zwischen ISR und Nicht-ISR-Code) wieder fehlt.

Was anderes...

Was hat es mit dem UART1 auf sich? Im Moment ist dort der gleiche Code 
wie auf UART0. Willst du zwei Casio an ein Atmega162-Board hängen? Wenn 
ja, was ist die Aufgabe des Atmega162-Boards, Datentransfer zwischen den 
beiden Casio (würde aber so nicht funktionieren, weil beide zum 
Atmega162 senden)?

von Flo S. (tuxianer)


Lesenswert?

Ich habe das Prinzip schon teilweise verstanden, aber wenn ich die 
Interrupts deaktiviere funktioniert das Receive ja logischerweise so 
nicht mehr. Ich bin noch am überlegen, wie ich das am besten umsetze. Ja 
an den anderen UART kommt ein 2. Rechner ran. Der µC ermöglicht die 
direkte Kommunikation
 zwischen 2 Rechnern im Programm, was so nicht funktioniert, da der 1ne 
Rechner ein anderes Handshake sendet, als der andere erwartet.

von Flo S. (tuxianer)


Lesenswert?

1
> 
2
> int main()
3
> {
4
>   ...
5
> 
6
>   sei();
7
> 
8
>   while( 1 ) {    // dies ist die einzige Schleife, die auf etwas
9
>                   // wartet. Sie wartet auf Arbeit
10
> 
11
>     if( ucUDR_valid0 ) {   // Ein Zeichen ist auf UART 0 angekommen
12
>       cli();
13
>       c = ucUDR0;          // hier ist es
14
> 
15
>       PORTxxxx = .....     // Led ein
16
>       ucUDR_valid0 = 0;
17
>       sei();
18
>     }
19
>   }
20
> }
21
>

Der test hatte übrigens funktioniert. Der Port war auf High.

Nur wie gesagt ich müsste ja jetzt das empfangen anders gestalten, wenn 
ich nach dem ersten empfangen die Interrupts deaktiviere.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

Ich hab Receive0 jetzt nochmal geändert:

von Karl H. (kbuchegg)


Lesenswert?

vorweg: Ich weiss nicht, wie ich es dir noch anders erklären
soll, ohne dass ich dein Programm schreibe.

> was du meinst...soll ich die Receive Funktion jetzt komplett
> weglassen?

  Ja

> Und alles in die Main integrieren?

Na ja. Soviel bleibt in der Receive Funktion nicht übrig,
wenn man die Warteschleife rauswirft. Im Grunde bleibt dann
ja nur eine Zuweisung übrig :-)

> Nur wie gesagt ich müsste ja jetzt das empfangen anders gestalten, wenn
> ich nach dem ersten empfangen die Interrupts deaktiviere.

Die Interrupts werden eaktiviert, damit dieser Programmteil

>       c = ucUDR0;          // hier ist es
>
>       PORTxxxx = .....     // Led ein
>       ucUDR_valid0 = 0;
>       sei();

nicht von einem UART Interrupt unterbrochen werden kann.
Das macht sich nämlich nicht so gut, wenn hier in diesem
Programmteil ucUDR_valid auf 0 gesetzt wird und kurz vorher
ein Interrupt versucht hat, den auf 1 zu setzen.

Aber schau doch mal ans Ende der Sequenz. Da steht ein kleiner
verträumter sei(), der nach Abschluss dieser Operation die
Interrupts wieder zulässt.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

Also wird der Interrupt nur beim ersten empfangenen Byte ausgelöst und 
wenn alle Bytes empfangen sind und die Übertragung komplett ist wieder 
aktiviert. Meinst du das so (siehe Anhang)?

von Karl H. (kbuchegg)


Lesenswert?

Florentin S. wrote:
> Also wird der Interrupt nur beim ersten empfangenen Byte ausgelöst und
> wenn alle Bytes empfangen sind und die Übertragung komplett ist wieder
> aktiviert. Meinst du das so (siehe Anhang)?

Nein.
Der Interrupt wird nur kurzzeitig abgeschaltet, während
ein (in Worten: 1) empfangenes Zeichen verarbeitet wird.

Ob die Übertragung aller Zeichen komplett ist, kann ich doch
zu diesem Zeitpunkt noch gar nicht sagen. Das weis ich doch
erst nachdem ich den Zähler hochgezählt habe, der mir sagt
wieviele Bytes jetzt schon empfangen wurden! Wenn der auf
50 steht, dann war das das letzte zu Empfangende Byte auf
dieser Schnittstelle.
1
uint8_t ByteCounter0;
2
uint8_t ByteBuffer0[50];
3
4
uint8_t ByteCounter1;
5
uint8_t ByteBuffer1[50];
6
7
int main()
8
{
9
  uint8_t c;
10
11
   ...
12
13
   ByteCounter0 = 0;
14
   ByteCounter1 = 0;
15
16
   ....
17
18
   while( 1 ) {
19
20
     if( ucUDR_valid0 ) {   // Ein Zeichen ist auf UART 0 angekommen
21
       cli();
22
       c = ucUDR0;          // hier ist es
23
       ucUDR_valid0 = 0;
24
       sei()
25
26
       ByteBuffer0[ ByteCounter0 ] = c;
27
       ByteCounter0++;
28
29
       if( ByteCounter0 == 50 ) {
30
         // Hurra, die 50 Bytes für den Header sind
31
         // allesamt beisammen
32
         //
33
         // mach was damit
34
35
         ByteCounter0 = 0;
36
       }
37
     }
38
39
// das ganze nochmal für UART 1
40
41
     if( ucUDR_valid1 ) {   // Ein Zeichen ist auf UART 1 angekommen
42
       cli();
43
       c = ucUDR1;          // hier ist es
44
       ucUDR_valid1 = 0;
45
       sei()
46
47
       ByteBuffer1[ ByteCounter1 ] = c;
48
       ByteCounter1++;
49
50
       if( ByteCounter1 == 50 ) {
51
         // Hurra, die 50 Bytes für den Header sind
52
         // allesamt beisammen
53
         //
54
         // mach was damit
55
56
         ByteCounter1 = 0;
57
       }
58
     }
59
60
  }
61
}

von Flo S. (tuxianer)


Lesenswert?

ok daran hatte ich auch schonmal gedacht nur wird dann die auswertung 
etwas umständlicher. Da ich ja nicht nur den haeder empfangen habe. Aber 
so müsste es gehen. Ich wollte wie gesagt Header Und Daten etc einzeln 
abspeichern.

von Karl H. (kbuchegg)


Lesenswert?

Obiges ist natürlich nur ein Skelett um das Prinzip aufzuzeigen.
Wenn ich mir dein Protokoll mal so ansehe, dann fällt mir dazu
ein, dass ich da noch einen Status mit einbauen würde.
Deine Empfangs-'Maschine' ist eine Machschine die in
bestimmten Stati sein kann. Zb. wartet die Maschine auf
das erste Sync byte (die 0x15), das ihr mitteilt, das
in bälde mit der Übertragung des Headers zu rechnen sein
wird.
Nun, das sind schon mal 2 Zustände. Welche gibts noch?

   die Maschine ist untätig (engl. idle) und wartet auf die 0x15
   was ist zu tun, wenn die 0x15 empfangen werden?
     Die Maschine muss 0x13 zurücksenden und geht in den
     Zustand EmpfangeHeader über

   Was ist im Zustand EmpfangeHeader zu tun?
   Nicht viel, die empfangenen Bytes, 50 an der Zahl sind
   abzuspeichern (oder auch nicht). Wie auch immer. Auf jeden
   Fall muss die Maschine 0x06 schicken und geht dann in den
   Zustand EmpfangeDaten über

   Was ist im Zustand EmpfangeDaten zu tun?
   Bytes speichern, 16 an der Zahl und nachdem die Daten da
   sind, wird ein 0x06 gesendet und die Maschine geht in
   den Zustand EmpfangeFooter (als gegenstück zum 'Header')
   über.

   Was ist im Zustand EmpfangeFooter zu tun?
   Kennen wir schon. 50 Bytes empfangen und hinten nach wieder
   ein 0x06 wegschicken.
   Dadurch ist ein Telegram beendet und die Maschine kann wieder
   in den Zustand Idle übergehen.
1
#define IDLE       0
2
#define REC_HEADER 1
3
#define REC_DATA   2
4
#define REC_FOOTER 3
5
6
7
uint8_t DataCounter0;
8
uint8_t DataBuffer0[16];
9
uint8_t ByteCounter0;
10
uint8_t ByteBuffer0[50];
11
uint8_t State0;
12
13
uint8_t DataCounter1;
14
uint8_t DataBuffer1[16];
15
uint8_t ByteCounter1;
16
uint8_t ByteBuffer1[50];
17
uint8_t State1;
18
19
int main()
20
{
21
  uint8_t c;
22
23
   ...
24
25
   DataCounter0 = 0;
26
   ByteCounter0 = 0;
27
   State0 = IDLE;
28
29
   DataCounter1 = 0;
30
   ByteCounter1 = 0;
31
   State1 = IDLE;
32
33
   ....
34
35
   while( 1 ) {
36
37
     if( ucUDR_valid0 ) {   // Ein Zeichen ist auf UART 0 angekommen
38
       cli();
39
       c = ucUDR0;          // hier ist es
40
       ucUDR_valid0 = 0;
41
       sei();
42
43
       if( State0 == IDLE && c == 0x15) {     // was hat im Zustand Idle zu geschehen?
44
         Transmit0( 0x13 );
45
         State0 = REC_HEADER;
46
       }
47
48
       else if( State0 == REC_HEADER ) {
49
         ByteBuffer0[ ByteCounter0 ] = c;
50
         ByteCounter0++;
51
52
         if( ByteCounter0 == 50 ) {
53
           Transmit0( 0x06 );
54
           ByteCounter0 = 0;
55
           State0 = REC_DATA;
56
         }
57
       }
58
59
       else if( State0 == REC_DATA ) {
60
         Data0[ DataCounter0 ] = c;
61
         DataCounter0++;
62
63
         if( DataCounter0 == 16 ) {
64
           Transmit0( 0x06 );
65
           DataCounter0 = 0;
66
           State0 = REC_FOOTER;
67
         }
68
       }
69
70
       else if( State0 == REC_FOOTER ) {
71
         ByteBuffer0[ ByteCounter0 ] = c;
72
         ByteCounter0++;
73
74
         if( ByteCounter0 == 50 ) {
75
           Transmit0( 0x06 );
76
           ByteCounter0 = 0;
77
           State0 = IDLE;
78
         }
79
       }
80
81
     }
82
83
// das ganze nochmal für UART 1
84
85
     if( ucUDR_valid1 ) {   // Ein Zeichen ist auf UART 1 angekommen
86
       cli();
87
       ........

von Karl H. (kbuchegg)


Lesenswert?

Florentin S. wrote:
> ok daran hatte ich auch schonmal gedacht nur wird dann die auswertung
> etwas umständlicher.

Etwas umständlicher schon. Aber dafür funktioniert sie aber auch.
Ausserdem: so wild ist das dann auch wieder nicht.

Mit eine paar Funktionen, in denen die State-Machine ausgelagert
wird, wird das eine schöne, kleine, schnucklige Hauptschleife.

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

So ich habs jetzt mal danach gestaltet. Gibt es nicht noch eine 
Möglichkeit Header und Daten einzeln zu speichern? Und was ist eine 
State-Maschine?

von Flo S. (tuxianer)


Lesenswert?

und leider geht das Programm immer noch nicht über den Header hinaus...

von Flo S. (tuxianer)


Lesenswert?

ich finde nicht raus, woran das liegen kann auf jeden Fall sendet er den 
2. Handshake nicht mehr. eigentlich werden doch alle Handshakes an der 
richtigen Stelle gesendet. Vlt läuft der µC zu schnell...aber durch das 
Interrupt empfängt er doch eigentlich nur, wenn auch was da ist...

von Flo S. (tuxianer)


Lesenswert?

Ich komm nicht weiter aber ich habe mir jetzt mal so einen USB - Seriell 
Converter bestellt und hoffe mal, das der mich weiter bringt.

von STK500-Besitzer (Gast)


Lesenswert?

Wie wäre es, wenn du mal die Aufgabe deines Programmes hinschreiben 
würdest?!
Dann könnten dir auch Leute helfen, die keine/wenig Ahnung von Assembler 
haben.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die Aufgabe ist schnell umrissen:

Ein Atmega162 soll mit einem "Casio GTR" (genaue Modellbezeichnung oben) 
Taschenrechner Daten austauschen. Dabei sollen beide UARTS des Atmega 
benutzt werden, wenn 2 Taschenrechner angesprochen werden sollen.

Die regen User dieser Casio-Reihe haben einen Teil des Protokolls bei 
den Send/Receive Befehlen des Caso und der Struktur der gesendeten Daten 
herausgefunden. Einen Link zu einer PDF Datei mit dieser Beschreibung 
hat Florentin in dem ganz oben angegebenen Thread angegeben. Ausserdem 
liegt ein funktionierendes ASM-Programm vor (auch oben angegeben).

Das derzeitige Teilziel ist, die Ausgabe des Casio-Befehls Send per 
UART0 auf den Atmega162 zu schaffen. Ein UART-Empangsinterrupt-Programm 
in C mit einer Teilimplementation der Funktionalität des ASM-Programms 
hängt mitten in dem empfangenen Telegramm (genauer: beim Empfangen des 
ersten Headers). Die sinnvollen Vorschläge von Karl heinz zur Abwicklung 
des Telegramms per state /machine/ (endlicher Automat) sind allerdings 
noch nicht eingebaut (Hausaufgaben machen Florentin!).

Die Hardware auf AVR Seite ist derzeit eine fertige, nicht näher 
beschriebene Platine mit wenigen Zugangsmöglichkeiten fürs Debugging. 
Erschwerend (neudeutsch: herausfordernd) ist, dass Florentin keine RS232 
Test- und Debugmöglichkeiten hat. Ein Anhängen des AVR oder des Casio an 
einen PC funktioniert bei ihm nicht, weil sein MAC keine RS232 
Schnittstelle hat, sondern nur USB. Ein USB-RS232 Konverter beschafft 
sich Florentin gerade. Ob der dafür erforderliche TTL-RS232-Pegelwandler 
vorhanden ist und an die fertige AVR Platine angebaut werden konnte, 
weiss ich im Moment nicht. Wir hatten das diskutiert, aber das Resultat 
ist mir nicht präsent. AVR und Casio sind jedenfalls direkt über TTL 
miteinander verbunden. Die derzeitige Debugmöglichkeit von Florentin 
ist, PORTA als Output-Port zu nutzen und die Pegel an den Pins mit dem 
Multimeter nachzumessen.

Mir war lange unklar, was hinter diesem Projekt stecken könnte...

...ich habe eine Seite im Netz gefunden, wo ähnliche Bauteile und auch 
beide UARTS benutzt werden. Es wird damit ein Chatprogramm zwischen zwei 
Taschenrechnern aufgebaut ;-) 
http://www.frangenberg.info/Michael/gtr/chat/index.html

Florentins Platine und Anwendung können auch ganz anders aussehem, so 
dass man nicht dortige Hardware als Grundlage für weitere 
Debuggingoptionen voraussetzen kann.

Es wäre nicht schlecht, wenn Florentin näher aus die Platine eingehen 
würde. Und wenn Florentin schon dabei ist: Mit welchem Programmer und 
welcher Programmersoftware schaffst du die Programme in den Atmega162? 
Vielleicht kann man da was in Richtung Debugging drehen...

von Falk B. (falk)


Lesenswert?

@  Karl heinz Buchegger (kbuchegg)

>vorweg: Ich weiss nicht, wie ich es dir noch anders erklären
>soll, ohne dass ich dein Programm schreibe.

Dann nimm doch einach mal alle deine sehr ausführlichen Erklärungen und 
pack sie in einen Wikiartikel + Beispielcode. Denn das sicher nicht die 
letzte Anfrage zum UART Interrupt.

MFG
Falk

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die Idee hatte ich so ähnlich gestern auch. Und das ist auch der Grund, 
warum ich mich relativ stark in diesen Thread reinhänge. Ich will den 
UART Interrupt selbst auch verstehen.

Daraufhin hatte ich genau diese Baustelle im AVR-GCC-Tutorial 
angelegt (=> UART => Interruptbetrieb). Ob es dort oder hinter dem 
Interruptteil des Tutorials stehen wird ist noch offen. Kommt darauf an, 
was vom Lernen hersinnvoller ist.

Im Moment bin ich am Herstellen und Testen von Beispielcode. Mitarbeit 
ist sehr willkommen.

von Karl H. (kbuchegg)


Lesenswert?

Falk Brunner wrote:
> @  Karl heinz Buchegger (kbuchegg)
>
>>vorweg: Ich weiss nicht, wie ich es dir noch anders erklären
>>soll, ohne dass ich dein Programm schreibe.
>
> Dann nimm doch einach mal alle deine sehr ausführlichen Erklärungen und
> pack sie in einen Wikiartikel + Beispielcode. Denn das sicher nicht die
> letzte Anfrage zum UART Interrupt.

Na, ja.
Sein Problem dürfte doch jetzt eigentlich nicht mehr der Interrupt
sein, sondern die Datenauswertung, wenn ich die letzten Meldungen
richtig interpretiere.

Leider ist Florian etwas hilflos wenn es zum Thema Debugging geht.
Hilft aber alles nichts, da muss er durch. Debugging hat auch
immer was mit Intuition, Ideen haben und auch ein klein wenig
Glück zu tun. Wenn ich nichts vernünftiges zum Debuggen habe,
dann hab ich meistens immer noch eine Led an einem Port, die
dann herhalten muss um mir anzuzeigen ob bestimmte Zustände
im Programm eingetreten sind. Und wenn das alles ist, was
ich als externen Indikator habe, dann muss halt das genügen
um mir ein Bild darüber zu verschaffen was im Programm abgeht.
Dazu muss ich mir aber überlegen, was ich überhaupt mit einer
Ja/Nein Entscheidung (und was anders erlaubt mir meine LED ja
nicht) als Statusinformation herausgeben kann und was ich mit
dieser Information anfangen, bzw. welchen Rückschluss ich daraus
ziehen kann.

von Flo S. (tuxianer)


Lesenswert?

Hi,
danke nochmal für die Hinweise. Über eine State-Maschine werde ich mich 
erkundigen, was das ist. Ich habe den Assemblercode zusammen mit Michael 
entwickelt (Link oben). Meine Platine ist ähnlich aufgebaut. Also nur 
das nötigste und halt an den Uarts die Kabel zum Rechner. Der Serielle 
Adapter ist wie gesagt bestellt und ich hoffe, dass er morgen ankommt. 
Einen Pegelwandler (Max232) habe ich zur Verfügung. Das ist nicht das 
Problem.

Das Problem muss wie gesagt irgendwo beim empfangen des Haders liegen. 
Entweder geht was zu schnell oder was anderes läuft schief. Ich hoffe 
das ich morgen mal ordentlich Debuggen kann um den Fehler noch genauer 
zu lokalisieren.

Vielen Dank noch mal für die Hinweise.

Gruß Florentin

von Flo S. (tuxianer)


Lesenswert?

Ich hab nochmal wegen der State Maschine geschaut...soll ich damit die 
Zustände schreiben wie Header wurde empfangen oder in wiefern kann ich 
diese einsetzen?


Was ich noch vergessen hatte ich flashe den Atmega mittels AVRDude.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Florentin S. wrote:

> soll ich damit die
> Zustände schreiben wie Header wurde empfangen oder in wiefern kann ich
> diese einsetzen?

Das hat dir Karl Heinz hier schon erläutert:

Beitrag "Re: UART Problem (Assembler zu C) II"

Das Gerippe der state machine steht da schon.

Das Prinzip ist, dass du mit jedem empfangenen Byte guckst, was du
damit anfangen kannst.  Wenn dieses Byte dazu führt, dass du
(basierend auf dem aktuellen Zustand des Automaten) einen bestimmten
Abschnitt des Headers jetzt erkannt hast, dann schaltet der
Automat weiter und guckt, was danach kommt.  Auf diese Weise
hangelt man sich Stück für Stück weiter.  Wenn irgendetwas
unerwartetes im Datenstrom ankommt, bricht der Zustandsautomat
(so der offizielle deutsche Name) ab und fällt auf den Grundzustand
zurück.

von Flo S. (tuxianer)


Lesenswert?

Danke den hab ich ja noch gar nicht gelesen.

@Karl Heinz hasst du den Beitrag mal ediert? Oder habe ich den schlicht 
weg überlesen? Danke. Dann bau ich sowas in der Art mal noch ein.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Florentin S. wrote:
> Hi,
> danke nochmal für die Hinweise. Über eine State-Maschine werde ich mich
> erkundigen, was das ist.

Genau das was ich als letztes Programmfragment weiter oben
gepostet habe.
In einer Variablen wird der aktuelle Zustand (der State)
gespeichert und wenn die Maschine arbeiten soll, entscheidet
sie anhand des States und dem neuen Input (und eventuell irgendwelchen
Zusatzbedingungen) was zu geschehen hat und in welchen neuen
State (das ist dann einfach eine Zuweisung an die State-Variable)
sie überwechseln soll.

Eine Statemaschine hat den Vorteil, dass man die Logik die
dahintersteckt, sehr einfach graphisch veranschaulichen kann
(siehe beiliegendes gif). Die Umsetzung aus so einer Graphik
in die tatsächliche Implementierung ist dann reine
Routinearbeit.

Im Gif gilt:
 die Kreise sind die Zustände (jweils mit dem Namen des Zustands)
 die grauen Pfeile sind die Zustandsübergänge
 bei Pfeil steht jeweils dabei:
    in blau: welche Voraussetzung muss gelten, damit dieser
             Pfad genommen wird
    in rot:  welche Aktion ist dabei durchzuführen

Wenn du dieses Bild mit meinem Code vergleichst, wirst du auch
feststellen, dass ich im Code ein paar Fehler gemacht habe.
Das liegt daran, dass ich den Code direkt eingetippt habe
und vor dem Posten nicht getestet habe. Durch die Grafik kannst
du die Logik deiner Maschine in einer abstrakten Art und Weise
festlegen und dich nur auf die richtigen Abläufe konzentrieren.
Du kannst dann auch auf dem Papier mal deine Maschine mit
einem simulierten Input durchspielen und die Abläufe kontrollieren.
Läuft das ganze auf dem Papier, dann setzt man das in Code um.
(und nicht so wie ich das gemacht habe: zuerst coden und dann
zeichnen. Wie du siehst schleichen sich da Fehler ein).

von Karl H. (kbuchegg)


Lesenswert?

Nachtrag.
Da diese State Maschine nur 4 Zustände kennt, würde es sich
zb. anbieten die State Nummer auf 2 Leds auszugeben und dann
mal ganz gemütlich Zeichen in die Maschine einzuspeisen.
Die Leds zeigen dir dann ganz genau an, in welchem Zustand
die Maschine ist und du kannst kontrollieren ob wenigstens
das funktioniert.

(PS: Der Fehler von dem ich im Codeteil gesprochen habe,
betrifft die Initialisierung der diversen Counter. Da liegt
einiges im Argen)

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

Ja vielen Dank nochmal das mit den Fehlern habe ich schon gemerkt das da 
ein paar Namen falsch waren etc. Die hab ich mal korrigiert. Ich muss 
nur nochmal schauen, ob inhaltlich alles stimmt. Der Code ist im Anhang. 
Muss aber nochmal alles durchprüfen.

von Flo S. (tuxianer)


Lesenswert?

So. Der Code funktioniert so anscheinend auch noch nicht. Wenn ich 0x15 
sende sendet er wenn überhaupt "0xD3" zurück oder sendet ununterbrochen 
"0xC6" Wenn ich den µC vom Strom trenne sendet er 2 Bytes genau weis ich 
nicht mehr was, aber ich glaub es war "F0". Vlt könnt ihr mit den 
Informationen was anfangen. Mir kommt das bald vor, wie Baudrate falsch 
eingestellt.

Edit:

Ich hab auch mal den Rechner an den PC geklemmt und den µC emuliert das 
Klappt wunderbar.

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ah, du bist jetzt so weit, dass du entweder den Casio oder den µC an die 
serielle Schnittstelle eines PC hängen kannst?

Zur Baudrate...

Aus dem gesetzten UBRR0L Wert (0x2F bzw. 47) im LSS-File letztens ist 
erkennbar, dass der µC in die UBRR_VAL Berechnung F_CPU = 7372800 Hz 
eingeflossen ist. Das ist die gleiche Taktrate wie im ASM-File. Das 
ASM-Programm funktionierte auch auf der gleichen Platine. D.h. die 
Taktrate fürs C-Programm stimmt und dann wird die Baudrate auch stimmen.

Und den anderen UART-Parametern...

Die habe ich auch in dem Programm im Anhang verwendet. Wenn ich meinen 
den PC auf 9600 Baud 8N2 einstelle, funktioniert die Kommunikation mit 
dem µC.

Tipp: In vielen Terminalprogrammen auf dem PC kann man die Kommunikation 
in eine Datei mitspeichern lassen. Das kann ungemein nützlich sein, um 
anderen die Ergebnisse zu zeigen...

von Flo S. (tuxianer)


Lesenswert?

Ich hatte Gelegenheit, das Teil an einem anderen Rechner zu testen. Es 
war ein Windows Rechner mit HTerm.

von Flo S. (tuxianer)


Lesenswert?

Irgend etwas ist komisch...ich habs jetzt nochmal an einem anderen 
Rechner getestet und weder dein Debug Programm funktionieren noch meine 
C Variante. Rechner Funktioniert und ich hab mal das ASM drauf geladen 
sobald ich 15 eigebe kommt 13 zurück. Ich sende 50 Bytes danach kommt 6 
und so weiter. Aber bei den C Varianten kommt nix!

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

ok ich habs...

ich sende 0x15

der µC antwortet mit 0xD3

dann sende ich 50 Bytes

der µC antwortet mit 0xC6

dann 16 Bytes

µC: 0xC6

dann 50

µC: 0xC6


das Programm hat also schon früher funktioniert siehe erster Beitrag. Da 
antwortete der µC auch mit 0xD3 nur woran kann das liegen? Im Anhang 
nochmal das Makefile:

Es muss also an dem Wert liegen, der Transmit übergeben wird oder etwas 
an der Baud stimmt nicht, was aber unrealistisch ist, da der µC ja auf 
0x15 antwortet.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Seltsam. Schick doch mal das LSS-File von dem jetzigen C-Code, damit man 
sehen kann, was auf unterster Ebene gemacht wird. Ich bin allerdings bis 
Montag nicht mehr online, da ich das schöne Schweinfurth besuche ;-)

von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

hier der Aktuelle...ich hab aber noch nen bisschen was gemacht nicht 
wundern.

von Flo S. (tuxianer)


Lesenswert?

mist ist grad nen Freund bei mir der was wissen wollte siehe GCC. 
Deswegen der andere Name nicht wundern ^

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Das ist mir total unerklärlich, denn das LSS sieht für mich OK aus.

Gut, Transmit0(int Senden) wäre besser ein Transmit0(unsigned char 
Senden) sein, damit Code eingespart wird, aber daran liegt es eher 
nicht.

Als echte Verzeiflungstat würde ich in Transmit0() die letzte Zeile in 
UDR0 = Senden & 0x1F; ändern, um herauszufinden, ob das Phänomen (Bit 6 
und 7 gesetzt) vom Hauptcode her kommt (ohne &) oder vom UART selbst 
(mit &).

von Flo S. (tuxianer)


Angehängte Dateien:

Lesenswert?

so ich hab jetzt mal den Rest eingespeist (Erstmal nur UART0). Ist das 
so in Ordnung oder kann man noch was optimieren? Der Compiler meckert 
nicht. Nur kann ichs leider noch nicht testen, bevor ich das allgemeine 
Problem beseitigt habe.

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.