Hallo, ich versuche in Rahmen einer Hausarbeit innerhalb meines Studiums die UART-Schnittstelle eines AT90CAN128 in Betrieb zu nehmen. Nun zu der Frage an dem mein Verständnis zerbricht. Wie ist es möglich, dass das Datenregister UDR0 gleichzeitig für Eingang und Ausgang zuständig ist. So wie ich es aus dem Datenblatt erlesen habe muss man um Daten zu senden diese in das Datenregister UDR0 schreiben und bei empfang diese aus UDR0 lesen. Wie wird nun unterschieden ob man lesen oder schreiben will? Ich füge noch meine ini und ISR bei, vielleicht habe ich hier schon einen Fehler der mein Unverständnis erklärt. Die Daten werden jeweils in einem FIFO abgelegt. Beim Senden aus dem FIFO gelesen und in das Datenregister eingetragen. Beim Empfangen aus dem Datenregister gelesen und in das FIFO eingetragen. Die Interrupts würden dafür in einer zusätzlichen Funktion freigegeben. Danke schon mal für alle Antworten. #ifndef fCPU #define fCPU 16000000 #endif //global variables enum E_MODE {Error,no_Error}; volatile uint8_t uart_str_complete = 0; // 1 .. String komplett empfangen E_MODE set_BAUD(uint16_t BAUD){ double BAUD_real, Error_value; uint16_t UBRR0_value; UBRR0_value=fCPU/(16*BAUD)-1; //calculate the count value BAUD_real=double(fCPU)/(16*(UBRR0_value+1));//calculate the real baud Error_value=(1-(BAUD_real/BAUD))*100; //calculate the error if(0.5 <= Error_value){ //if the error to high return error return Error; } else{ //else write the count value to the UBRR0 register UBRR0H = (UBRR0_value>>8)&0xFF; UBRR0L = UBRR0_value&0xFF; return no_Error; } } E_MODE init_UART0(uint16_t BAUD){ if(Error==set_BAUD(BAUD)){ return Error; } else{ //disable multiprocessor mode and double asynchronous mode UCSR0A &= ~((1<<MPCM0)|(1<<U2X0)); UCSR0B &= ~(1<<UCSZ02); //select frame size 8 bit UCSR0C |= ((1<<UCSZ00)|(1<<UCSZ01)); //select frame size 8 bit UCSR0C &= ~((1<<UPM00)|(1<<UPM01)); //select no parity mode UCSR0C &= ~(1<<USBS0); //select one stop bit UCSR0C &= ~(1<<UMSEL0); //select asynchronous mode UCSR0B |= ((1<<RXEN0)|(1<<TXEN0)); //enable Receiver, Transmitter return no_Error; } } ISR(USART0_RX_vect){ //Interrupt service routine for receive data unsigned char temp; cli(); temp = UDR0; if(uart_str_complete==0){ Write_UART_Fifo_RXD(temp); if('\n'==temp){ uart_str_complete = 1; Write_UART_Fifo_RXD(uint8_t('\0')); UCSR0A &= ~(1<<RXCIE0); //disable receive complete interrupt } } sei(); } ISR(USART0_UDRE_vect){ //Interrupt service routine for transmitte data unsigned char temp; cli(); if('\0'==temp){ UDR0=temp; uart_str_complete = 1; UCSR0A &= ~(UDRIE0); //disable data register empty interrupt } else{ Read_UART_Fifo_TXD(temp); UDR0=temp; } sei(); }
Falls ich noch relevante Informationen vergessen habe sollte schreibt bitte was Ihr für eine Antwort noch benötigt. Gruß Manuel
Hi > UCSR0A &= ~((1<<MPCM0)|(1<<U2X0)); > UCSR0B &= ~(1<<UCSZ02); //select frame size 8 bit > UCSR0C |= ((1<<UCSZ00)|(1<<UCSZ01)); //select frame size 8 bit > UCSR0C &= ~((1<<UPM00)|(1<<UPM01)); //select no parity mode > UCSR0C &= ~(1<<USBS0); //select one stop bit > UCSR0C &= ~(1<<UMSEL0); //select asynchronous mode > UCSR0B |= ((1<<RXEN0)|(1<<TXEN0)); //enable Receiver, Transmitter Gehts irgendwie noch komplizierter? Außer UCSZn1 und UCSZn0 in UCSR0C sind alle Bits in UCSRnA, UCSRnB und UCSRnC nach einem Reset = 0. MfG Spess
Hallo, > Wie ist es möglich, dass das Datenregister UDR0 gleichzeitig für Eingang > und Ausgang zuständig ist Weil es sich physikalisch um 2 Register handelt: eines, das geschrieben wird (Senden), und ein weiteres, das gelesen wird (Empfangen). Sie werden lediglich über die gleiche Adresse angesprochen. Übrigens ist es in der ISR nicht notwendig, Interrupts mittels cli() und sei() zu manipulieren. Beim Aufruf einer ISR werden von der AVR-CPU standardmässig alle weiteren Interrupts so lange gesperrt, bis die Routine verlassen wird. Zum UART-Handling von AVR's gibt es hier im Forum auch ein Tutorial; dort einfach mal reinschauen.
Hallo, Danke für die schnelle Antwort. Das erhellt mein Horizont deutlich. Wegen der Komplexität, ja ist kompliziert aber wird so verlangt. Sonst argumentiert der Prof, dass ja möglicherweise durch einen vorherigen Zugriff die Register schon verändert wurden und wenn man dann nicht alles nötige auf 0 setzt funktioniert es nicht. Habe das zumindest mal so erlebt.
Hi >Sonst argumentiert der Prof, dass ja möglicherweise durch einen >vorherigen Zugriff die Register schon verändert wurden und wenn man dann >nicht alles nötige auf 0 setzt funktioniert es nicht. Und was ist mit einem hartem UCSR0B = ((1<<RXEN0)|(1<<TXEN0)) Dann spart man sich diese Weicheierprogrammierung wie UCSR0B &= ~(1<<UCSZ02); MfG Spess
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.