시리얼 통신 방법중 하나로 이외 흔히 사용되는 방법으론 SPI와 I2C등이 있다
가장 오래된 통신방법
그렇게 하여 나온것이 보율(baud rate)이다.
이는 프랑스의 과학자 장 모리스 에밀 보도(Jean Maurice Emile Baudot)의 이름을 따온 것이다.
초기 데이터 통신에 있어서 보통 1초 동안 전달되는 데이터 비트의 수를 나타내는 단위로 모뎀 등의 데이터 단위를 사용하였다, 이 경우는 보율의 단위가 bps(bit per second)가 된다. 하지만 기술발전에 따라 많은 정보 표현이 가능해졌기에 bps는 보율과 같거나 더 크게 된다.
만약 데이터의 변화는 4번이지만 변할떄마다 받는 정보가 2비트라면 8bps라는 보율을 가지게 된다.
송, 수신의 보율이 같다가 항상 정확하게 통신이 이루어지는것은 아니다.
송신의 경우 필요할떄만 이루어지는데, 이떄 어느떄부터가 송신을 보낸것인지 수신부에서는 이해하지 못하기떄문이다. 이를 위해 '0'이 시작 비트, '1'이 정지 비트로 사용된다. UART는 바이트 단위(8 bit)로 통신하며, 여기에 시작, 정지 비트를 추가하여 총 10비트를 전송하는 것이 일반적이다.
데이터를 받지 않을떄는 '1'신호를 받지만, 받는 시점부터 '0'의 신호를 받으며, 실제 데이터인 8비트 데이터 수신후 끝 신호인 '1'의 신호를 받게된다.
ATmega128의 경우 2개의 UART가 있다.
흔히 UART0, UART1이라고 한다.
UART | RX | TX |
---|---|---|
UART0 | PE0 | PE1 |
UART1 | PD2 | PD3 |
연결시 RX, TX는 서로 교차해서 연결 해야한다.
연결 | 컴퓨터 | ATmega128 |
---|---|---|
- | RX | TX |
- | TX | RX |
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
READ | RXB7 | RXB6 | RXB5 | RXB4 | RXB3 | RXB2 | RXB1 | RXB0 |
WRITE | TXB7 | TXB6 | TXB5 | TXB4 | TXB3 | TXB2 | TXB1 | TXB0 |
초기값 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
송수신된 데이터가 저장되는 버퍼 레지스터
TXB=전송
RXB=수신
이둘의 레지스터는 동일한 입출력 주소를 사용한다.
송신할 경우 TXB에 저장되고, 수신할 경우 RXB로 저장된다.
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | RXCn | TXCn | UDREn | FEn | DORn | UPEn | U2Xn | MPCMn |
이름 | 비트 | 역할 |
---|---|---|
RXCn | 7 | 수신버퍼(UDRn의 RXB)에서 아직 읽지 않은 데이터가 있을 경우 1 읽을 경우 0이 된다 이 비트가 1일 경우 수신 완료 인터럽트 발생 |
TXCn | 6 | 송신 버퍼가 비면 (다 보냈을경우) 1이 된다. 이 비트가 1일 경우 송신 완료 인터럽트 발생 처리 후 0이 된다. |
UDREn | 5 | UDRn이 비어 있을(송수신 공간이 전부 비었을) 경우 새로운 데이터를 받을수 있게 1이되는 상태 플레그 |
FEn | 4 | 수신데이터가 없을 경우 HIGH 상태이며, 데이터 프레임 수신이 시작되는 순간부터 LOW 가 된다. |
DORn | 3 | 수신 버퍼가 가득 찬 상태에서 수신 시프트 레지스터에 새로운 문자가 수신되고 다시 그 다음 문자의 시작 비트가 검출되는 오버런 상황이 발생할때 1이 된다. |
UPEn | 2 | 수신 버퍼에 저장된 문자 데이터에 패리티 오류가 발생시 1의 값을 가짐. 패리티 비트사용이 설정된 경우만 사용가능 |
U2Xn | 1 | 비동기 전송 모드에서만 사용되며, 2배속이면 1, 1배속이면 0의 값을 가짐 |
MPCMn | 0 | 멀티 프로세서 모드 1, 일반 모드 0 |
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | RXCIEn | TXCIEn | UDRIEn | RXENn | TXENn | UCSZn2 | RXB8n | TXB8n |
이름 | 비트 | 역할 |
---|---|---|
RXCIEn | 7 | 수신 완료 인터럽트 허용 비트 |
TXCIEn | 6 | 송신 완료 인터럽트 허용 비트 |
UDRIEn | 5 | 송신데이터 레지스터 준비 완료 인터럽트 발생 허용 비트 |
RXENn | 4 | 수신 허용 비트 |
TXENn | 3 | 송신 허용 비트 |
UCSZn2 | 2 | UCSRnC의 1,2 번 비트와 함께 전송 문자 길시 설정 비트 (일반적으론 8비트사용) |
RXB8n | 1 | 수신 데이터가 9비트인 경우 데이터의 9번째 비트 반드시 UDRn 레지스터보다 먼저 읽어야 한다 |
TXB8n | 0 | 송신 데이터가 9비트인 경우 데이터의 9번째 비트 반드시 UDRn 레지스터보다 먼저 써야 한다 |
비트 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
이름 | - | UMSELn | UPMn1 | UPMn0 | USBSn | UCSZn1 | UCSZn0 | UCPOLn |
이름 | 비트 | 역할 |
---|---|---|
- | 7 | - |
UMSELn | 6 | 동기 or 비동기 설정 비트 |
UPMn1 | 5 | 패리티 모드 설정 비트 |
UPMn0 | 4 | 패리티 모드 설정 비트 |
USBSn | 3 | 정지 비트수 지정 0 : 1비트 , 1 : 2비트 |
UCSZn1 | 2 | UCSRnB의 UCZn2와 같이 쓰이는 비트들로 데이터 비트수를 정하는 비트들이다. |
UCSZn0 | 1 | UCSRnB의 UCZn2와 같이 쓰이는 비트들로 데이터 비트수를 정하는 비트들이다. |
UCPOLn | 0 | 동기식 모드일때 1로 설정 클록(XCK)의 극성을 지정한다. |
4.1. UPMnX 표
UPMn1 | UPMn0 | |
---|---|---|
0 | 0 | 없음 |
0 | 1 | - |
1 | 0 | 짝수 패리티 |
1 | 1 | 홀수 패리티 |
UCSZn2 | UCSZn1 | UCSZn0 | 비트 |
---|---|---|---|
0 | 0 | 0 | 5 |
0 | 0 | 1 | 6 |
0 | 1 | 0 | 7 |
0 | 1 | 1 | 8 |
1 | 0 | 0 | - |
1 | 0 | 1 | - |
1 | 1 | 0 | - |
1 | 1 | 1 | 9 |
UBRRnH
UBRRnL: 보율 설정용 비트
#include <avr/io.h>
void UART1_init(void)
{
UBRR1H=0x00;
UBRR1L=0x16;
UCSR1A|=_BV(U2X1);
UCSR1C|=0x06;
UCSR1B|=_BV(RXEN1);
UCSR1B|=_BV(TXEN1);
}
void UART1_transmit(char data)
{
while(!(UCSR1A&(1<<UDRE1)));
UDR1=data;
}
unsigned char UART1_receive(void)
{
while(!(UCSR1A&(1<<RXC1)));
return UDR1;
}
void UART1_print_string(char *str)
{
for(int i=0; str[i];i++){
UART1_transmit(str[i]);
}
}
void UART1_print_1_byte_number(uint8_t n)
{
char numString[4]="0";
int i,index=0;
if(n>0){
for(i=0;n!=0;i++){
numString[i]=n%10+'0';
n=n/10;
}
numString[i]='\0';
index=i-1;
}
for(i=index;i>=0;i--){
UART1_transmit(numString[i]);
}
}
#ifndef UART1_H_
#define UART1_H_
void UART1_init(void);
void UART1_transmit(char data);
unsigned char UART1_receive(void);
void UART1_print_string(char *str);
void UART1_print_1_byte_number(uint8_t n);
#endif
#include <avr/io.h>
#include "UART1.h"
int main()
{
UART1_init();
char str[]="Test using UART1 Library";
uint8_t num=128;
UART1_print_string(str);
UART1_print_string("\n\r");
UART1_print_1_byte_number(num);
UART1_print_string(str);
while(1){
UART1_print_string(str);
UART1_print_string("\n\r");
}
return 0;
}