본문 바로가기

AVR/AVR 연습, Tutorial

AVR UART 비동기 통신 사용자 함수 문자 비교 LED ON/OFF 제어하기 - AVR 연습



USART레지스터를 정리했으니, 다음은 역시 간단하게 LED를 사용해서 UART통신을 통한 제어를 해보겠습니다. UART는 이 통신방식으로 지원되는 모듈들이 많아서 상당히 범용적으로 사용되는 통신이여서 꼼꼼하게 가겠습니다.

그나저나 고3이여서 포스팅이 느립니다. 그나마 틈틈이 하고 있어여 :-)



사용된 회로도를 볼까요!




모듈측은 원래 사용하던 LED에 추가로 PC와 AVR모듈사이에 USB to UART 장치 혹은 UART 직렬포트가 있는 컴퓨터의 경우 MAX232라는 IC를 통해 AVR과 연결해서 통신할수 있습니다.

저는 이전에 아두이노에 사용하려고 만들어 뒀던 CP2012를 사용한 USB to UART 장치를 통해서 AVR 모듈과 연결해서 테스트 해보았습니다. ~~ 그럼 소스보기로 ...~


 갑자기 노트북 쓰려니까 적응안되서 혼났습니다. 키적응도 안되고... ㅎ



CodeVision AVR용 소스코드 


#include <tiny2313.h>    // Tiny2313 입출력 관련 헤더파일을 포함합니다.

#include <delay.h>    // 지연함수 관련 헤더파일을 포함합니다.


char rx_char(void)    // 문자형 rx_char 수신 사용자 함수를 생성합니다.

{

while((UCSRA&0x80) == 0);    // 문자 수신이 완료될 때까지 대기 UCSRA의 RXC가 비트1 이 되면 다음라인으로

return UDR;    // UDR 수신데이터 반환

}


void tx_char(char tx_data)    // 문자형 tx_char 송신 사용자 함수를 생성합니다.

{

while((UCSRA&0x20) == 0);    // UDR레지스터가 빌 때까지 대기 UCSRA의 UDRE가 비트1 이 되면 다음라인으로

UDR = tx_data;    // UDR레지스터에 입력한 tx_data 입력합니다.

}


void main(void)    // 메인함수를 호출합니다.

{

char  i, data;    // 문자형 변수 i, data를 생성합니다.


DDRB=0xFF;    // B포트 8비트 전체를 출력으로 설정합니다.

PORTB=0x00;    // B포트 8비트 전체의 초기값을 논리0 (0V)로 설정합니다.


UCSRA=0x00;    // UART설정 레지스터A 별도 설정 없음

UCSRB=0x18;    // UART설정 레지스터B RXEN과 TXEN을 비트1로 설정해서 송수신기능을 활성화 합니다.

UCSRC=0x06;    // UART설정 레지스터C UCSZ1과 UCSZ0을 비트1로 설정해서 8비트 데이터 전송으로 설정합니다.

UBRRH=0x00;    // UBBR 통신속도 설정레지스터 상위 바이트로 8비트를 초과하지 않아 UBRRL에 모두 입력됩니다.

UBRRL=0xCF;    // UBRR 통신속도 설정레지스터 하위 바이트로 8Mhz크리스탈 2400bps속도로 207로 설정합니다.


while(1)    // 아래구문을 무한 반복합니다.

{

data = rx_char();    // data 변수에 rx_char 사용자 함수사용으로 수신된 데이터를 저장합니다.

if(data=='y')    // data변수와 문자y가 같으면

{

PORTB=0xFF;    // B포트 전체 논리1 (5V)를 출력합니다.

tx_char('_');    // tx_char 사용자 함수 사용으로 _문자를 송신합니다.

tx_char('o');    // tx_char 사용자 함수 사용으로 o문자를 송신합니다.

tx_char('k');    // tx_char 사용자 함수 사용으로 k문자를 송신합니다.

}

if(data=='n')    // data변수와 문자n과 같으면

{

PORTB=0x00;    // B포트 전체 논리0 (0V)를 출력합니다.

tx_char('_');    // tx_char 사용자 함수 사용으로 _문자를 송신합니다.

tx_char('o');    // tx_char 사용자 함수 사용으로 o문자를 송신합니다.

tx_char('k');    // tx_char 사용자 함수 사용으로 k문자를 송신합니다.

}

if(data=='b')    // data변수와 문자b가 같으면

{

for(i=0;i<3;i++)    // 아래구문을 3번 반복합니다.

{

PORTB=0xFF;    // B포트 전체 논리1 (5V)를 출력합니다.

delay_ms(200);    // 위 상태를 0.2초 유지합니다.

PORTB=0x00;    // B포트 전체 논리0 (0V)를 출력합니다.

delay_ms(200);    // 위 상태를 0.2초 유지합니다.

}

tx_char('_');    // tx_char 사용자 함수 사용으로 _문자를 송신합니다.

tx_char('o');    // tx_char 사용자 함수 사용으로 o문자를 송신합니다.

tx_char('k');    // tx_char 사용자 함수 사용으로 k문자를 송신합니다.

}

}

}



