UART 통신을 하려면 Baudrate 설정이 필수적이다.
계산 식은 위의 표와 같이 하면 된다.
ex) 9600bps로 통신을 한다면
UBRR = ( 16Mhz / ( 16 x 9600bps) ) -1 = 106.167 이 되므로
UBRR에는 106즉 0x67을 넣어줘야 한다.
물론 UBRR0H와 UBRR0L로 되어 있어 상위바이트와 하위바이트에 나눠서 넣어주면 된다.
(9600은 하위 8비트 안에 들어가므로 상위에는 0x00을 넣는다.
UDRn 레지스터는 Tx일 때는 Tx로 보낼 데이터를 저장할 Buffer로 사용되고
Rx일 땐 데이터를 받을 Buffer로 사용된다.
이 버퍼가 보낼 준비가 되거나
받을 준비가 된다면
UCSRnA에 있는 UDREn 레지스터가 Set 된다.
TXENn 을 통하여 Tx Enable과
RXENn 을 통하여 Rx Enable을
설정할 수 있다.
보통 UART 통신을 셋팅하는 레지스터가 많다
비동기 신호냐 동기 신호냐 선택 레지스터
페리티비트를 넣을지 말지 선택
스탑비트를 몇 비트로 넣을 건가
캐릭터 사이즈 선택(보통 8bit 선택)
Baudrate 설정 레지스터
다만 아래의 표와 같이
외부 크리스탈에 따른 클럭으로 인하여
통신 에러율이 발생한다.
특히 16Mhz 를 사용하면 통신 오차가 심하다.
그래서 통신용으로 사용한다면 14.7456Mhz 크리스탈로 교체하여 사용한다.
Atmega128에서 UART를 통해 아스키코드 48번부터 122번까지 보내는 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /* * USART_Test2.c * * Created: 2015-01-07 오전 10:49:51 * Author: user */ #include <avr/io.h> #include <util/delay.h> void putchar1(char c){ while( (UCSR0A & (1<<UDRE0)) == 0 ); UDR0 = c; } /* UCSR0A의 5bit에 있는 UDRE0는 Transmit Buffer를 가리키는 Indicator이다. 만약 Buffer에 있는 데이터를 다 전송하면 UDRE0는 1로 Set된다. */ int main(void) { unsigned char i=48; UCSR0A = 0x00; UCSR0B = (1<<TXEN); // Tx Enable //Asynchronous Mode UCSR0C = (1<<UCSZ1)|(1<<UCSZ0); // 8bit, 1stopbit, no parity UBRR0H = 0x00; // UBRR = (16/(16*9600))-1 = 103.167 UBRR0L = 0x67; // Baudrate = 9600 while(1) { putchar1(i++); _delay_ms(500); putchar1(10); if(i == 122) i = 48; } } | cs |
Atmega128에서 Hello World! 를 보내는 코드
putString을 통해 캐릭터 하나씩 보내는 방식
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | /* * USART_Test2.c * * Created: 2015-01-07 오전 10:49:51 * Author: user */ #include <avr/io.h> #include <stdio.h> #include <util/delay.h> void putChar1(char c){ while( (UCSR0A & (1<<UDRE0)) == 0 ); UDR0 = c; } /* UCSR0A의 5bit에 있는 UDRE0는 Transmit Buffer를 가리키는 Indicator이다. 만약 Buffer에 있는 데이터를 다 전송하면 UDRE0는 1로 Set된다. */ void putString(char *string){ unsigned char i=0; while(string[i] != 0){ // 문자열의 맨 마지막엔 항상 NULL문자가 있으므로 putChar1(string[i++]); // NULL문자가 나올때 까지 1byte씩(캐릭터문자) 보냄 } // 마지막에 Line Feed 보내숴 시리얼 모니터의 뉴라인 생성 putChar1(0x0A); } int main(void) { //unsigned char i=48; char *string = "Hello World!"; UCSR0A = 0x00; UCSR0B = (1<<TXEN); // Tx Enable //Asynchronous Mode UCSR0C = (1<<UCSZ1)|(1<<UCSZ0); // 8bit, 1stopbit, no parity UBRR0H = 0x00; // UBRR = (16/(16*9600))-1 = 103.167 UBRR0L = 0x67; // Baudrate = 9600 while(1) { putString(string); _delay_ms(1000); } } | cs |