AVR2012.02.04 11:06

[AVR Essay 18] UART 통신 5

 

이번에는 예고 했듯이 인터럽트 방식의 UART 통신이다.

 

실험에 사용할 회로는 앞과 동일하지만 그래도 또 올려 본다.

 

다음은 실습에 사용할 프로그램이다.

 

// TX는 보낼 데이터가 있을때 알아서...
// RX는 인터럽트 발생시...
// 알파벳 진행하다가 알파벳 입력 받으면 거기서 부터 다시 시작...

// Baud Rate = 9600
// Flow Control In = None
// Flow Control Out = None
// Data Bits = 8
// Stop Bits = 1
// Parity = None

#include 
<avr/io.h>
#include 
<avr/interrupt.h>

#include "delay.h"

char rx_data, tx_data;    
// 수신, 송신 데이터를 각각 임시 저장


// 데이터 수신시 인터럽트 발생
SIGNAL(SIG_UART_RECV)
{
    cli();            
// 전체 인터럽트 중지

    rx_data = UDR;    
// 수신 받은 데이터를 임시 변수에 저장

    UCSRA &= 0x7f;    
// clear RXC flag

    sei();            
// 전체 인터럽트 허용
}


int main(void)
{
    
// 포트 초기화    
    DDRD = 0xFE;    
// RxD/PD<0> = 입력, TxD/PD<1> = 출력

    
// RS232 초기화
    UBRRL = 51;        
// 8MHz에서 9600 bps
    UCSRB = 0x18;    
// RXEN = 1, TXEN = 1
    UCSRB |= 0x80;    
// RXC interrupt 허용
    
    sei();            
// 전체 인터럽트 허용

    rx_data = 'a';    
// 초기값 설정

    while(1)
    {
        tx_data = rx_data;    
// 전송할 데이터 설정

        
// 다음 알파벳 생성, z면 a로 다시 시작
        if(rx_data != 'z')
        {
            rx_data++;
        }
        else
        {
            rx_data = 'a';
        }

        while((UCSRA & 0x20) == 0x00);    
// UDE가 비었으면 송신 가능

        UDR = tx_data;    
// 데이터를 보낸다.

        delay_ms(1000);    
// 1초 지연
    }

    return 0;
}

 

요놈을 컴파일 한 후 ATmega8535에 전송 한 후 PC에서 해당 포트를 열면

 

a 부터 z까지 약 1초 간격으로 출력됨을 확인해 볼 수 있다.

 

이때, a에서 z 중 아무 값이나 입력하면 입력한 값 부터 시작해서 알파벳에 다시 출력됨을 확인하자.

위에서 빨간색은 AVR에서 수신한 데이터이고 파란색은 PC에서 보낸 데이터이다.

 

결과와 비교해서 그리 어렵지 않으니 직접 소스코드를 분석해 보는 것이 좋다.

 

참고로 여기서는 AVR에서 데이터 수신시 SIGNAL(SIG_UART_RECV) {...} 부분이

 

인터럽트로 실행된다는 것만 유의하면 될 것이다.

 

인터럽트에 대한 기본적인 내용은 앞의 인터럽트 부분에서 언급했으니 그쪽을 참고하면 될 것이다.

