Hi Kani,
Irgendwie komme ich mit dem USART nicht klar. Ich glaube die Codebeispiele sind zu hoch für mich.
Soweit bin ich jetzt
CodeBox C
#include <avr/io.h>
/*########## USART initialisieren ##########*/
void USART_Init( unsigned int baud )
{
/* Set baud rate */
UBRRHn = (unsigned char)(baud>>8);
UBRRLn = (unsigned char)baud;
/* Enable receiver and transmitter */
UCSRnB = (1<<RXENn)|(1<<TXENn);
/* Set frame format: 8data, 2stop bit */
UCSRnC = (1<<USBSn)|(3<<UCSZn0);
}
Der Code ist aus dem
Datenblatt des ATMEGA644.
UBRRH
n , UBRRL
n , UCSR
nB , UCSR
nC ...
Der Buchstabe "n" ist klein geschrieben. Ganz im Gegensatz zu den restlichen
Buchstaben. Und "n" wird auch gerne als Nummerierung genommen. Also
müßte das heißen ... UBRRH
0 , UBRRH
1 , UCSR
0B , UCSR
1B , ...
Aber ACHTUNG ! Das ist nicht bei allen ATmegas so. Also sieh in der Register
Summary hinten im Datenblatt nach welche Register und Bits der ATmega
wirklich hat. Bei manchen hast du eine Ziffer drin und bei manchen nicht.
Da bin ich beim ATmega48 auch das erste mal drauf reingefallen. Der
ATmega32 und der ATmega48 haben beide nur einen USART aber beim
32 haben die Register keine Ziffer dazwischen und beim 48 haben sie eine
Null mit drin.
Der ATmega8515 hat keine Ziffern drin.
Hier mal ein Beispiel und Erklärung der Register und Bits in Assembler von
mir. Das mußt Du nur etwas in C umsetzen. ...
CodeBox ASM
; ==================================================================
; ===== USART initialisieren (9k6 8n1) =============================
; ==================================================================
usartinit:
push r16 ; r16 auf Stack retten (fuer wiederherstellung)
;
; ===== BAUDRATE fuer USART =====
;
; U2X=0 Baud = fosc / 16(UBBR+1) , UBBR = ( fosc / 16Baud )-1
; U2X=1 Baud = fosc / 8(UBBR+1) , UBBR = ( fosc / 8Baud )-1
; Baud = bps , fosc = SystemClock , UBBR = UBBRH+UBBRL (0-4095)
;
; 9600 Baud => bei U2X=1 UBBR=207,33 @16MHz
;
; UBRRL - USART Baud Rate Register Low Byte
; * Bit 0..7 : USART Baud Rate Register bit 0..7
;
; UBRRH - USART Baud Rate Register High Byte
; * Bit 0 : USART Baud Rate Register bit 8
; * Bit 1 : USART Baud Rate Register bit 9
; * Bit 2 : USART Baud Rate Register bit 10
; * Bit 3 : USART Baud Rate Register bit 11
; * Bit 4 : 0
; * Bit 5 : 0
; * Bit 6 : 0
; * Bit 7 : USRSEL (Register Select) 1=UCSRC 0=UBRRH
;
ldi r16,0 ; Baudrate-Register HighByte
out UBRRH,r16 ; Highpart = 0
ldi r16,207 ; Baudrate-Register LowByte
out UBRRL,r16 ; Lowpart = 207
;
; UCSRA - USART Control and Status Register A
; * Bit 0 : MPCM Multi-processor Communication Mode
; * Bit 1 : U2X Double the USART transmission speed
; * Bit 2 : UPE Parity Error
; * Bit 2 : PE = UPE For compatibility
; * Bit 3 : DOR Data overRun
; * Bit 4 : FE Framing Error
; * Bit 5 : UDRE USART Data Register Empty
; * Bit 6 : TXC USART Transmitt Complete
; * Bit 7 : RXC USART Receive Complete
; 76543210
ldi r16,0b00000010 ; U2X=1
out UCSRA,r16 ;
;
; URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL
; 7 6 5 4 3 2 1 0 UCSRC
;
; UCSRC - USART Control and Status Register C
; * Bit 0 : UCPOL Clock Polarity
; * Bit 1 : UCSZ0 Character Size Bit 0
; * Bit 2 : UCSZ1 Character Size Bit 1
; * Bit 3 : USBS Stop Bit Select 0 = 1Stop-Bit , 1 = 2 Stop-Bits
; * Bit 4 : UPM0 Parity Mode Bit 0
; * Bit 5 : UPM1 Parity Mode Bit 1
; * Bit 6 : UMSEL USART Mode Select Async=0 Sync=1
; * Bit 7 : URSEL Register Select
;
; UPM 00 Disabled UCSZ 000 5-Bit , 100 Reserved
; 01 Reserved 001 6-Bit , 101 Reserved
; 10 Even Parity 010 7-Bit , 110 Reserved
; 11 Odd Parity 011 8-Bit , 111 9-Bit
;
; SyncMode TxD Changed RxD Sampled
; UCPOL 0 Rising XCK Edge Falling XCK Edge
; 1 Falling XCK Edge Rising XCK Edge
; 76543210
ldi r16,0b10000110 ; URSEL=1 (UCSRC) , USBS=0 UCSZ=3 => Frame-Format 8Bit/1Stop
out UCSRC,r16 ;
;
; UCSRB - USART Control and Status Register B
; * Bit 0 : TXB8 Transmit Data Bit 8
; * Bit 1 : RXB8 Receive Data Bit 8
; * Bit 2 : UCSZ2 Character Size Bit 2
; * Bit 2 : CHR9 = UCSZ2 For compatibility
; * Bit 3 : TXEN Transmitter Enable
; * Bit 4 : RXEN Receiver Enable
; * Bit 5 : UDRIE USART Data register Empty Interrupt Enable
; * Bit 6 : TXCIE TX Complete Interrupt Enable
; * Bit 7 : RXCIE RX Complete Interrupt Enable
; 76543210
ldi r16,0b00011000 ; UCSZ2=0 (8Bit) , TXEN + RXEN => Enable Receiver/Transmitter
out UCSRB,r16 ;
pop r16 ; r16 wiederherstellen
ret ; Subroutine Ende
Danach geht es weiter mit receive and transmit. Also empfangen und senden. Da fängt es an zu hapern. Also es gibt ein Buffer der die Daten erst sammelt/zwischenspeichert, bis eine Reihe/Kette voll ist und dann sendet oder?
Der USART hat ein Register "UDR" USART-Data-Register. Das sind eigentlich
zwei Register. Wenn du Daten liest, dann kommen die aus dem Empfangsteil
des UDR und wenn du Daten schreibst, dann gehen die an den Sendeteil
vom UDR. Er ist also getrennt in Sende- und Empfangsregister. das eine
wird beim lesen angesprochen und das andere beim schreiben.
Sieh dir mal das USART-Block-Diagram im Datenblatt an. Da ist das gut
zu sehen.
Das was du ins Senderegister schreibst wird auf der TxD rausgeschoben.
Was auf der RxD empfangen wird, das landet im Empfangsregister. Das
besteht aus so einem kleinen Zwischenpuffer (FIFO - First In First Out)
von ein paar wenigen empfangenen Zeichen. Wenn es keinen Zwischenpuffer
hätte, dann müßtest Du sofort reagieren, wenn was empfangen wird, damit
das nächste empfangene Byte nicht ins Nirwana läuft (weil das Empfanngs-
register wäre ja noch voll). Darum ist da so ein kleiner FIFO drin. Frag mich
jetzt nicht wie viele Byte der zwischenpuffert (meißt so 4, 8, oder 16).
Also nichts weiter als ne Warteschlange. Ob der Sendepuffer schon wieder
frei ist oder der Empfangspuffer was empfangen hat kannst Du an den
Statusbits im Register UCSRA sehen. Bit 5 => 1 = Sendepuffer leer , Du
kannst wieder was zum senden in den Sendepuffer schreiben.
Bit 7 => 1 = Es ist was im Empfangspuffer was du lesen kannst.
Hier nochmal meine Routinen ...
CodeBox ASM
; ==================================================================
; ===== USART - Daten senden =======================================
; ==================================================================
usartwr: ; Warten auf leeren Sendepuffer
sbis UCSRA,5 ; Skip if Bit 5 is Set : UDRE USART Data Register Empty
rjmp usartwr ; Sende-Buffer noch nicht leer
out UDR,r16 ; Daten (r16) in Sendepuffer schreiben => wird gesendet
ret ; Subroutine Ende
; ==================================================================
; ===== USART - Daten empfangen ====================================
; ==================================================================
usartrd: ; Warten auf Daten im Empfangspuffer
sbis UCSRA,7 ; Skip if Bit 7 is Set : RXC USART Receive Complete
rjmp usartrd ; Noch nichts empfangen
in r16, UDR ; Daten aus Empfangspuffer in r16 einlesen
ret ; Subroutine Ende
Das war es eigentlich soweit. ...
Gruß
Dino