오늘 수업은 지금까지 이론으로 수업한 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 | 0 | USART0을 비동기 모드로 설정 |
0 | 1 | USART0을 동기 모드로 설정 |
1 | 0 | 사용하지 않음 |
1 | 1 | USART0을 SPI 마스터모드 (MSPIM) 로 설정 |
UCSR0C 레지스터 4~5번 비트인 UPM00 , UPM01 (USART Parity Mome)는 USART 포트에서 패리티 모드를 설정한다.
패리티 사용을 설정하면 송신부에서는 자동으로 패리티 비트를 계산하여 전송하며 , 수신부 에서는 수시된 패리티 비트와 계산한 패리티 비트를
비교하여 일치하지 않으면 UCSR0A 레지스터에서 UPE0 = 1로 세트한다.
USART0 포트에서 페리티 모드의 설정
UPM00 | UPM00 | 페리티 모드 |
0 | 0 | 페리티 체크 기능을 사용하지 않음 |
0 | 1 | 사용하지 않음 |
1 | 0 | 짝수 페리티 방식을 사용 |
1 | 1 | 홀수 페리티 방식을 사용 |
끝으로 데이터 전송 길이를 설정해야 하는데 사용할 비트들은 UCSR0B , UCSR0C 레지스터에 나누어져 있는데 하나만 보고
많이 당황하지 않도록 주의해야 한다.
UCSR0B의 2번 비트인 UCSZ02 , UCSR0C의 1번, 2번 비트인 UCSZ00 , UCSZ01 (USART Stop Bit Select) 을 이용하여
데이터 전송길이를 설정한다.
USART0 포트에서 전송 데이터 길이의 설정
UCSZ02 | UCSZ01 | UCSZ00 | 전송 데이터 길이 |
0 | 0 | 0 | 5비트 |
0 | 0 | 1 | 6비트 |
0 | 1 | 0 | 7비트 |
0 | 1 | 1 | 8비트 |
1 | 0 | 0 | 사용하지 않음 |
1 | 0 | 1 | 사용하지 않음 |
1 | 1 | 0 | 사용하지 않음 |
1 | 1 | 1 | 9비트 |
=======================================
덧 붙여
LED 부자 경순
p.s : 다들 컴파일 하시고 USB 이용해서 .Hex 파일 옮길때 USB 케이블 조심히 다뤄야 될거 같습니다.
USB케이블 잘못되면 데이터 옮기는 과정에서 손실 발생해서 제대로된 결과가 출력이 안되는거 같아요.
것 때문에 오늘 누군가는 하 ㅜㅜ..
'코스웨어 > 13년 스마트컨트롤러' 카테고리의 다른 글
놀땐 미친듯이 놀아야지 ㅋㅋㅋㅋㅋㅋ (3) | 2013.06.06 |
---|---|
도서관리 최종 (7) | 2013.06.06 |
초음파 센서하니 떠오른...음속에 대해 - 전영기 (4) | 2013.06.05 |
2013-06-05 수업내용 전영기 (0) | 2013.06.05 |
2013.06.04_AVR_USART_LED차례대로켜보기 (4) | 2013.06.04 |
13기수 진격의 남좌들 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ (11) | 2013.06.04 |
vi 명령어 일람 (5) | 2013.06.03 |
리눅스 공부 하려고 찾은 사이트 (5) | 2013.06.02 |