(http://blog.naver.com/ds5pnz/140033279651)

 

 

간단한 통신 프로그램일 경우에는 폴링 방식이나 인터럽트 방식 중 하나만 적절히 이용하면 된다.

 

그런데 시스템이 커질 경우에는 이를 둘 다 사용할 필요가 있다.

 

즉, 데이터 수신은 일일이 인터럽트로 받아 (버퍼가 2문자로 제한이 있다.) 이를 적절한 공간에 저장 한다.

 

그 후 필요에 따라 이 공간에서 데이터를 받아 오는 방식(폴링)이다.

 

경우에 따라서는 일정 형태의 패킷을 수신할 필요가 있기 때문에 완성된 패킷일때만 수신할 수도 있다.

 

이를 라이브러리로 만들어 사용하면 편리하다.

 

다음 에세에에서는 내가 여기 저기서 주워다 조합한 라이브러리를 소개하는 것으로 UART 통신을 마치도록 하겠다.

Posted by 콩알은
AVR2012.02.03 15:38

[AVR Essay 17] UART 통신 4

 

본격적으로 UART 통신 실습을 해 보자.

 

지금 다룰 것은 폴링 방법이다. 이와 대비되는 의미는 인터럽트이고...

 

폴링... 원래 단어는 polling이다.

 

사전적 의미로는 투표라는 의미인데 사실 감이 안 온다.

 

김동근의 텀즈 (terms.co.kr)에 따르면 다음과 같은 뜻을 가지고 있다.

 

통신에서, "폴링"은 한 프로그램이나 장치에서 다른 프로그램이나 장치들이 어떤 상태에 있는지를 지속적으로 체크하는 전송제어 방식으로서, 대체로 그들이 아직도 접속되어 있는 지와 데이터 전송을 원하는지 등을 확인한다.  명확히 말하면, 여러 개의 장치가 동일 회선을 공유하는 멀티드롭이나 멀티포인트 통신에서, 제어 장치는 각 장치에 한번에 하나씩 메시지를 보내어, 전송할 데이터가 있는지(즉, 회선을 사용하기 원하는지)를 묻는다. 
 
"장치들이 어떤 상태에 있는지를 지속적으로 체크"가 아마 핵심인 것 같다.

 

설명할려면 손 아프고 보는 사람은 눈 아프니

 

일단 폴링 방식에 의한 UART 통신을 일단 해 보고 결과만 가지고 이야기 하도록 하자.

 

아래와 같이 회로를 꾸민다. 참고로 이 회로는 바로 뒤에 다룰 인터럽트 방식에도 그대로 쓰인다.

 

이 회로의 완성품은 다음과 같다. 폰카로 찍어서 화질이 안 좋으니 이해 바란다.

위 사진에서 우측에 세가닥 선은 PC와 연결되는 모습니다.

 

실험에 사용할 소스는 다음과 같다.

 

// 전송 받은 알파벳이 소문자면 대문자로, 대문자면 소문자로 변환
// 알파벳이 아닌 경우에는 "?"를 출력

// Baud Rate = 9600
// Flow Control In = None
// Flow Control Out = None
// Data Bits = 8
// Stop Bits = 1
// Parity = None

#include 
<avr/io.h>

int main(void)
{
    
// 포트 초기화
    DDRD = 0xFE;    
// RxD/PD<0> = 입력, TxD/PD<1> = 출력

    
// USART 초기화
    UBRRL = 51;        
// 8MHz에서 9600 bps
    UCSRB = 0x18;    
// RXEN = 1, TXEN = 1

    char rx_data, tx_data;    
// 수신, 송신 데이터를 각각 임시 저장

    while(1)
    {
        while((UCSRA & 0x80) == 0x00);    
// RXC = 1 이면 수신 끝
        
        rx_data = UDR;        
// 받은 데이터를 임시 변수에 저장

        
// 알파벳 소문자가 입력 되었을 경우
        if( (rx_data >= 'a') && (rx_data <= 'z') )
        {
            tx_data = rx_data - 'a' + 'A';    
// 소문자를 대문자로 변환
        }
        
        
// 알파벳 대문자가 입력 되었을 경우
        else if( (rx_data >= 'A') && (rx_data <= 'Z') )
        {
            tx_data = rx_data - 'A' + 'a';    
// 대문자를 소문자로 변환
        }

        
// 알파벳이 아닌경우 "?" 출력
        else
        {
            tx_data = '?';
        }

        while((UCSRA & 0x20) == 0x00);    
// UDE가 비었으면 송신 가능

        UDR = tx_data;    
// 데이터를 보낸다.
    }

    return 0;
}

 

소스를 대충 보면 이해되겠지만,

 

피씨 측에서 소문자를 날리면 AVR은 이에 해당하는 대문자를 리턴하고,

 

피씨 측에서 대문자를 날리면 AVR은 이에 해당하는 소문자를 리턴하며,

 

알파벳이 아닌 경우에는 ?를 리턴하는 프로그램이다.

 

(어렵지 않은 소스이니 반드시 이해하자.)

 

이 프로그램을 컴파일 후 ATmega8535에 다운로드 한 후

 

앞서 소개한 시리얼 웍스를 실행 한 후 ATmega8535와 연결된 포트를 설정에 맞추어 연 후 알파벳을 입력해 보자.

 

다음과 같은 결과를 얻을 수 있을 것이다.

여기서 파란색은 PC에서 입력한 값이고 빨간색은 AVR에서 받아온 값이다.

 

 

결과적으로 폴링 방식에 대해서 다시 살펴 보자.

 

while(1)

{

          scanf("%d", &a);

          printf("%d", a);

}

 

위 프로그램의 경우 입력 값을 받기 이전에는 프로그램은 아무런 행동도 하지 않는다.

 

즉, 입력 값을 받은 이후에야 다음 작업을 수행 할 수 있다.

 

폴링 방식은 이와 유사하다고 볼 수 있다.

 

위에서 짠 AVR 프로그램에서 rx_data = UDR; 는 바로 위의 scanf("%d", &a);와 동일하다고 보면 된다.

 

폴링 방식은 일일이 수신된 데이터가 있는지 확인하고 데이터를 수신 할때까지 기다리던지,

 

일정 시간동안 수신 상태를 유지하다가 다음 작업을 진행하는 방법 등이다.

 

이 경우 프로그래머는 언제 날아 올지 모르는 데이터에 대해서 항상 신경써야 하기 때문에 어렵다.

 

이를 보다 편리하게 극복한 방법이 인터럽트이다.

 

다음에 인터럽트 방식의 UART 통신에 대해 다루겠지만 수신 데이터가 인터럽트로 처리되기 때문에

 

프로그래머는 데이터가 언제 날아올지 신경을 쓰지 않아도 된다는 것만 알아 두자.

 

 

이번장은 여기까지...

Posted by 콩알은
AVR2012.02.03 15:23

[AVR Essay 16] UART 통신 3

 

오랜만입니다. 제가 많이 바빠서 이제야 다시 AVR Essay를 글쩍거리게 되었군요.

 

이 글을 쓰는데 있어서 예전에 비해 몇 가지 변한게 있습니다.

 

오늘은 UART 통신과 직접 관련이 없는 내용이니 바쁘시면 이거는 안 읽으셔도 됩니다.

 

(그래도 한번만 읽어 주세요...ㅠ.ㅠ)

 

 

우선 노트북이 바뀌었습니다.

 

예전에는 패러럴 포트도 있고 시리얼 포트도 있고 해서 작업하기 좋았는데,

 

새로 산 노트북에는 USB만 딸랑 있습니다. 어쩌겠습니까... 시대의 흐름이 그러한데...

 

그래서 패러럴 방식으로 사용하던 ISP는 USB 방식으로 교체하였고,

 

시리얼 통신은 USB-RS232 변환 케이블을 이용하였습니다.

 

이에 대해서는 차 후에 설명 드리겠습니다.

 

그리고 디지털 카메라가 없습니다.

 

디지털 카메라로 결과 사진 찍어 올리곤 했는데 사정상 디카를 반납하게 되었습니다.

 

그래서 고민하다가 당장 디카 살 돈은 없고 해서 제가 가지고 있는

 

100만 화소짜리 핸드폰으로 찍기로 했습니다. 궁한데 어쩌겠습니까...ㅋㅋ

 

 

앞에서 사용하던 회로도 좀 바뀌었습니다. 우선 ATmega8535 회로는 다음과 같이 생겼습니다.

 

 

심플하게 만들었습니다. 아마 주변 회로가 완성된 모듈 제품을 사용하신다면 이게 보기 편할 것 입니다.

 

제가 가진게 8MHz짜리라서 앞으로도 쭉~~ 요놈 가지고 쓸 계획 입니다. 오실레이터 회로 생략 입니다.

 

고민하다가 과감하게 전원도 생략 했습니다.

 

요놈이 전기 먹고 산다는 것은 AVR Essay를 읽으시는 분이면 다 아실 것이기 때문에 일일이 전원을 그릴 필요가 없을 것 같네요.

 

이번에 전원부도 5V와 3.3V 동시에 출력하도록 새로 만들고 MAX232 모듈도 새로 만들었습니다.

 

전원부야 거의 대부분 회로도에서 생략 할 것이기 때문에 따로 심볼을 만들지 않겠고 MAX232는 다음과 같습니다.

앞에 선이 긴 이유는 AVR과 직접 연결 될 것이기 때문이고 뒤에 선이 짧은 것은 PC와 연결 될 것이기 때문 입니다.

 

(즉, 별 의미가 없고 제 마음대로 정한 것 입니다.)

 

원래 MAX232 칩이 두개의 UART 신호를 처리 할 수 있기 때문에 그냥 두개 만들었습니다.

 

아마 보통 R1, T1만 사용할 것 입니다. 참고로 ATmega128은 2개의 UART 장치가 있어서 둘다 쓸 수도 있습니다.

 

참고 삼아서 요놈 실물을 보여드리겠습니다.

역시나 핸드폰으로 찍어서 화질은 별로 입니다. 그래도 부품은 대충 보이네요.

 

끝에 PC 연결 커넥터는 제가 가지고 있는 AVR Mall의 ATmega128 모듈과 호환되게 만들었습니다.

 

 

마지막으로 PC 측 통신 프로그램이 바뀌었습니다.

 

이거 전에 통신 프로그램으로 하이퍼터미널을 사용했는데, 이유는 모르겠지만 노트북이 바뀐 이후로

 

PC에서 AVR로 데이터 전송이 잘 안되었습니다. 아마 USB-RS232 장치와 호환이 안 되서 그런것 같습니다.

 

그래서 제가 즐겨 쓰는 다른 통신 프로그램을 소개 할까 합니다.

 

시리얼 웍스라는 프로그램인데 프로그램도 작고 기능도 쏠쏠하게 쓸만 한 것 같더군요.

 

(본 프로그램은 이 문서에 첨부 되어 있습니다.)

생긴거는 이렇게 생겼는데 기능도 하이퍼 터미널을 비롯해 다른 통신 프로그램과 유사합니다.

 

한가지 좋은점이 있다면 헥사 코드 (16진수)를 바로 보고 전송할 수 있다는 것 입니다.

 

나중에 패킷을 짜서 통신을 할 때 디버깅시 아주 편리한 기능을 합니다.

 

뭐, 글 읽을 줄 알고 마우스질 할 수 있으시면 직접 프로그램 실행해서 어떤 기능이있나 살펴 보세요.

 

 

이상 이번 장을 마치겠습니다.

 

오랜만에 썼는데 별 영양가는 없는 이야기들 뿐이네요.

 

다음부터 본격적으로 UART 통신에 대해서 다시 다루겠습니다.

Posted by 콩알은