티스토리 뷰
위의 그림은 AVR에 있는 UART블럭의 블럭도이다. UART블럭은 크게 세부분으로 나누어 볼 수 있다. 데이터를 정확한 시간에 맞춰 내보내거나, 수신되는 데이터를 정확한 위치에서 샘플링할 수 있게 하기 위한 clock generator가 있고, 송신기능을 처리해 주는 transmitter가 있다. 그리고 수신기능을 담당하는 receiver블럭이 있다.
그림을 자세히 보면 알겠지만 UART 블럭에는 Data bus에 연결된 다섯개의 레지스터를 찾을수가 있다.
클럭 설정을 하기 위한 UBRR레지스터가 있다. UART에서 통신 속도를 baud rate라고 하는데 이 값은 아무값이나 설정해서 사용하는 것이 아니고 정해진 몇개의 값들이 있다. 예전에는 9600bps를 많이 사용하였다. 그러나 최근의 임베디드 시스템에서는 115200bps를 주로 쓴다. 이 외에도 GPS모듈과 같이 UART로 통신하는 부품들은 57600이나 38400 등등 정해진 다른 값들을 사용하기도 한다. Baud rate 속도가 미리 정해져 있는 경우는 거기에 맞춰서 동작되도록 할 수 밖에 없겠지만, 그렇지 않고 디버깅을 위하여 컴퓨터와 통신할 때에는 가급적이면 빠른 속도로 통신하는게 좋다.
UART블럭의 제어와 인터럽트 설정등 기타 기능을 제어하기 위한 UCSRA, UCSRB, UCSRC 레지스터가 있다.
송신 데이터를 내보내거나 수신데이터가 저장되는 UDR레지스터가 있다. Transmitter블럭에도 UDR레지스터가 있고, receiver블럭에도 UDR 레지스터가 있다. 이름과 주소가 같지만 하드웨어적으로는 서로 따로 존재한다. CPU에서 UDR레지스터에 쓰기 동작을 하면 Transmitter에 있는 UDR레지스터에 값을 쓰게 되고, 읽기 동작을 수행하면 Receiver에 있는 UDR레지스터에서 데이터를 읽어 오게 된다.
Datasheet 문서를 참조하여 UART를 동작시켜 보도록 하겠다. 먼저 UART 통신에 사용되는 TXD와 RXD 핀이 어디에 있는지 알아보자.
AVR 전체 블럭도에서 UART 블럭을 찾아 보면 PORT D블럭과 서로 화살표가 연결되어 있는것을 볼 수 있다. 이것은 UART에서 사용하는 시그널이 PORT D를 통해서 외부와 연결된다는 것을 표시해 주는것이다. 그러므로 문서의 핀 구성도에서 PD로 시작되는 핀에서 찾으면 쉽게 UART에서 사용하는 핀을 찾을 수 있다.
핀 구성도에서 보듯이 PD0핀에 (PCINT16/RXD)라고 되어 있고, PD1에는 (PCINT17/TXD)라고 되어 있다. 이와 같이 하나의 핀을 여러 용도로 다르게 사용할 수 있는데 이런것을 alternate function이라고 부른다. 이렇게 하는 이유는 CPU에서 사용할 수 있는 기능은 많은데 밖으로 나오는 핀의 개수는 한계가 있기 때문에 핀을 서로 공유할 수 밖에 없기 때문이다. 다른 표현으로는 핀이 mux되었다라고도 한다.
위의 Table 14-9라고 되어 있는 표를 보면 PD0는 UART input pin으로 PD1은 UART output pin으로 사용된다고 표시되어 있다. 그러므로 UART 통신을 위해서 PD0와 PD1 핀을 컴퓨터와 연결하면 된다는 것을 알 수 있다.
다음으로는 앞에서 살펴봤던 UART 레지스터의 주소가 무엇인지 알아 보는 것이다.
Datasheet 문서의 register summary에서 UART 관련 레지스터를 찾아봤더니 위의 그림과 같은 주소값을 볼 수 있다. 레지스터들이 연속해서 있으므로 C프로그램에서는 구조체를 이용하면 좋을것 같다.
#define UART_REG 0xC0 struct uart { uint8_t ucsr_a; uint8_t ucsr_b; uint8_t ucsr_c; uint8_t reserved; uint8_t ubrr_l; uint8_t ubrr_h; uint8_t udr; }; volatile struct uart *const uart = (void*)UART_REG;
이제 위의 구조체를 이용하여 UART 초기화 과정을 구현해 보겠다.
AVR datasheet 문서에도 UART 초기화 코드 예제가 나오므로 문서를 참조하여 위의 코드와 다르게 구현할 수도 있다.
UCSRB레지스터에는 Tx enable, Rx enable 설정 비트가 있다. UART를 초기화 할때는 일단 TX,RX를 disable 시킨후에 다른 레지스터를 변경하는 것이 일반적이다. 따라서 5번 줄은 UART의 TX,RX를 disable 시키는 코드이다.
UCSRA레지스터는 주로 status 확인 용도로 주로 쓰인다. 초기화 과정에서는 0으로 설정하도록 한다.
UCSRC는 데이터 크기와 패리티비트 사용여부, stop 비트 크기를 설정하는데 사용된다. 일반적으로 데이터크기는 8, no parity, stop bit 1으로 설정한다. 위의 코드에서도 이와 같이 설정하였다.
기본적인 UART설정을 완료한 이후에 가장 중요한 baud rate를 설정해 주어야 한다.
위의 그림이 baud rate설정을 위한 계산식을 설명하는 것이다. AVR에서 baud rate 설정은 UBRR 레지스터를 사용하는데 위의 계산식에서 보다시피 UBRR과 baud rate는 반비례관계에 있음을 알 수 있다. 즉 UBRR의 값이 커지면 baud rate는 작아지고, UBRR의 값이 작아질수록 baud rate는 높아지게 된다. 계산식에 포함된 16은 샘플링 값이다.
AVR의 동작 클럭 속도가 1MHz일때 가장 높은 속도의 baud rate는 위의 계산식에 의하여 1000000 / 16 = 62500가 된다. 62500bps는 일반적으로 사용되는 값이 아니므로 이보다 낮은 속도중에 사용가능한 baud rate는 57600이다.
이제 baud rate 57600을 설정하기 위한 UBRR값을 구해 보도록 하겠다. 1000000 / (16*57600) - 1 = 0.0850 의 값이 나온다. UBRR은 정수값만 설정 가능하므로 소수점이하 값은 버리고 정수값인 0이 57600bps를 위한 UBRR 값이 된다. 그런데 여기에서 문제가 발생하게 되는 것이다. 원래대로 하면 소수점 아래부분까지 UBRR 설정에 포함되어야 정확한 baud rate 설정이 되는데, 이 부분을 떼어냄으로 인하여 그 만큼의 오류가 발생하는 것이다. 즉 8.5%만큼의 baud rate오류가 발생하는 것이다. 이 오류를 구하는 공식이 datasheet 문서에 나와 있다.
그리고 대표적인 baud rate값에 따른 에러율을 표로 만들어서 제공하기도 한다.
위의 표가 AVR 동작 클럭이 1MHz일때의 UBRR 값과 그에 따른 에러율을 각 baud rate별로 설명해 놓은 것이다. 위의 표를 보면 4800bps로 설정할 때 에러율이 가장 낮게 나오므로 일단은 4800bps로 동작될 수 있게 UBRR 값을 설정하도록 하겠다. 참고로 위의 표를 보면 U2X 값이 0일때와 1일때 두가지 경우에 대해서 에러율을 표시해 주는데 U2X값을 1로 설정하면 샘플링 배수가 16이 아니고 8이 된다. 이렇게 하면 샘플링 속도가 반으로 줄어들게 되므로 같은 UBRR에 대해서 baud rate가 두배가 된다. 예를 들면 U2X가 0일때 UBRR의 값이 12이면 baud rate가 4800이지만, U2X가 1일 때 UBRR의 값이 12가 되면 baud rate가 9600으로 두 배가 되는것을 볼 수 있다. 이런 옵션이 AVR에서 제공되는 이유는 AVR의 동작 클럭이 비교적 낮은 속도이므로 최대로 설정할 수 있는 baud rate가 상대적으로 낮을 수 밖에 없다. 조금이라도 지원하는 baud rate값을 키우기 위해서 샘플링 속도를 낮추는 방법을 제공하는 것이다. U2X비트는 UCSRA 레지스터에서 설정할 수 있다.
UART 초기화 코드의 8,9번 라인이 UBRR 레지스터에 값을 입력하는 것이다. Baud rate설정이 끝났으면 마지막으로 송수신 기능이 활성화 되도록 UCSRB레지스의 Rx enable, Tx enable 비트값을 설정하면 된다.
이제 초기화 과정이 끝났으면 UART 데이터가 제대로 나가는지 확인해 보는 코드를 만들어 보겠다. 송수신 기능을 동시에 확인하는 것이 아니라 일단 AVR에서 송신이 제대로 되는지부터 확인하는 것이 좋다. 그 이유는 컴퓨터는 이미 UART 기능이 검증되었다고 가정할 수 있기 때문에 AVR의 송신 기능이 제대로 동작된다면 컴퓨터에서 그 결과를 바로 확인해 볼수 있다. 만약 수신기능부터 먼저 확인하는 경우 제대로 수신이 되었는지 확인할 방법이 없기 때문이다.
AVR에서 데이터를 내 보낼때는 UCSRA레지스터의 UDRE 비트값이 1로 되어 있는지 확인한 후에 데이터를 내보내야 한다. 만약 이 값이 0으로 되어 있으면 현재 데이터를 내 보내고 있는 중이라는 것을 알려 주는 것이다.
위와 같이 코드를 만들면 200msec마다 ">"가 컴퓨터 화면에 나타날 것이다.
AVR 설정과 송신 코드가 완료 되었으므로 이제 컴퓨터에서 UART 통신을 하는 방법에 대해서 설명 하도록 하겠다.
USB to Serial 장치를 이용하여 UART통신을 할 것이므로 컴퓨터의 장치관리자에 USB장치가 등록되었는지 먼저 확인하여야 한다.
위의 그림에 보이는것처럼 장치관리자의 포트(COM & LPT)에 USB-to-Serial Comm Port(COM3)가 정상적으로 등록되어 있는것을 볼 수 있다. 이 포트를 통해서 UART 통신이 이루어 지는 것이다.
컴퓨터에서 UART통신을 하기 위하여 터미널 프로그램을 설치하여야 한다. 대표적인 터미널 프로그램으로 윈도우 OS에서 제공하는 하이퍼터미널이 있는데 최근의 윈도우OS에는 이 프로그램이 빠져 있다. 따라서 인터넷에서 터미널 프로그램을 다운받아 설치하여야 한다. 많은 터미널 프로그램이 있으므로 개인 취향이나 기능을 살펴보고 하나 설치하면 된다. 어차피 UART 통신은 기본 기능이므로 대동소이할것으로 예상된다.
이 블로그에서는 테라텀(TeraTerm)을 기준으로 설명하도록 하겠다. 인터넷에서 테라텀을 검색하여 설치한다.
테라텀을 실행하면 다음과 같은 화면이 나온다.
장치관리자에서 확인했던 COM3포트를 선택한 후 OK버튼을 누른다.
그 다음 AVR에서 설정하였던 UART설정과 동일하게 테라텀에서도 UART 설정을 해 주어야 한다.
테라텀 프로그램의 메뉴에서 Setup > Serial Port...을 선택하면 위의 다이얼로그 화면을 볼 수 있다. Baud rate값을 4800으로 하고 Data크기 8비트, Parity None, Stop 비트 1로 설정한 후 OK를 누른다.
그럼 테라텀 화면에 200msec마다 '>'가 찍히는 것을 볼 수 있을 것이다.
일단 위와 같은 화면이 나오면 AVR의 UART 송신이 제대로 동작된다는 것을 알수 있다. 좀더 코드를 수정하여 확실하게 데이터 송신이 잘 되고 있다는것을 확인해 보도록 하겠다.
위와 같이 코드를 보완하고 실행시켜 보자.
화면에 대소문자 알파벳과 숫자가 한줄씩 출력되는것을 볼 수 있을것이다.
여기까지 정상적으로 수행되는것을 확인하였으면 AVR에서 UART 송신이 제대로 설정되어 데이터를 오류없이 내보내는 것을 알 수 있게 된다.
다음글에서는 UART 수신에 대해서 설명하도록 하겠다.
'입문' 카테고리의 다른 글
UART - sprintf, my_printf (0) | 2016.04.03 |
---|---|
UART - 수신 (0) | 2016.04.03 |
UART - 원리와 연결 (2) | 2016.03.29 |
_delay_ms (10) | 2016.03.27 |
LED 온도계 3 (6) | 2016.03.24 |