Embedded System/AVR

[AVR] USART 직렬통신 하기(시리얼통신)

임베지수 2017. 4. 2. 14:40

AVR과 컴퓨터간에 시리얼통신으로 데이터를 주고 받아보자. 이론적인 내용은 잘 몰라서 설명은 내 마음대로한다.

 

먼저 시리얼통신에는 동기모드와 비동기모드 두 가지 모드가 있다. 자세한 내용은 잘 모르겠지만 내가 알기론 동기식과 

 

비동기식의 차이는 클럭의 차이다. 디지털회로시간에 배우긴했는데 기억이 가물가물...

 

 

일단 건드려야할 레지스터는 4개 밖에 없다.

 

 

색이 칠해져있는건 뭔지 feel이 온다. UCSR은 저놈들이 중요한놈들이다.

 

일단 UCSRA의 비트5 UDRE는 새로운 송신데이터를 받을 준비가 되어 있으면 set 되는 플래그이다. Read만 가능!

 

UCSRB의 4,3번 비트는 Rx enable, Tx enable이다. 즉 avr의Rx, Tx핀을 일반IO 말고 데이터 송수신 용도로 쓰게한다.

 

UCSRB와 UCSRC의 UCSZ는 전송데이터의 길이를 설정해준다. 5비트부터 9비트까지 가능하다. 자세히는 뭔지 모른다.

 

내생각에는 데이터가 char형 이니까 8비트를 쓰는게 아닐까? 아스키값을 주고 받으니까... 아님 말고

 

패리티비트를 설정해주고 싶으면 데이터시트 보고 UCSRC의 5,4번 비트를 설정해주면 된다.

 

UCSZ는 아래 표를 보고 설정해준다.

 

 

UBRR은 보레이트를 설정해주는 레지스터다. 즉 통신속도를 설정해주는 것이다. 통신속도에 맞는 UBRR 값을  넣어주면 

 

된다. 아래 표는 외부클럭 16MHz기준일때의 값이다. 다른 값들은 데이터시트 ㄱㄱ 캡쳐하기 귀찮음

 

 

 

그럼 데이터는 어디에 저장되는 것인가? UDR이라는 레지스터에 저장된다. 이제 코드를 작성해보다.

 

#include "avr/io.h"
#include "avr/iom128.h"

unsigned char get_data(void)
{
	while(!(UCSR0A&0x80)); // 수신완료될때까지 대기
	return UDR0;
}

void send_data(unsigned char data)
{
	while(!(UCSR0A&0x20)); // 송신데이터를 받을 준비가 될때까지 대기
	UDR0 = data;

	DDRA = 0xff;

	if(data == '1') // 만약 터미널에서 날아온 데이터가 숫자 1 이라면 LED 전부 켜라.
		PORTA = 0x00;
	else			// 1 이외의 값이면 LED 전부 꺼.
		PORTA = 0xff;
}

void main()
{
	UCSR0A = 0x00; // ready flag clear
	UCSR0B = 0x18; // rx, tx enable
	UCSR0C = 0x06; // tx data len : 8bit

	UBRR0H = 0;
	UBRR0L = 51; // boudrate 19200

	while(1)
	{
		send_data(get_data());
	}
}

 

데이터는 어떻게 보내는 것인가? 윈도우7에는 하이퍼터미널이 없다. 따로 프로그램을 구해야한다.

 

위드로봇에서 제공해주는 시리얼프로그램이 괜찮다고 해서 그걸로 설명하겠다.

 

시리얼 프로그램은 http://www.withrobot.com/에서 다운받을 수 있다.

 

프로그램을 실행하면 아래 빨간 네모부분을 설정해준다. 난 시리얼케이블이 COM1로 잡혀있고(컴퓨터마다 다르다. 장치관리자에서 확인할 수 있다.) 통신속도는 19200으로 맞춰주었다. UBRR레지스터 설정한걸 기억하자. Open port를 눌러서 avr과 연결해준다.

 

이제 정상작동 하는지 확인해보자.

 

 

 

전송데이터가 1이 아닌 0일때 LED가 꺼져있다.

 

 

1을 보내면 LED가 전부 켜졌다.