본문 바로가기
코스웨어/13년 스마트컨트롤러

6월4일 USART 수업 정리 - 김경순

by 알 수 없는 사용자 2013. 6. 4.
728x90
반응형

오늘 수업은 지금까지 이론으로 수업한 USART를 사용하는 소스를 작성했다.

가장 먼저 USART에 관련된 레지스터들을 헤더파일에 define 한다.

수업시간에 USART0번을 쓰기로 약속했으므로 USART0 을 기준으로 레지스터들을 define 해준다.


레지스터들을 define 할때는 스펙 416p 부터 시작하는 Register Summary을 보고 define 해주도록한다.

usart.h

#ifndef _USART_H_
#define _USART_H_



#define MCK      16000000
#define BAUD     115200
#define UBRR     ((MCK/(BAUD*16L))-1)

#define UBRRH    (UBRR >> 8)
#define UBRRL    (UBRR & 0XFF)

#define UDR0     (*((volatile unsigned char * )0xC6)) //USART I/O Data Register (입출력 데이터 레지스터)
#define UCSR0A   (*((volatile unsigned char * )0xC0)) //USART Control and Strtus Register A (제어및 상태 레지스터) 
#define UCSR0B   (*((volatile unsigned char * )0xC1)) //USART Control and Strtus Register B (제어및 상태 레지스터)
#define UCSR0C   (*((volatile unsigned char * )0xC3)) //USART Control and Strtus Register C (제어및 상태 레지스터)
#define UBRR0L   (*((volatile unsigned char * )0xC4)) //USART BAUD RATE Register Low (보레이트 레지스터)
#define UBRR0H   (*((volatile unsigned char * )0xC5)) //USART BAUD RATE Register High (보레이트 레지스터)

//-------------UCSR0A
#define MPCM0 0
#define U2X0  1
#define UPE0  2
#define DOR0  3
#define FE0   4
#define UDRE0 5
#define TXC0  6
#define RXC0  7

//-------------UCSR0B
#define TXB80  0
#define RXB80  1
#define UCSZ02 2
#define TXEN0  3
#define RXEN0  4
#define UDRIE0 5
#define TXCIE0 6
#define RXCIE0 7

//-------------UCSR0C
#define UCPOL0  0
#define UCSZ00  1
#define UCSZ01  2
#define USBS0   3
#define UPM00   4
#define UPM01   5
#define UMSEL00 6
#define UMSEL01 7

//LED용 레지스터 
#define PORTA (*((volatile unsigned char * )0x22))
#define DDRA (*((volatile unsigned char * )0x21))
#define PINA (*((volatile unsigned char * )0x20))


void Usart_Init(void);
void Led_Init(void);
void RxData(void);


void __vector_25(void)__attribute__ ((signal , used , externally_visible));


//C소스안에 어셈블리를 강제 삽입 할경우 사용 (inline Asm) , ggc만 사용 가능 
#define sei() __asm__ __volatile__ ("sei" ::) //아트메가에만 공존 SREG에 I자리에 1을 넣는다.
#define sleep() __asm__ __volatile__ ( "sleep" "\n\t" :: )

#endif


교재를 참고하면 필요한 레지스터들을  알수가 있는데 각각 

UDR0 , UCSR0A , UCSR0B , UCSR0C , UBRR0L , UBRR0H 이렇게 총 6개의 레지스터가 필요하다.

각 레지스터들의 기능을 정리하면 


UDR0 (USART0 I/O Data Register) - USART 포트의 송수신 데이터 버퍼의 기능을 수행한다.


UCSR0A (USART0 Control and Status Register A) - USART 포트의 송수신 동작을 제어하거나 

송수신 상태를 저장하는 기능을 수행 한다.

.


UCSR0B  (USART0 Control and Status Register B) - USART 포트의 송수신 동작을 제어하거나 

전송 데이터를 9비트로 설정한 경우에 전송 데이터의 9번째 비트값을 저장하는 기능을 수행한다.

.


UCSR0C  (USART0 Control and Status Register C) - USART 포트의 송수신 동작을 제어하는 기능을 수행한다



UBRR0L(USART0 Baud Rate Register L) , UBRR0H (USART0 Baud Rate Register H)  - 16비트중에서 12비트만 유효 한것으로 

USART 포트의 송수신 속도를 설정하는 기능을 수행한다.

즉 이 레지스터의 값은 분주비로 작용하여 전송속도인 보레이트를 결정한다. 16비트 레지스터를 라이트 하는 경우에는 항상 상위 바이트인 

UBRR0H를 먼저 라이트 해야 하고 하위 바이트인 UBRR0L을 나중에 라이트 해야 한다.


각 비트의 내용은 교재를 참조하면 자세히 설명되어 있으며 아래에 수업중 사용한 비트들을 설명은 따로 보충.


그리고 헤더파일 마지막쯤

//C소스안에 어셈블리를 강제 삽입 할경우 사용 (inline Asm) , ggc만 사용 가능 
#define sei()   __asm__ __volatile__ ("sei" ::)      //Atmega에만 공존  SREG에 I자리에 1을 넣는다.
#define sleep()  __asm__ __volatile__ ( "sleep" "\n\t" :: )


오늘 새롭게 배운것으로 C소스안에 어셈블리를 강제로 삽입할경우 사용되는데 inline assembly 라고 한다.

실행속도 향상을 위하여 사용되며 이 명령어 되한 내용은 스펙 Instruction Set Summary 챕터안에 설명되어 있다.


usart.c

#include "usart.h"

void Usart_Init()
{

    Led_Init();

    UBRR0H = 0;    //UBRRH;
    UBRR0L = 8;    //UBRRL;

    UCSR0A = (0<<MPCM0) | (0<<U2X0) | (0<<UPE0) | (0<<DOR0) | (0<<FE0) 
    | (0<<UDR0) | (0<<TXC0) | (0<<RXC0);

    //수신완료 인터럽트 허용(교재 137p를 참조하여 벡터 함수를 만듬) , 송수신부 작동 허용 
    //8비트를 전송하기 위해 UCSZ02 0으로 셋팅 
    UCSR0B = (0<<TXB80) | (0<<RXB80) | (0<<UCSZ02) | (1<<TXEN0) | (1<<RXEN0) 
    | (0<<UDRIE0) | (0<<TXCIE0) | (1<<RXCIE0);

    //8비트 전송을 위해 UCSZ00 , UCSZ01 1로 맞춤 ,짝수 페리트를 사용하기 위해 UPM01 1 , UPM00 0으로 셋팅
    //비동기 모드 사용을 위해 UMSEL00 0 , UMSEL 01 0으로 셋팅 
    UCSR0C = (0<<UCPOL0) | (1<<UCSZ00) | (1<<UCSZ01) | (0<<USBS0) | (0<<UPM00) 
    | (1<<UPM01) | (0<<UMSEL00) | (0<<UMSEL01);


    sei(); //전체 인터럽트가 발생 ,USART용 인터럽트를 켜지 않으면 활성화 안됨 

    return;
}

void Led_Init()

    DDRA = 0xff;     //8개 포트을 출력용으로 사용 
    PORTA = 0xff;   //off


    return;
}

void __vector_25(void//교재 p137 참고하여 맞춤 
{
    //while(0==(UCSR0A&(1<<RXC0)));

    switch(UDR0)
    {
        case '1' :
        {
            PORTA = 0xfe;    
                 break;
        }

       case '2' :
        {
            PORTA = 0xfc;
                  break;
        }

      case '3' :
       {
            PORTA = 0xf8;
                 break;
        }

        case '4' :
        {
            PORTA = 0xf0;
                 break;
        }

        case '5' :
       {
            PORTA = 0xe0;
                  break;
       }

        case '6' :
        {
            PORTA = 0xc0;
                  break;
        }

        case '7' :
        {
             PORTA = 0x80;
                   break;
        }

        case '8' :
        {
            PORTA = 0x00;
                  break;
        }

        default :
        {
            PORTA = 0xff;
                 break;
        }

   }


return;

}

 UBRR0H = 0;    //UBRRH;

 UBRR0L = 8;    //UBRRL;

C언어 에서는 반올림을 지원하지 않기 때문에 주석에 달린대로 값을 넣었을 경우 제대로 명령이 실행되지 않았다.

그렇기 때문에 교재 227p를 참조하여 값을 직접 넣어줘야 한다.


   //수신완료 인터럽트 허용(교재 137p를 참조하여 벡터 함수를 만듬) , 송수신부 작동 허용 
    //8비트를 전송하기 위해 UCSZ02 0으로 셋팅 
    UCSR0B = (0<<TXB80) | (0<<RXB80) | (0<<UCSZ02) | (1<<TXEN0) | (1<<RXEN0) 
    | (0<<UDRIE0) | (0<<TXCIE0) | (1<<RXCIE0);

    //8비트 전송을 위해 UCSZ00 , UCSZ01 1로 맞춤 ,짝수 페리트를 사용하기 위해 UPM01 1 , UPM00 0으로 셋팅
    //비동기 모드 사용을 위해 UMSEL00 0 , UMSEL 01 0으로 셋팅 
    UCSR0C = (0<<UCPOL0) | (1<<UCSZ00) | (1<<UCSZ01) | (0<<USBS0) | (0<<UPM00) 
    | (1<<UPM01) | (0<<UMSEL00) | (0<<UMSEL01);

수신완료 인터럽트를 허용하고 8비트를 전송하고 , 송수신부 작동 허용, 짝수 패리트 사용 , 비동기 모드를 사용하기 위해서

위와 같이 설정을 해야 한다.


우선 UCSR0B 레지스터 7번 비트인 RXCIE0(USART RX Complete Interrupt Enable)는 수신완료 인터럽트를 개별적으로 허용하는 비트이다.

이를 1로 설정하고 SREG 레지스터의 I비트가 1이라면 1문자가 수신되어 UCSR0A 레지스터의 RXC0 비트가 1로 되는 경우 수신완료 인터럽트가 

발생한다.

다음 4번비트 RXEN0 (USART Receiver Enable)은 USART 포트의 수신부가 동작하도록 허용하는 비트인데 1을 넣어 활성화 한다.

또 3번비트 TXEN0  (USART Transmiter Enable)은 USART 포트의 송신부가 동작하도록 허용하는 비트이기 때문에 이역시 1을넣어 활성화 한다.


UCSR0C 레지스터에서 6번, 7번 비트가 USART 포트에서 동작모드를 설정하는 비트이다.

(UMSEL00-6번 비트 / UMSEL01-7번 비트) ( (USART Mode Select)


SART0 포트에서 동작 모드 설정 

UMSEL01

UMSEL00 

동작 모드 

 0

 USART0을 비동기 모드로 설정 

 0 

USART0을 동기 모드로 설정 

 1

사용하지 않음 

 1

USART0을 SPI 마스터모드 (MSPIM) 로 설정 


UCSR0C 레지스터 4~5번 비트인 UPM00 , UPM01  (USART Parity Mome)는 USART 포트에서 패리티 모드를 설정한다.

패리티 사용을 설정하면 송신부에서는 자동으로 패리티 비트를 계산하여 전송하며 , 수신부 에서는 수시된 패리티 비트와 계산한 패리티 비트를 

비교하여 일치하지 않으면 UCSR0A 레지스터에서 UPE0 = 1로 세트한다.


USART0   포트에서 페리티 모드의 설정

 UPM00

UPM00 

페리티 모드 

페리티 체크 기능을 사용하지 않음 

사용하지 않음 

짝수 페리티 방식을 사용 

 1

홀수 페리티 방식을 사용 


끝으로 데이터 전송 길이를 설정해야 하는데 사용할 비트들은 UCSR0B , UCSR0C 레지스터에 나누어져 있는데 하나만 보고 

많이 당황하지 않도록 주의해야 한다.


UCSR0B의 2번 비트인 UCSZ02 , UCSR0C의 1번, 2번 비트인 UCSZ00 , UCSZ01 (USART Stop Bit Select) 을 이용하여 

데이터 전송길이를 설정한다.


USART0 포트에서 전송 데이터 길이의 설정

  UCSZ02

UCSZ01 

UCSZ00 

전송 데이터 길이 

5비트 

6비트 

7비트 

8비트 

사용하지 않음 

사용하지 않음 

사용하지 않음 

9비트 



=======================================

덧 붙여 




LED 부자 경순



p.s : 다들 컴파일 하시고 USB 이용해서 .Hex 파일 옮길때 USB 케이블 조심히 다뤄야 될거 같습니다.

USB케이블 잘못되면 데이터 옮기는 과정에서 손실 발생해서 제대로된 결과가 출력이 안되는거 같아요.

것 때문에 오늘 누군가는 하 ㅜㅜ..멍2



728x90