1. 마이크로 컨트롤러의 정의
- 마이크로 프로세서 : 프로세서를 하나의 칩안에 집적하여 넣어 소형화한 형태
- 마이크로컨트롤러(MCU: Micro Controller Unit) : 지능화와 소형화를 위하여 마이크로 프로세서에 메모리와 각종
주변장치들을 함께 집적하여 넣은 칩
2. AVR 마이크로 컨트롤러 개요
- 1997년 처음 발표한 8비트 제어용 마이크로프로세서로서 RICS 기술을 기반으로 만들어 짐
- 대부분의 명령이 단일 클럭으로 실행되어 동작 속도를 혁신적으로 개선
- 임베디드 환경에 적합한 저전력 소모의 칩
- AVR은 데이터 메모리와 프로그램 메모리가 분리된 하버드 아키텍처를 따름 CPU의 데이터 처리 속도를 높일 수 있음
- 칩 내에 프로그램 코드용으로 플래시 메모리를 내장하고, 사용자가 프로그램을 쉽게 다운로드 할 수 있는 isp 방식 적용
- 많은 장점 때문에 상대적으로 늦게 출시되었음에도 불구하고 8051이나 PIC을 능가하는 인기를 단시간 내에 얻게 되었음
3. AVR 마이크로 컨트롤러 특징
- 하버드 아키텍쳐 : 명령어와 데이터 통로를 저장공간과 물리적으로 분리한 컴퓨터 아키텍처를 말함.
CPU가 없는 병렬식 컴퓨터 구조. 데이터와 명령어가 다른 버스를 사용
- 장점 : 명령어를 읽을 때 데이터를 읽거나 쓸 수 있어 성능이 뛰어나다
- 단점 : 버스 시스템이 복잡하여 설계가 복잡하다
- 폰노이만 아키텍쳐 : 데이터는 메모리에서 읽거나 메모리에 쓰기도 하는 방면에 명령어는 메모리에서 읽기만 하는 구조
CPU 중심의 컴퓨터. 데이터와 명령어가 같은 버스를 공유
- 장점 : 범용성이 좋고 여러 목적으로 이용이 가능하기 때문에 현재 컴퓨터에 많이 사용된다
- 단점 : 명령어를 읽을 때 데이터를 읽거나 쓸 수 없다
4. ATMega128의 리셋 모드
- Power-on Reset : 전원전압 VCC의 전압 레벨에 따른 리셋
- External Reset : /RESET 핀에 의한 외부 리셋
- Watchdog Reset : 워치독 타이머에 의한 리셋
- Brown-out Reset : Brown-out Detector에 의한 리셋
- JTAG AVR Reset : JTAG 시스템에 의한 리셋
5. 마이크로 컨트롤러와 GPIO
- GPIO(General Purpose Input Output)
- 개념 : 범용으로 사용되는 입출력 포트. 설계자가 마음대로 변형하면서 제어할 수 있도록 제공해 주는 I/O(입출력) 포트
- 개요 :
- 입력과 출력을 마음대로 선택할 수 있고, 0과 1의 출력 신호를 임의로 만들어줄 수 있는 구조를 가짐
- 입력으로 사용할 때는 외부 인터럽트를 처리할 수 있도록 하는 경우가 많음
- 입출력 방향 전환용 레지스터와 출력용/입력용 데이터 레지스터 등이 필요
- 마이크로 컨트롤러에서는 대부분의 핀들을 GPIO로 설정하는 경우가 많음
6. DDRx 레지스터
- 입출력의 방향설정을 하기 위한 레지스터.
- DDRA~DDRG레지스터의 해당 비트에 ‘1을 쓰면 출력, ‘0’을 쓰면 입력으로 설정. 0xFF : 출력 0x00 : 입력
7. PORTx 레지스터
- 데이터를 출력하기 위한 레지스터이다
- 출력을 원하는 데이터값을 PORTx 레지스터에 넣어주면 된다
8. PINx 레지스터
- 데이터 입력용 레지스터이다
- PINx 레지스터에 해당하는 값을 읽으면 해당 핀의 값이 읽어진다.
3-1 LED
// 1)
#include<avr/io.h>
#include<util/delay.h>
int main(){
char i;
unsigned char LED_Data=0x0;
// 2)
DDRE = 0xFF;
// 3)
while(1){
PORTE = LED_Data;
LED_Data++;
for(i=0;i<100;i++)
_delay_ms(10); //ms단위의 딜레이함수
}
return 0;
}
1) AVR 입출력에 대한 헤더 파일과 delay 함수사용을 위한 헤더파일을 선언한다.
2) 포트E 를 출력포트로 설정한다.
3) 포트E로 변수 LED_Data에 있는 데이타를 출력한다. 그리고 값을 1씩 더해주며, 1초 딜레이를 가진 다음 루프를
반복한다. _delay_us()함수는 104 us 까지 , _delay_ms()함수는 35ms 까지 지원한다.
3-2 switch
// 1)
#include<avr/io.h>
int main(){
// 2)
DDRE = 0xFF;
DDRB = 0x00;
// 3)
while(1){
PORTE = PINB;
}
return 0;
}
1) AVR 입출력에 대한 헤더 파일을 선언한다.
2) 포트E 를 출력포트로 설정한다. 포트B 를 입력포트로 설정한다.
3) 포트B에 연결된 버튼의 값이 포트E의 LED로 출력되고, 루프를 반복한다.
3-3 FND
// 1)
#include<avr/io.h>
#include<util/delay.h>
int main(){
// 2)
unsigned char FND_DATA_TBL[]={0x3F,0X06,0X5B,0X4F,0X66,0X6D,0X7C,0X07,0X7F,0X67,0X77,0X7C,0X39,0X5E,0X79,0X71,0X08,0X80};
unsigned char cnt=0 , i ;
// 3)
DDRD = 0xFF;
// 4)
while(1){
PORTD = FND_DATA_TBL[cnt];
cnt++;
if(cnt>17) cnt=0; //테이블 크기를 초과하는 경우 방지.
for(i=0;i<50;i++)
_delay_ms(10);
}
return 0;
}
1) AVR 입에 대한 헤더 파일과 delay 함수사용을 위한 헤더파일을 선언한다.
2) 0~9, A~F 그리고 점,밑줄 을 FND에 맞추어 정리해둔 테이블을 선언한다.
3) 포트D 를 출력포트로 설정한다.
4) 포트D에 FND_DATA_TBL배열에 저장된 값을 500ms 단위로 하나씩 출력한다.
_delay_us()함수는 104 us 까지 , _delay_ms()함수는 35 ms 까지 지원한다.
5-1 interrupt_led
#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
unsigned char Time_STOP = 0;
// 2)
SIGNAL(SIG_INTERRUPT0);
int main(){
unsigned char LED_Data = 0x01,i;
// 3)
DDRD = 0xFE;
DDRE = 0xFF;
// 4)
EICRA = 0x0F;
EICRB = 0x00;
EIMSK = 0x01;
EIFR = 0x01;
// 5)
sei();
while(1){
// 6)
PORTE = LED_Data;
if(Time_STOP == 0) {
if(LED_Data == 0x80) LED_Data = 0x01;
else LED_Data <<= 1;
}
for(i=0;i<10;i++)
_delay_ms(10);
}
return 0;
}
SIGNAL(SIG_INTERRUPT0){
cli();
if(Time_STOP == 0)
Time_STOP = 1;
else
Time_STOP = 0;
sei();
}
1) AVR 입출력에 대한 헤더 파일과 인터럽트를 사용하기 위한 헤더delay 함수사용을 위한 헤더파일을 선언한다.
2) 인터럽트 서비스 루틴을 선언한다. 인터럽트 0
3) 포트D 의 PD0를 입력포트로 설정한다. 포트E를 출력으로 선언한다.
4) 인터럽트 0를 상승엣지에서 동작하도록 설정한다.
5) 모든 인터럽트를 허용하는 함수.
6) 100ms마다 LED가 좌측으로 쉬프트되면서 켜진다. Time_Stop이 0인경우에만 계속 쉬프트된다. Time_Stop이 1이 되면
LED_Data가 변하지 않게 되고, LED는 멈춘다.
7) 한번 누르면 스톱, 한번더 누르면 재개한다. cli() 함수는 전체인터럽트 금지하는 함수이다. 인터럽트중에 인터럽트발생을 방지하기 위한 처리이다. 처리가 모두 끝나면 sei()함수로 인터럽트를 다시 허용한다.
5-2 Interrupt_stopwatch
// 1)
#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
unsigned char time_10ms=0,time_100ms=0,time_1s=0,time_10s=0;
char Time_STOP = 1;
// 2)
SIGNAL(SIG_INTERRUPT0);
SIGNAL(SIG_INTERRUPT1);
int main(){
unsigned char FND_DATA_TBL[]={0x3F,0X06,0X5B,0X4F,0X66,0X6D,0X7C,0X07,0X7F,0X67,0X77,0X7C,
0X39,0X5E,0X79,0X71,0X08,0X80};
// 3)
DDRD = 0xFC;
DDRG = 0x0F;
DDRE = 0xFF;
// 4)
EICRA = 0x0F;
EICRB = 0x00;
EIMSK = 0x03;
// 5)
sei();
Time_STOP = 1;
while(1){
// 6)
PORTG = 0x07; // C3을 선택한다
PORTE = FND_DATA_TBL[time_10ms]; //FND_DATA_TBL배열에서 time_10ms만큼의 FND데이타를 출력한다.
_delay_ms(2); //잔상을 남게하기 위한 딜레이
PORTG = 0x0B;
PORTE = FND_DATA_TBL[time_100ms];
_delay_ms(2);
PORTG = 0x0D;
PORTE = FND_DATA_TBL[time_1s]|0x80;
_delay_ms(3);
PORTG = 0x0E;
PORTE = FND_DATA_TBL[time_10s];
_delay_ms(3);
if(Time_STOP==1) continue; //인터럽트에 의한 Stop/Resume 처리
//여기까기 사용된 딜레이 함수가 약 10ms이므로 time_10ms는 10ms마다 증가된다.
time_10ms++;
if(time_10ms == 10){
time_10ms = 0;
time_100ms++ ;
}
if(time_100ms == 10){
time_100ms = 0;
time_1s++ ;
}
if(time_1s == 10){
time_1s = 0;
time_10s++ ;
}
if(time_10s == 10){
time_10s = 0;
}
}
return 0;
}
// 7)
SIGNAL(SIG_INTERRUPT0){ // Stop/Resume 처리
cli();
if(Time_STOP==0)
Time_STOP=1;
else
Time_STOP=0;
sei();
}
// 8)
SIGNAL(SIG_INTERRUPT1){ //리셋
cli();
time_10ms=0;
time_100ms=0;
time_1s=0;
time_10s=0;
sei();
}
1) AVR 입출력에 대한 헤더 파일과 인터럽트 를 사용하기 위한 헤더delay 함수사용을 위한 헤더파일을 선언한다.
2) 인터럽트 서비스 루틴을 선언한다. 인터럽트 0,1
3) 포트D 의 PD0, PD1을 입력포트로 설정한다. 포트E,포트G를 출력으로 선언한다.
4) 인터럽트 0,1을 상승엣지에서 동작하도록 설정한다.
5) 모든 인터럽트를 허용하는 함수.
6) 10ms단위부터 10초단위까지의 스톱워치가 동작하면서 인터럽트에 의해 리셋, 스톱을 FND로 출력한다.
7) 한번 누르면 스톱, 한번더 누르면 재개한다. cli() 함수는 전체인터럽트 금지하는 함수이다. 인터럽트중에 인터럽트발생을
방지하기 위한 처리이다. 처리가 모두 끝나면 sei()함수로 인터럽트를 다시 허용한다.
8) 시간을 리셋한다.
'프로그래밍 > ATMega128' 카테고리의 다른 글
(ATMega128) PC와의 UART통신 (0) | 2016.07.10 |
---|---|
(ATmega128) 타이머로 LED 켜기 (0) | 2016.07.10 |
(ATMega128) PWM 사용하기 (0) | 2016.07.10 |
(ATMega128) 인터럽트를 이용한 LED동작 멈춤/재생 (0) | 2016.07.10 |
(ATMega128) FND값 올리기 (0) | 2016.07.10 |