- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 20

Thema: 16bit UART Übertragung

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    29.12.2014
    Beiträge
    13

    16bit UART Übertragung

    Hallo Community,

    Auf Empfehlung sponsere ich dem Thema einen eigenen Thread^^

    mein Vorhaben ganz simpel: eine Zahl (16bit) soll in 2x(8bit) zerlegt werden und via UART auf einen zweiten µC gesendet und auf einer 7-Segment LED-Anzeige ausgegeben werden.
    Mit einer 8-bit Zahl habe ich die Ansteuerung des 7-Segment Displays getestet um dies schonmal abzuhaken in seiner Funktion.

    Problem ist, wenn ich eine 16-bit Zahl (hier 6789) sende, gibt die LED-Anzeige lauter Zufallszahlen aus und wechselt hin- und her.

    Ich stehe mit meiner Programmiererfahrung noch ziemlich am Anfang und habe versucht eine Lösung zu finde, jedoch ohne Erfolg. Ich poste die wichtigen Ausschnitte meines Codes (unwichtiges rausgelöscht) was das Senden und Empfangen angeht, wäre nett wenn mir einer helfen kann (ist ja bestimmt nichts großes)

    SENDEN
    Code:
    .
    .
    .
    .
    uint16_t zahl=6789;
    
    uint8_t HByte;
    uint8_t LByte;
    
    
    void daten_senden (uint8_t data)
    {
    	while (!(UCSRA & (1<<UDRE))){} //warten bis senden möglich ist
    	
    	UDR = data; //Zeichen in den Ausgabepuffer schreiben
    }
    
    void usart_init (void)
    {
    	UCSRB |= (1<<TXEN); //Daten senden
    	UCSRC = (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);  // Asynchron 8N1
    	UBRRH = UBRR_VAL >> 8;
    	UBRRL = UBRR_VAL & 0xFF;
    }
    
    
    int main(void)
    {
        usart_init();
    
        while (1) 
        {
    		
    		HByte = (zahl >> 8);
    		LByte = zahl & 0xff;		
    
    		daten_senden(HByte);
    		daten_senden(LByte);		
        }
    }


    EMPFANGEN

    Code:
    .
    .
    .
    
    
    uint16_t zahl;
    uint8_t usart_empfang; 
    
    void usart_init (void)
    {
    	UCSRB |= (1<<RXEN) |(1<<RXCIE) ; //Daten empfangen und Interrupt für Datenempfang enable
    	UCSRC = (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);  // Asynchron 8N1
    	UBRRH = UBRR_VAL >> 8;
    	UBRRL = UBRR_VAL & 0xFF;
    }
    
    
    ISR(USART_RXC_vect)
    {
    	usart_empfang = UDR;	
    }
    
    
    int main(void)
    {	
    	usart_init();
    	
    	sei();
    	
        while (1) 
        {
    		
    		uint8_t HByte = usart_empfang;
    		uint8_t LByte = usart_empfang;
    			
    		zahl = (((uint16_t) HByte) << 8 ) | LByte;
    		
    		zahl_ausgeben(zahl);	
    		
    		
        }
    }

  2. #2
    HaWe
    Gast
    welche µCs programmierst du?
    Ich habe perfekt funktionierenden UART-Code in C/C++ (synchron, quasi per handshake), sowohl für Arduino-Arduino als auch Raspi-Arduino.
    Arduino- und Raspi Codes sind fast 100% identisch, da ich nicht auf die super-speziellen Arduino-libs zugreife:


    Arduino-Arduino
    http://www.mindstormsforum.de/viewto...tart=15#p67476

    Raspi-Arduino
    http://www.mindstormsforum.de/viewto...p=67907#p67815

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    29.12.2014
    Beiträge
    13
    AVR

    Du kannst mir deinen Code ja trotzdem mal schicken, vlt. erkenne ich den Fehler denn komme einfach nicht drauf.

    Wäre nett, danke.

    Edit: habe die Links jetzt auch gesehen danke bin für jeden Tipp dankbar...

  4. #4
    HaWe
    Gast
    ps, lass dich von den Arduino-Display-Treibern nicht verwirren, ich musste den Code so schreiben, dass er mit verschiedenen TFTs und ihren libs funktioniert.

  5. #5
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    33
    Beiträge
    1.192
    Hallo,
    das Problem ist wohl eher, dass hier nicht wirklich synchronisiert wird.
    Die beiden Mikrocontroller starten sicher nicht gleichzeitig in die int main und schon kann es passieren, dass der Empfänger z.B. ein Byte hinterher "hinkt".
    Auch bei dieser Konstruktion
    Code:
    uint8_t HByte = usart_empfang;
    uint8_t LByte = usart_empfang;
    hab ich so meine Bedenken. Ja, die globale Variable usart_empfang wird in der ISR gesetzt.
    Aber wie wird sichergestellt, dass genau in dem passenden Moment auch das nächste Byte vom Sender kommt?
    Es kann hier passieren, dass zweimal das gleiche Byte abgespeichert wird, weil einfach das Timing nicht hinhaut.
    Überlege gerade, ob man usart_empfang nicht sogar als volatile deklarieren sollte...

    Probiere es mal mit Byte pollen an dieser Stelle.
    Und überlege dir was zur Synchronisation.
    Wenn der Empfänger "irgendwann" einliest, kann er am Datenstrom nicht erkennen, wo die most und least significant bytes sind.


    Aber keine Panik, das bekommst du sicher hin. So wild ist das nicht

    Grüße,
    Bernhard
    "Im Leben geht es nicht darum, gute Karten zu haben, sondern auch mit einem schlechten Blatt gut zu spielen." R.L. Stevenson

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    29.12.2014
    Beiträge
    13
    Ich dachte (uSart s=synchron), dass die Synchronisierung der AVR selbst regelt.

    Ok ich muss mich erstmal einlesen, was man unter Byte pollen versteht... an der Stelle sei erneut betont, mein Wissen ist eher dies eines Anfängers^^

  7. #7
    HaWe
    Gast
    jo, ich weiß wohl, warum ich Arduinos und Raspis verwende

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Zitat Zitat von opc Beitrag anzeigen
    Ich dachte (uSart s=synchron), dass die Synchronisierung der AVR selbst regelt.
    Das S steht für synchron, das A aber für asynchron. Der USART versteht zwei unterschiedliche Modi, w4elche aber nur die Bitübertragung betreffen. Bei S braucht es eine zusätzliche Taktleitung, bei A dann Start- und Stopp-Bits.

    Zitat Zitat von opc Beitrag anzeigen
    Ok ich muss mich erstmal einlesen, was man unter Byte pollen versteht... an der Stelle sei erneut betont, mein Wissen ist eher dies eines Anfängers^^
    Zuerst einmal ist so ein USART ein Schieberegister.
    Beim Sender schreibst du dein Datum in das Schieberegister rein und die Bits werden dann einzeln über die Leitung geschoben. Beim Empfänger geht es umgekehrt.
    Wenn du jetzt neue Daten ins Schieberegister schreibst, während die alten noch nicht draussen sind, gibt es Datensalat.
    Praktisch spendet man dem Schieberegister noch ein Buffer-Register in welches du eigentlich deine Daten schreibst. Wenn das Schieberegister leer ist, übernimmt es die Daten aus dem Buffer. Damit du weisst, wann das Buffer-Register geleert ist, gibt es das TE-Bit. Sobald das Buffer-Register geleert ist, wird dieses Bit gesetzt, schreibst du dann was in den Buffer, wird das TE-Bit wieder zurückgesetzt.

    Der Empfänger ist eigentlich gleich aufgebaut. Wenn das Schieberegister alle Bist eingesammelt hat, werden diese in den Buffer kopiert und das RE-Bit gesetzt. Jetzt kann das Schieberegister schon den nächsten Datenstrom empfangen. Beim Lesen des Buffers wird dann das RE-Bit zurückgesetzt oder man muss es extra zurücksetzen.
    Will das Schieberegister Daten in den Buffer schreiben und das RE-Bit ist noch gesetzt, gibt einen Buffer-Overrun-Fehler.

    Je nach Bitrate dauert das Schieben der Daten aber. Bei 9600 Bit/s und asynchron, werden jeweils 10 Bit übertragen, also maximal 960 Zeichen/s. Das sind dann 1.04ms/Zeichen.

    In 1ms kann aber eine CPU eine Menge Code abarbeiten.
    Du musst also in deinem Code sicherstellen, dass beide Bytes auch schon übertragen wurden!


    Code:
        while (1) 
        {
    		
    		uint8_t HByte = usart_empfang;
    		uint8_t LByte = usart_empfang;
    Hier steckt der Wurm drin!
    Bei der zweiten Abfrage von usart_empfang weisst du gar nicht ob da schon was neues drin steht.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  9. #9
    HaWe
    Gast
    seltsam ist schon, dass du beide Bytes getrennt sendest, so kommen sie sicher verzögert an.
    Besser wäre es schon mal, einen Byte-Array zu senden.

    Außerdem ist UART extrem fehleranfällig. Daher verwende ich ein Start-sync-byte und eine checksum, um sicher zu sein, dass auf beiden Seiten der selbe Array rein und wieder raus kommt.

    - - - Aktualisiert - - -

    aaahh, haha, hat sich überschnitten...

Ähnliche Themen

  1. RFM12 und AVR Funkmodul mit Uart Übertragung
    Von Ripper121 im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 15.10.2010, 13:21
  2. uart übertragung 1. bit immer 1
    Von tanger im Forum C - Programmierung (GCC u.a.)
    Antworten: 4
    Letzter Beitrag: 08.03.2008, 10:08
  3. 16bit int über UART versenden
    Von pongi im Forum C - Programmierung (GCC u.a.)
    Antworten: 8
    Letzter Beitrag: 30.07.2007, 18:18
  4. UART Problem mit Übertragung
    Von ricola im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 24.10.2005, 09:39
  5. Wirres Zeug mit C bei der UART übertragung von µC zu PC
    Von MaN im Forum C - Programmierung (GCC u.a.)
    Antworten: 9
    Letzter Beitrag: 01.09.2005, 18:59

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests