ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ATmega8535 - 시리얼통신 (UART)
    Programming/Embeded 2009. 7. 9. 23:43

    Code Vison AVR C

    ATmega 8535

     RS232 시리얼 통신

     컨넥터와 신호선

    RS232 통신을 위한 컨넥터는 9핀과 25핀 컨넥터가 있으나, 최근에는 9핀 컨넥터를 많이 사용한다. 실제 데이터가 송 수신 되는 핀은 TXD(3) 와 RXD(2) 이고 기능은 다음과 같다.

    9핀 컨넥터의 모습

     

    TXD - Transmit Data

    비동기식 직렬 통신 장치가 외부 장치로 데이터를 보낼 때, 직렬 통신 데이터가 나오는 신호선

    RXD - Receive Data

    외부 장치에서 들어오는 직렬 통신 데이터를 입력받는 신호선

    케이블을 만들 때에는 반대쪽 커넥터에 연결하기 전에 한번 교차 시켜야 한다. (Rx ->Tx , Tx->Rx)

    ATmega8535에서의 RXD, TXD

    MAX232

     

    MAXIM사에서 생산되는 RS-232통신을 가능토록 해주는 송수신 IC이다. 송수신 드라이브를 각각 2개씩 가지고 있다.

    AVR과 컴퓨터가 인식하는 0과 1의 값이 다르기 때문에..

     

    마이컴

    컴퓨터

    0

    0V

    -10V

    1

    5V

    10V

    이 차이를 해결해주는 것이다.

     

    TTL IC의 전원단자와 다르게 15번 핀이 GND, 16번이 VCC이므로 주의하자

     

     

    IC 내부에는 VOLTAGE DOUBLER와 VOLTAGE INVERTER가 있다.

    DOUBLER는 5V를 10V로 증폭 INVERTER는 증폭된 신호를 반전

    내부에 5V를 충전했다 10V로 보내기 위한 콘덴서가 있다.

     

    MAX232는 전압을 바꾸어 주는 역할만을 하며 통신을 하는것은 아님에 주의!

     

     

     

    프레임 형식

     

    직렬 데이터 프레임은 동기비트 (스타트, 스톱 비트) 와 에러 검사를 위한 패리티 비트(선택가능)와 데이터 비트를 포함하는 1문자를 의미한다.

     

    컴퓨터 쪽에서는 다음과 같이 설정한다.

     

     

    보레이트 9600 데이터 비트는 8비트 패리티 비트 사용 안 함 STOP비트는 1로 설정한 모습

     

    시리얼 통신을 위한 레지스터

     

    ATmega8535에는 시리얼 통신용 컨트롤러가 포함 되어 있다.

    CPU 내부에서 CPU의 코어 부분과 시리얼 통신용 컨트롤러가 데이터를 주고 받고, 컨트롤러는 RxD, TxD의 핀을 통해 외부와 통신을 하고 있다.

    시리얼 통신을 위한 레지스터에는 설정용 레지스터와 데이터 통신용 레지스터가 있고 설정용 레지스터를 이용해 설정을 하고 통신용 레지스터를 이용해 실제 통신을 한다

     

     

    UDR

    7

    6

    5

    4

    3

    2

    1

    0

    RXB (Read)

    TXB (Write)

     

    UDR레지스터는 데이터를 입력하면 설정한 값에 맞게 데이터를 전송하는 레지스터이다.

    UDR레지스터를 읽으면 수신 데이터 버퍼 레지스터(RXD)의 내용을 볼수 있다. 즉, 송신 데이터를 UDR레지스터에 쓰기하면 송신데이터 버퍼 (TXB)에 저장하고, 수신 데이터를 UDR 레지스터에 쓰기하면 수신 데이터 버퍼(RXB)에 수신되어 있는 값이 읽혀진다.

     

     

     

    UCSR 레지스터

    UCSR은 A,B,C세 개로 구성 되어 있고, 상태 설정과 제어의 기능을 한다.

     

    UCSRA

    7

    6

    5

    4

    3

    2

    1

    0

    RXC

    TXC

    UDRE

    FE

    DOR

    PE

    U2X

    MPCM

    7. RXC : 수신 완료 표시 비트

    6. TXC : 송신 완료 표시 비트

    5. UDRE : 송신 데이터 레지스터 준비 완료 표시 비트

    4. FE : 프레임 에러 표시 비트

    3. DOR : 데이터 오버런 에러 표시 비트

    2. PE : 패리티 에러 표시 비트

    1. USX : 송신 속도 2배 설정

    0. MPCM : 멀티 프로세서 통신 모드

        *1번과 0번을 설정하고 나머지는 읽기 전용이다. (사용 할 때 1 아닐 때 0)

     

    UCSRB

    7

    6

    5

    4

    3

    2

    1

    0

    RXCIE

    TXCIE

    UDRIE

    RXEN

    TXEN

    UCSZ2

    RXB8

    TXB8

    7. RXCIE 수신 완료 인터럽트 인에이블 비트

    6. TXCIE 송신 완료 인터럽트 인에이블 비트

    5. UDRIE 송신 데이터 레지스터 준비 완료 인터럽트 인에이블 비트

    4. RXEN 수신기 인에이블

    3. TXEN 송신기 인에이블

    2. UCSZ2 전송 데이터 길이 선택 비트

    1. RXB8 수신 데이터 비트 8

    0. TXB8 송신 데이터 비트 8

     

    UCSRC

    7

    6

    5

    4

    3

    2

    1

    0

    URSEL

    UMSEL

    UPM1

    UPM0

    USBS

    UCSZ1

    UCSZ0

    UCPOL

    7. UREL 레지스터 선택 비트

    6. UMSEL 시리얼 통신 모드 설정 비트

    5. UPM1 패리티 모드 설정 비트

    4. UPM0 패리티 모드 설정 비트

    3. USBS 정지 비트 선택

    2. UCSZ1 전송 데이터 비트 수 설정

    1. UCSZ0 전송 데이터 비트 수 설정

    0. UCPOL 클럭 극성 선택

     

    보레이트 속도 설정 관련 레지스터

     

    보레이트 - 신호 하나의 속도

    보레이트 속도를 조절 하는 레지스터는 UBRRH와 UBRRL 2개로 이루어져 있다. UBRRH의 4비트와 UBRRL의 8비트를 합친 12비트를 이용하여 속도를 설정한다.

     

    UBBRH

    7

    6

    5

    4

    3

    2

    1

    0

    URSEL

    사용하지 않음 ( 0 )

    UBRR의 값 (11 ~8 비트)

     

    UBBRL

    7

    6

    5

    4

    3

    2

    1

    0

    UBRR의 값 (7 ~0 비트)

     

    UBRRH는 UCSRC레지스터와 같은 번지를 사용 하고 있다. 그렇기 때문에 UCSRC로 사용 할 것인지 UBRRH로 사용 할 것인지 선택을 해야 하는데, 이 기능을 하는 것이 7번 URSEL비트이다.

    URSEL이 0일 때 UBRRH의 기능을 갖고 1일 때 UCSRC의 기능을 갖는다.

     

    UBRR의 값은 보레이트와 시스템 클럭을 이용하여 계산 한다.

    예를 들어 시스템 클럭이 16Mhz 이고 보레이트를 9600 bps로 잡았을 때

     

    UBRR의 값은 103.1666.... 이 된다.

    여기서 소수점 이하를 버리고 103을 2진수로 변환하면 1100111이 된다.

    결국 UBRRH의 4 비트에는 모두 0이 들어가고 UBRRL에는 01100111이 들어가므로, 다음과 같이 입력 한다.

        UBRRH=0;

        UBRRH=103;    //물론 0b01100111으로도 입력 가능하다.

     

    데이터 전송 레지스터

     

    직렬 통신에 사용하는 입출력 함수

     

    void puts(char *str)

     

    외부로 SRAM의 문자열을 출력 하는 기능을 가진다. 문자열의 끝 부분에는 null(0x0A)를 추가하여 출력한다. null 문자는 터미널 화면에서 줄바꾸기를 한다.

    하지만 줄의 맨 앞이 아닌 최종 출력지점의 바로 다음 줄로 출력 된다.

     

    Ex)    Hello NClab!

             Hello NClab!

     

    터미널의 제일 첫줄로 줄바꿈을 하기 위해서는 제어 문자인 "\r"=>"0x0D+0x0A"를 끝 부분에 첨가하거나 다음 문장에 "0x0D"를 출력 하여 커서를 맨앞으로 이동 시킨다.

     

    void putsf(char flash *str)

     

    외부로 Flash의 문자열을 출력 하는 기능을 가진다.

    줄바꿈 형식은 puts와 동일

     

    void printf(char flash *fmtstr [,arg1,arg2,....])

    fmtstr 문자열에 있는 문자열을 출력 하는 기능을 가진다. 특히, fmtstr은 상수이며 Flash 메모리에 위치해 있어야 한다.

    Ex) int_val = 112;

        printf("Interger value =%5i", int_val);

        // %5i 는 5칸에 정수를 출력 하라는 뜻

     

     

    직렬 통신 프로그램

     

    출력 함수들을 사용해보자

     

    #include <mega8535.h>

    #include <stdio.h>

     

    void rs232_putchar(void)        //한글자씩 출력하는 putchar() 사용한 함수

    {

    putchar('I');

    putchar(' ');

    putchar('L');

    putchar('O');

    putchar('V');

    putchar('E');

    putchar(' ');

    putchar('N');

    putchar('C');

    putchar(0x0A);        //줄바꿈

    putchar(0x0D);        //커서 제일 앞으로

    }

     

     

    void main(void)

    {

    char data[] = "I LOVE NC 2";    //SRAM 문자열을 출력 하기 위한 문자열 배열

     

    // USART initialization

    // Communication Parameters: 8 Data, 1 Stop, No Parity

    // USART Receiver: On

    // USART Transmitter: On

    // USART Mode: Asynchronous

    // USART Baud Rate: 9600

    UCSRA=0x00;

    UCSRB=0x18;

    UCSRC=0x86;

    UBRRH=0x00;

    UBRRL=0x33;

     

        rs232_putchar();    //한글자씩 출력 하는 함수 호출

        

        puts(data);    //SRAM 문자열 출력

        putchar(0x0D);    //줄바꿈

     

        putsf("I LOVE NC 3 \r");    //Flash 문자열 출력 (줄바꿈 문자 \r)포함

    }

     

    결과

    I LOVE NC

    I LOVE NC 2

    I LOVE NC 3

     

     

    입력은 어떻게 받는지 알아보자

     

    #include <mega8535.h>

    #include <stdio.h>

     

    unsigned char rx_data;        //수신된 문자를 받기 위한 전역 변수

     

    void led_control(void)

    {

    rx_data = getchar();    //getchar() 수신 데이터를 받는 함수 이다(UDR).

    putchar(rx_data);        //받은 문자를 출력 함으로써 에코 효과

    switch (rx_data) {    //받은 문자에 따라 행동

    case 0x30: PORTA = 0x00;        //0X30 '0' 해당하는 ASCII코드임

    break;                //'0'일때 PORTA 0 출력

    case 0x31: PORTA = 0x01;        //0X31 '1' 해당하는 ASCII코드임

    break;

    case 0x32: PORTA = 0x02;        //0X32 '2' 해당하는 ASCII코드임

    break;

    case '3': PORTA = 0x03;    //직접 '3'이라는 문자를 적어 있음

    break;

    case '4' :PORTA = 0x04;

    break;

    case '5': PORTA = 0x05;

    break;

    case '6': PORTA = 0b00110011;    //물론 출력은 2진수로도 쓸수 있다.

    break;

    default: PORTA = 0x00;

    };

    }

     

    void main(void)

    {

    PORTA=0x00;

    DDRA=0xFF;        //PORTA 모두 출력 모드

     

    // USART initialization

    // Communication Parameters: 8 Data, 1 Stop, No Parity

    // USART Receiver: On

    // USART Transmitter: On

    // USART Mode: Asynchronous

    // USART Baud Rate: 9600

    UCSRA=0x00;

    UCSRB=0x18;

    UCSRC=0x86;

    UBRRH=0x00;

    UBRRL=0x33;

     

    while (1)        //무한루프로 입력을 감지 한다.

    {

    led_control();    //함수 호출

    };

    }

     

    결과

    0~6까지의 입력에 따라 LED가 반응한다.

    응용 프로그램 : 입력을 받아 LCD에 표시 해보자

    #include <mega8535.h>

    #asm

    .equ __lcd_port=0x15

    #endasm

    #include <lcd.h>

    #include <stdio.h>

     

    unsigned char getdata;        //입력된 ASCII코드를 담을 변수

     

    void char_input (void)        //입력 받은 문자에 따라 행돌할 함수

    {

        getdata = getchar();    //입력된 문자를 받고

    switch (getdata){

    case 0x0D:        //Enter

        lcd_gotoxy(0,1);    //2 1열로 커서 옮김 (줄바꿈)

        break;

    case 0x1B:        //Esc

        _lcd_ready();    //LCD 데이터 수신 준비

        _lcd_write_data(0b00000001);    //클리어 명령

        break;

    case 0x09:                //TAB

        _lcd_ready();

        _lcd_write_data(0b00011000);    //전체 화면 왼쪽으로 쉬프트

        break;

        case 0x08: _lcd_ready();            //BackSpace

            _lcd_write_data(0b00010000);    //커서를 왼쪽으로 한칸 옮김

            lcd_putchar(0x20);        //공백문자 입력

            _lcd_ready();

            _lcd_write_data(0b00010000);    //커서를 왼쪽으로 한칸 옮김

            break;

    default:

        lcd_putchar(getdata);    //받은 문자를 LCD 출력

        putchar(getdata);        //컴퓨터 화면에 출력 (에코)

        PORTA = getdata;    //LED 출력 (ASCII code 볼수 있다.)

    };

     

    }        

     

    void main(void)

    {

    PORTA=0x00;

    DDRA=0xFF;     //LED ASCII code출력을 위해 모두 출력모드로

     

    // USART initialization

    // Communication Parameters: 8 Data, 1 Stop, No Parity

    // USART Receiver: On

    // USART Transmitter: On

    // USART Mode: Asynchronous

    // USART Baud rate: 9600

    UCSRA=0x00;

    UCSRB=0x18;

    UCSRC=0x86;

    UBRRH=0x00;

    UBRRL=0x33;

     

    lcd_init(16);

    _lcd_ready();

    _lcd_write_data(0b00001111);    //표시 ON/OFF제어 표시,커서,점멸 모두 ON

    printf("Enter : ");        //입력하라는 안내문 표시

    while (1)                //무한루프로 입력을 감지

    {

        char_input();    //함수 호출     

    };

    }

     

    /*********************************************

    This program was produced by Talsu

    RS232시리얼 통신을 이용하여 키보드의 입력을 받아

    LCD화면에 표시 해주는 프로그램 입니다.

    키 입력이 자유 롭게 되고.

    Enter키 = 줄바꿈

    Backspace = 한글자 지우기

    space = 띄우기

    TAB = 화면 쉬프트

    *********************************************/



    from :
    http://talsu.net/

    'Programming > Embeded' 카테고리의 다른 글

    DK-128  (0) 2012.12.26
    8255A - Programmable Peripheral Interface  (0) 2009.07.12
    ATmega8535 Datasheet  (0) 2009.07.10
    ATmega8535 - 타이머,카운터 제어 시계 설계  (0) 2009.07.09
    ATmega8535 - FND & LCD 제어  (0) 2009.07.09
Designed by Tistory.