Hallo Ich bin nun schon seit fast einer Woche dabei den folgenden Fehler zu Suchen. Rahmenbedingungen: Auf dem uRechner läuft ein Programm, welches Messwerte erfassen soll. Diese werden in Arrays gespeichert. Ein kleine C# Sharp Programm soll die Messerte auslesen und in einer Datei Speichern, welche mittels Ajax auf eine Webseite geladen wird. Auf dem uRechner sind Baudraten und Parity so wie Stop bits richtig gesetzt. Es wird ein 20MHz eingesetzt. Die Taktrate habe ich mit _delay_ms(1000) und einer blinkenden LED schon getestet. das Problem: Sende ich ein bestimmtes Zeichen an den Controller beginnt dieser damit 254 Byte an den PC zu schicken. Mittels hTerm klappt dies Wunderbar. Bei C# kommen aber immer unterschiedlich viele Zeichen an. meistens so an die 120 bis 180 und dann hört es einfach auf. Mitlerweile habe ich das Programm schon so angeändert, dass immer nur 25 byte übertragen werden und der uRechner dann erst auf eine Checksumme des PCs Wartet. Aber selbst hier treten sehr oft Checksummen Fehler auf oder es kommen nicht alle 25 Byte am PC an. Hier nochmal. Mit hTerm kein Problem. In Visual C# nutze ich die fertige SerialPort Klasse. Es sind 8 bit Daten, 2 Stop bits und keine Parität eingetragen. Der Puffer ist auf den Standartmäßigen 4kb. Es ist keine Timeout überwachung. Die Daten lese ich mit dem Interrupt aus, welches ausgelöst wird, wenn sich ein neues byte im Puffer befindet. Es wird dann immer nur ein byte mit .Readbyte() aus dem ComPort gelesen. Trotzdem gehen jede Menge Daten verloren oder kommen fehlerhaft an. Die einstellungen bei Visual C# sind genau die gleichen wie bei hterm. Was vieleicht noch eine Interessante Information ist, ist dass es auf meinem Desktop PC auch mit C# wunderbar klappt. Auf allen anderen Laptops allerdings nicht. Die USB-Serial Adapter sind die gleichen mit gleichem Treiber und gleichem OS. Am ATmega644 ist ein MAX232 vor den UART geschaltet. Ich hoffe mir kann jemand helfen. Bin echt am verzweifeln. Ich würde auch euf eine andere Programmiersprache umsteigen, wenn mir jemand die Einbindung der Bibliotheken erklährt. Vieleicht gibt es auch ne Alternative zur .net Klasse von C#. Ein Umsteigen auf Visual C++ oder VB wird wahrscheinlich keinen sinn machen, da diese ja die gleiche Klasse verwenden. Danke für eure Bemühungen.
der fehler liegt sehr wahrscheinlich im Quellcode. Ohne den können wir nicht sinnvoll zu hilfe beitragen.
Hmm dass das als Antwort kommt habe ich mir fast gedacht. Prolem ist, dass der Qullcode ziemloch groß ist. Ich veruche mal die Relevanten Teile darzustellen: c#
1 | //Comport Initialisieren
|
2 | ComPort = new System.IO.Ports.SerialPort(this.components); |
3 | ComPort.Parity = System.IO.Ports.Parity.None; |
4 | ComPort.BaudRate = 9600; |
5 | ComPort.PortName = "COM10"; |
6 | ComPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(ComPort_DataReceived); |
7 | ComPort.DataBits = 8; |
8 | ComPort.StopBits = 2; |
9 | |
10 | //mit einem Klich auf eine Schaltfläche wird der Comport geöfnet
|
11 | |
12 | private void onButton(object sender, EventArgs e) |
13 | {
|
14 | try
|
15 | {
|
16 | ComPort.Open(); |
17 | ComPort.Write(new byte[] { (byte)(0x02) }, 0, 1); |
18 | }
|
19 | catch (Exception ex) |
20 | {
|
21 | MessageBox.Show(ex.Message); |
22 | }
|
23 | }
|
24 | |
25 | private int counter; //Steht hier natürlich nicht in echt ;) |
26 | |
27 | private void ComPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) |
28 | {
|
29 | byte puffer = Convert.ToByte(ComPort.ReadByte()); |
30 | Console.WriteLine("Befehlteil: " + counter + "//" + puffer); |
31 | counter++; |
32 | }
|
Und der Atmel
1 | #define BAUD 9600UL //halbe Baudrate
|
2 | |
3 | // Berechnungen
|
4 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
|
5 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
|
6 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
|
7 | |
8 | #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
|
9 | #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
|
10 | #endif
|
11 | |
12 | void USART1_init() |
13 | {
|
14 | //Baudrate einstellen
|
15 | UBRR1H = UBRR_VAL >> 8; |
16 | UBRR1L = UBRR_VAL & 0xFF; |
17 | |
18 | //Empfangen und Senden
|
19 | //8 Bit
|
20 | //2 Stop Bit
|
21 | //None Parity
|
22 | |
23 | UCSR1B = 0b10011000; |
24 | UCSR1C = 0b10001110; |
25 | }
|
26 | |
27 | void USART1_send_Byte(uint8_t byte) |
28 | {
|
29 | while(!( UCSR1A & (1<<UDRE1))); //warten auf Datenregister empty; |
30 | //_delay_ms(40); //Steht dieser wert auf 100 oder mehr läuft es einigermaßen gut. Ist aber ja kein Zustand
|
31 | UDR1= byte; |
32 | }
|
33 | |
34 | ISR (USART1_RX_vect) |
35 | {
|
36 | cli(); |
37 | uint8_t puffer = UDR1; |
38 | if(puffer == 0x02) |
39 | {
|
40 | for(uint8_t i = 0; i<254;i++) |
41 | {
|
42 | USART1_send_Byte(Datenarray[i]); // das Array ist natürlich lang genug und woanders definiert |
43 | }
|
44 | }
|
45 | }
|
Das ist ja eigendlich alles was man wissen muss denke ich. Ich habe vorsichtshalber noch einmal ein sehr abgespecktes Programm geschrieben, was nur mit diesem Quellcode aufgebaut ist. Auch da kommen nach manchmal gerade 20 byte keine neuen Daten mehr an. Mit hterm werden ohne Probleme 254 Byte mit dem Richtigen Inhalt empfangen.
Jan schrieb: > private void ComPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) > { > byte puffer = Convert.ToByte(ComPort.ReadByte()); > Console.WriteLine("Befehlteil: " + counter + "//" + puffer); > counter++; > } woher weist du das nur 1byte ankommt? while ( ComPort.BytesToRead > 0 ) { byte puffer = Convert.ToByte(ComPort.ReadByte()); Console.WriteLine("Befehlteil: " + counter + "//" + puffer); counter++; } sinnvoller ist es aber vermutlich gleich alle verfügbaren bytes mit Read in ein array einzulesen.
Könnte ich mal ausprobieren. Aber ich muss dann wissen wie viele es sind. Seltsam ist dass es auf dem Desktop PC geht. Aber aber der hat auch wesendlich mehr Rechnleistung als der Laptop. Vieleicht ist es ja tatsäch so hinzubekommen. Werde morgen mal 2 Testprogramme schreiben und hochladen und es da dann direkt ausprobieren.
Jan schrieb: > Die Daten lese ich mit dem Interrupt aus, welches ausgelöst wird, wenn > sich ein neues byte im Puffer befindet. Es wird dann immer nur ein byte > mit .Readbyte() aus dem ComPort gelesen. Trotzdem gehen jede Menge Daten > verloren oder kommen fehlerhaft an. 1.: Passendes Encoding eingestellt? Sollte System.Text.Encoding.GetEncoding(28591) (ISO-8859-1) sein, da die anderen u.U. die übertragenen Werte verändern (ASCII "kürzt" alle Bytes > 127, UTF-8 wartet u.U. auf Multibyte-Zeichen etc.) 2.: Wie ist der ReceivedBytesThreshold eingestellt? U.U. diesen höher stellen 3.: Im DataReceived-Event sollte mit BytesToRead abgefragt werden wie viele Bytes im Buffer sind z.B.
1 | private static void SP_OnDataReceived(object sender, SerialDataReceivedEventArgs e) { |
2 | SerialPort sp = (SerialPort)sender; |
3 | byte[] buffer = new byte[sp.BytesToRead]; |
4 | sp.Read(buffer, 0, buffer.Length); |
5 | // do something
|
6 | }
|
Falls Strings übertragen werden kann man ReadExisting() verwenden.
Jan schrieb: > Seltsam ist dass es auf dem Desktop PC geht. Aber aber der hat auch > wesendlich mehr Rechnleistung als der Laptop. das ist doch klar, der PC schafft es bei jeden byte die Methode aufzurufen, der Laptop schafft es scheinbar nicht. Es aber aber drozdem ein Programmierfehler.
Ich habe gerade nochmal ein Testprogramm geschrieben. Die Usart schnittstelle läuft tatsächlich sehr viel besser, wenn alle verfügbaren bytes ausgelesen werden. Es treten zwar immernoch oft Fehler auf aber das ist nicht schlimm. Normalerweise hat aber der Comport schon einen Buffer der 4kb groß ist. Selbst wenn mein Laptop also nicht in der lage ist immer gleich die bytes einzulesen wenn ich sie einzeln einlese müssten sie aber im Speicher puffer bleiben. Der uRechner sendet nach 25 byte erst weiter wenn ein CRC empfange wurde. Der 4kB speicher kann also nie überlaufen. Naja Hauptsache es geht so. Danke für die Hilfe.
Jan schrieb: > Normalerweise hat aber der Comport schon einen Buffer der 4kb groß ist. > Selbst wenn mein Laptop also nicht in der lage ist immer gleich die > bytes einzulesen wenn ich sie einzeln einlese müssten sie aber im > Speicher puffer bleiben. Der uRechner sendet nach 25 byte erst weiter > wenn ein CRC empfange wurde. Der 4kB speicher kann also nie überlaufen. das Probelm ist/war das die funktion SerialDataReceivedEventArgs auch wenn 25byte im Puffer sind, nur einmal aufgerufen wird. Wenn du jetzt nur 1byte abrufst, dann bleiben noch 24byte im Puffer und es erfolgt kein ReceivedEvent mehr, weil ja nichts neues Empfangen wurde.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.