AVR Studio용 소스코드


#include <avr/io.h>    // AVR 입출력 관련 헤더파일을 포함합니다.

#define F_CPU 8000000UL    // 사용하고 있는 크리스탈 주파수 값을 상수로 설정합니다.

#include <util/delay.h>    // 지연 함수 관련 헤더파일을 포함합니다.


char rx_char(void)    // 문자형 rx_char 수신 사용자 함수를 생성합니다.

{

while((UCSRA&0x80) == 0);    // 문자 수신이 완료될 때까지 대기 UCSRA의 RXC가 비트1 이 되면 다음라인으로

return UDR;    // UDR 수신데이터 반환

}


void tx_char(char tx_data)    // 문자형 tx_char 송신 사용자 함수를 생성합니다.

{

while((UCSRA&0x20) == 0);    // UDR레지스터가 빌 때까지 대기 UCSRA의 UDRE가 비트1 이 되면 다음라인으로

UDR = tx_data;    // UDR레지스터에 입력한 tx_data 입력합니다.

}


int main(void)    // 메인함수를 호출합니다.

{

char  i, data;    // 부호없는 문자형 변수 i, data를 생성합니다.


DDRB=0xFF;    // B포트 8비트 전체를 출력으로 설정합니다.

PORTB=0x00;    // B포트 8비트 전체의 초기값을 논리0 (0V)로 설정합니다.


UCSRA=0x00;    // UART설정 레지스터A 별도 설정 없음

UCSRB=0x18;    // UART설정 레지스터B RXEN과 TXEN을 비트1로 설정해서 송수신기능을 활성화 합니다.

UCSRC=0x06;    // UART설정 레지스터C UCSZ1과 UCSZ0을 비트1로 설정해서 8비트 데이터 전송으로 설정합니다.

UBRRH=0x00;    // UBBR 통신속도 설정레지스터 상위 바이트로 8비트를 초과하지 않아 UBRRL에 모두 입력됩니다.

UBRRL=0xCF;    // UBRR 통신속도 설정레지스터 하위 바이트로 8Mhz크리스탈 2400bps속도로 207로 설정합니다.


while(1)    // 아래 구문을 무한 반복합니다.

{

data = rx_char();    // data 변수에 rx_char 사용자 함수사용으로 수신된 데이터를 저장합니다.

if(data=='y')    // data변수와 문자y가 같으면

{

PORTB=0xFF;    // B포트 전체 논리1 (5V)를 출력합니다.

tx_char('_');    // tx_char 사용자 함수 사용으로 _문자를 송신합니다.

tx_char('o');    // tx_char 사용자 함수 사용으로 o문자를 송신합니다.

tx_char('k');    // tx_char 사용자 함수 사용으로 k문자를 송신합니다.

}

if(data=='n')    // data변수와 문자n과 같으면

{

PORTB=0x00;    // B포트 전체 논리0 (0V)를 출력합니다.

tx_char('_');    // tx_char 사용자 함수 사용으로 _문자를 송신합니다.

tx_char('o');    // tx_char 사용자 함수 사용으로 o문자를 송신합니다.

tx_char('k');    // tx_char 사용자 함수 사용으로 k문자를 송신합니다.

}

if(data=='b')    // data변수와 문자b가 같으면

{

for(i=0;i<3;i++)    // 아래구문을 3번 반복합니다.

{

PORTB=0xFF;    // B포트 전체 논리1 (5V)를 출력합니다.

_delay_ms(200);    // 위 상태를 0.2초 동안 유지합니다.

PORTB=0x00;    // B포트 전체 논리0 (0V)를 출력합니다.

_delay_ms(200);    // 위 상태를 0.2초 동안 유지합니다.

}

tx_char('_');    // tx_char 사용자 함수 사용으로 _문자를 송신합니다.

tx_char('o');    // tx_char 사용자 함수 사용으로 o문자를 송신합니다.

tx_char('k');    // tx_char 사용자 함수 사용으로 k문자를 송신합니다.

}

}


return 0;    // 정상종료 값 0을 리턴합니다.

}



