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.