du musst halt die Zahl in einzelne Bytes zerlegen. Wie du das dann genau aufbaust bleibt dir überlassen -- es muss schließlich nur auf beiden Seiten die gleiche Form haben.
Hallo zusammen!
Hab schon einige Beträge hier zu UART gelesen, mein Problem hab ich aber noch nicht gefunden:
Ich habe zwei Atmegas über UART verbunden was auch funktioniert, wenn ich Zahlen <255 verschicke.
Wie kann ich jetzt am geschicktesten eine 16 oder 32 bit Zahl senden und vom anderen Contoller empfangen?
Die UDR Register können nur 8bit aufnehmen, oder? und erwarten als Variablentyp ein unsigned char.
Grüße
du musst halt die Zahl in einzelne Bytes zerlegen. Wie du das dann genau aufbaust bleibt dir überlassen -- es muss schließlich nur auf beiden Seiten die gleiche Form haben.
Wie man Fragen richtig stellt:
http://www.lugbz.org/documents/smart-questions_de.html
kannst du mir nen kleinen Einstieg / Beispiel geben wie man das in C macht?
Und wie kann ich beim Empfangen unterscheiden welches Byte wohin gehört?
In dem Du ein Übertragungsprotokoll festlegst. Am einfachste geht das so:Zitat von Karl Napf
zuerst schickst Du ein bestimmtes byte, an dem der Empfänger erkennt, dass gleich eine Zahl übertragen wird. Das byte kann z.b. eine 0x02 sein. Danach überträgst Du die Variable als ein Hex-Wert mit ASCI-Zeichen. Da die einzelnen Zeichen alle einen Wert über 0x02 haben, ist eine Verwechselung mit dem Startbyte 0x02 ausgeschlossen. Danach sendest Du ein Abschlussbyte, z.b. 0x04, was das Ende der Übertragung signalisiert. Letzteres kann aber auch wegfallen. Der Empfänger muss jetzt warten, bis das Startbyte bei ihm ankommt. Dann weiss er, dass die nächsten 4 bzw 8 Bytes eine Zahl sind, empfängt diese und wandelt sie in einen 16/32bit wert um.
MfG Mark
Ich will z.B eine Zahl wie 43692 übertragen.
Das mit dem Zerlegen in Bytes hab ich hingekriegt
könnte so ausehen:
int16_t Value
((Value >> 8) & 0xFF);
((Value >> 0) & 0xFF);
Aber wie kann ich die 2 Bytes beim Empfangen wieder zu ordnen. Muss ich ein Bit von dem jeweiligen Byte für die Zuordnung reservieren und das dann abfragen?
Geht's nicht irgendwie einfacher oder gibt's was fertiges?
du hast eine serielle Verbindung die auf 8 bit Werten basiert. Du wirst also immer irgendein Protokoll machen müssen -- z.b. könnstest du über eine GPIO-Verbindung ein Handshaking machen und dann einfach n Werte in festgelegter Reihenfolge und Form übertragen. Oder du nimmst 7 bit und das 8. bit also Statusbit (z.b. um die Zahl als solche zu markieren, oder in einen Kommandomodus umzuschalten).
Was du jetzt genau mit dem "zuordnen" am Empfänger meinst ist mir aber nicht wirklich klar ... du musst halt dein Protokoll dekodieren.
Wie man Fragen richtig stellt:
http://www.lugbz.org/documents/smart-questions_de.html
mit zuordnen mein ich wenn mein UART zwei 8bit Werte nacheinader empfängt und ich sie danach zu einer 16bit Zahl zusammen fügen will muss ich doch wissen welches das high Byte und welches das low Byte ist.
Kannst du mir die zweite Möglichkeit ein bißchen genauer erklären, hab von "Bussystemen" leider wenig Ahnung und wie man das in C implementiert ist mir auch nicht.
na ja, du kannst z.b. zwei GPIOs miteinander verbinden. Auf dem Sender ist das dann ein Ausgang, beim Empfänger ein Eingang. Wenn du jetzt beispielsweise eben den Pin auf 1 ziehst bedeutet das "jetzt kommt ein 16bit Wert" und hast vorher verbindlich festgelegt dass das MSB zuerst kommt. Dann sendest du die zwei Bytes und macht den Pin wieder aus.
Wenn du ohne sowas auskommen willst kannst du eben einfach erst 7 bit schicken und verbindlihc vereinbaren dass wenn das 8. bit aus ist dass das MSB ist. Dann schickst du das LSB und machst das 8. bit an. Allerdings verlierst du damit 2 bit aus deiner 16bit Zahl, d.h. du kannst so nur 14 bit übertragen.
Aber ich versteh dein Problem sowieso nicht ganz: du musst einfach nur _vorher_ verbindlich für _beide_ Seiten festlegen wie die Reihenfolge ist. Du musst halt darauf achten dass beide Controller synchronisiert sind. Wie z.b. mit der GPIO-Methode, oder du musst das über eine Startup condition machen. Oder du schickst nach dem Einschalten einfach mal 20 Nullbytes und vereinbarst dass nach mehr 20 Nullbytes mit einem darauffolgenden 0xff die Synchronisation anfängt.
Es gibt da quasi beliebig viele Möglichkeiten.
Wie man Fragen richtig stellt:
http://www.lugbz.org/documents/smart-questions_de.html
ich hab's jetzt mal so probiert:
hab außer RXD und TXD noch eine Verbindung zwischen den beiden Contoller hergestellt.
Jetzt setze ich den einen Pin high und der Sender soll das erste Byte schicken. Danach wieder low und beim 2. high soll er das 2. Byte schicken (der Sender zählt die Anzahl der highs/ Impulse mit).
Das funktioniert so aber nicht, mein Display zeigt die beiden Werte abwechseln an.
Code vom Sender:
hier der Code vom Empfänger:Code:void uart_putc(unsigned char zahl) { while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ { } UDR = zahl; /* sende Zeichen */ } int main(void) { //Steuerleitung DDRA &= ~(1<<DDA6); //Eingang //init UART UBRRH = 0; // Highbyte ist 0 UBRRL = 3; // Lowbyte ist 51 UCSRB |= (1<<TXEN); //auf senden gestellt UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); unsigned char Bsp1 = 43; unsigned char Bsp2 = 78; int i = 0; for( ; ; ) { if(i==0) { if (PINA & (1<<PINA6)) { uart_putc(Bsp1); i=1; } } else if (i==1) { if (PINA & (1<<PINA6)) { uart_putc(Bsp2); i=0; } } } return 0; }
Code:unsigned char uart_getc(void) { while (!(UCSRA & (1<<RXC))) { } // warten bis Zeichen verfügbar return UDR; // Zeichen aus UDR zurueckgeben } int main(void) { lcd_init(LCD_DISP_ON); //Display lcd_clrscr(); //init UART UBRRH = 0; // Highbyte ist 0 UBRRL = 3; // Lowbyte ist 51 UCSRB |= (1<<RXEN); //auf empfangen gestellt UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //Steuerleitung DDRD |= (1<<PD2); //Ausgang char buffer1[6]; char buffer2[6]; int a; int b; while(1) { PORTD |= (1<<PD2); a = uart_getc(); PORTD &= ~(1<<PD2); PORTD |= (1<<PD2); b = uart_getc(); PORTD &= ~(1<<PD2); itoa( a, buffer1, 10 ); lcd_gotoxy(0, 0); lcd_puts(buffer1); itoa( b, buffer2, 10 ); lcd_gotoxy(0, 1); lcd_puts(buffer2); } return 0; }
Ähm ... das sieht doch so richtig aus. Wenn der Wert 16 bit sein soll musst du auf Empfängerseite beide Werte natürlich noch zusammensetzen. Also val = byte1 | (byte2<<Zitat von Karl Napf
Oder überseh ich gerade was?
Wie man Fragen richtig stellt:
http://www.lugbz.org/documents/smart-questions_de.html
Lesezeichen