소스코드 동작 구성


생각보다 동작에 대한 구성은 어려움이 없습니다. 먼저 문자 수신 함수인 rx_char()은 UCSRA레지스터 즉 UART의 제어를 담당하는 레지스터 A중 RXC비트는 UCSRA 7번 비트인데요. 이 비트는 UART전송시 받은 데이터를 저장하는 UDR레지스터에 데이터가 수신이 완료되면 RXC비트가 1로 변하는데요. 다시 소스코드로 돌아와 while구문은 조건문이 거짓이면 while문을 빠져나오게 되는데, while((UCSRA&0x80) == 0)은 RXC비트가 1이 되면 0과 같지 않아 거짓이 되므로 다음 구문으로 넘어가고 다음구문은 return UDR;로 함수 사용시 수신된 데이터를 반환합니다.


송신 함수 tx_char도 마찬가지고 UCSRA레지스터의 UDRE비트는 UDR레지스터가 비었을 때 1이 되는데, 이 UDR레지스터에 쓰기를 하면 전송용 레지스터로 변경됩니다. 따라서 while((UCSRA&0x20) == 0)을 통해 UDRE비트가 1이 되면, 조건문이 거짓이게 되므로, while문을 빠져 나오고 UDR레지스터에 입력데이터 tx_data를 쓰기해서 UART로 전송하고 마지막으로 return 0; 값으로 정상 종료 합니다.



하이퍼 터미널 설정


먼저 컴퓨터에 별도의 시리얼 통신용 터미널 프로그램이 없다면 가볍게 무설치 하이퍼터미널을 다운로드 합니다.


 하이퍼터미널 다운로드 - 구글 드라이브로 연결됩니다.


실행시 위치정보 등록 창이 뜨면서 전화번호를 등록하라는 질의 창이 나오지만, 취소를 누르는데, 역시 정말 취소하시겠냐는 물음이 나옵니다. 여기서도 (예)를 눌러줍니다.

이 후 적당한 이름을 입력해서 새 연결을 생성합니다. 연결을 생성하고 나면 역시 위치정보 등록 창이 뜨는데, 불필요 하므로 역시 취소를 눌러줍니다.




연결에 사용할 통신 포트를 선택합니다. USB to UART 장치를 이용해서 만든 포트는 임의로 지정되기 때문에 연결한 직렬포트가 맞는지 확인 후 연결합니다.

(메인보드에 자체 지원하는 직렬포트는 Max232 IC로 TTL레벨로 변환 후 사용하고, COM1 또는 COM2 중 하나 입니다.)




AVR과 통신하고자 하는 속도를 선택합니다. AVR에서 레지스터 설정시에 2400Bps로 설정했기 때문에 비트/초는 2400으로 설정하고, 데이터 전송 비트는 8비트로 설정했기 때문에 데이터 비트는 8비트 패리티는 없음 정지비트는 1로 설정하고 흐름제어는 없음으로 설정합니다.




하이퍼터미널에서는 입력되는 문자가 표시가 안되기 때문에 설정이 필요한데요. 파일 > 속성 > 상단 설정 > ASCII설정 에서 ASCII 보내기 쪽은 필요에 따라 줄 끝에 LF(Line Feed)를 붙여 보냄 체크, 입력된 문자를 터미널 창에 표시 체크, ASCII 받기에서 받는 줄 끝에 LF(Line Feed) 붙임을 체크 합니다.




이후에 문자를 입력해서 전송이 되는지 동작이 되는지 테스트를 해봅니다.^





동작영상




소문자 y를 누르면 B포트 LED 전체가 들어오고, 소문자 n을 누르면 B포트 LED 전체가 꺼지고 소문자 b를 누르면 B포트 LED 전체가 3번 깜박이는 것을 확인 해 볼수 있습니다.

생각보다 장치가 많이 필요해서 애먹었지만, 문자비교 LED제어 포스팅 끝... 입니다. :-)