Transcript Review
마이크로콘트롤러응용설계 – 1
Review
1. ATmega128의 특징
2. DIO – LED 출력, switch 입력, FND 출력
3. interrupt
시스템및센서네트워크연구실
1
ATmega128의 특징
고성능의 저전력 RISC 구조
133개 명령어 (대부분 한 사이클로 실행)
32*8 비트 범용 작업 레지스터
16MHz에서 16MIPS 명령 처리 속도, 곱셈기 2사이클 실행
데이터 및 비휘발성 메모리
128K 바이트 ISP 방식 프로그램용 플래시 메모리
4K 바이트 SRAM, 4K 바이트 EEPROM
64K 바이트 메모리
주변장치
ISP 기능을 갖는 SPI 인터페이스
JTAG 인터페이스
53개의 IO핀
리셋을 포함한 35개의 인터럽트 소스
시스템및센서네트워크연구실
2
프리스케일러를 갖는 2개의 8비트 타이머/카운터, 2개의 16비트 타이머/
카운터
8채널 10비트 AD 컨버터와 아날로그 비교기
TWI, SPI 인터페이스, 2개의 USART
독립적인 내장 발진기에 의한 워치독 타이머
특수 기능
6개의 슬립 모드
내부 RC 오실레이터와 외부 크리스탈을 연결하기 위한 발진회로 내장
외부, 내부 인터럽트 소스
동작 전압
2.7-5.5V (128L), 4.5-5.5V (128)
동작 클럭
0-8MHz (128L), 0-16MHz (128)
시스템및센서네트워크연구실
3
ATmega128 마이크로컨트롤러의 특징
AVR 8비트 RISC Mega 시리즈 비교
시스템및센서네트워크연구실
4
ATmega128 pin 배치
시스템및센서네트워크연구실
5
ATmega128의 메모리 구조
Flash program memory
application flash section
64K * 16 bit
instruction (명령어) – 16비트 또는 32비트
SPI 통신을 이용한 ISP, JTAG, 병렬 프로그래밍 방식
10,000번의 쓰기 및 삭제 가능
SRAM
32 registers
64 IO registers
160 Extended IO registers
4096 internal SRAM : 내부 데이터 메모리
64K external SRAM
EEPROM data memory
4K byte data EEPROM
시스템및센서네트워크연구실
6
IO 레지스터
IO 레지스터 (p71 Table 3-1, Table 3-2)
IO 레지스터를 이용하여 마이크로컨트롤러의 주변장치, 특수기능 등을
사용
IO 레지스터의 설정에 따라, 마이크로컨트롤러의 핀이 규정된 기능으로
동작함
• DDRB = 0b11111111;
// PORTB 출력 설정
• PORTB = 0b11111111; // PORTB high 출력
시스템및센서네트워크연구실
7
시스템및센서네트워크연구실
8
LED sink 회로 / switch pull up 회로
5V
PC0
+5V
PC1
…..
10K
PC7
PD2
104 (0.1uF)
시스템및센서네트워크연구실
9
FND 회로
PB0
1
5
B
C
PA1
6
1K
FND
PA0
10
E
+5V
…..
PA7
시스템및센서네트워크연구실
10
PORT 관련 레지스터
IO register
PORTx (port x data register) : 포트 x 데이터 출력 레지스터
• 초기값 0
DDRx (port x data direction register) : 포트 x 데이터 방향 설정 레지스터
• 초기값 0
PINx (port x pin input address) : 포트 x 입력 레지스터
• 초기값 N/A
• 읽기만 가능
포트핀의 동작 상태
DDRx – 0, PORTx – 1 : 입력
DDRx – 1, PORTx – 0 : 출력, low 출력 (sink 출력 회로)
DDRx – 1, PORTx – 1 : 출력, high 출력 (source 출력 회로)
기타 : high impedance 상태 (동작안함)
시스템및센서네트워크연구실
11
실습 1
// PORTC를 이용하여 LED 1개 0.5초 간격으로 왕복 순차 점멸
#include <mega128.h>
#include <delay.h>
// mega128 마이크로콘트롤러 관련 헤더 파일
// delay 함수 정의 헤더 파일
void main(void)
{
char led = 0b11111110;
DDRC = 0xFF;
// char형 변수 선언
// DDRC : 포트 방향 설정 레지스터
while(1){
while(led != 0b01111111) {
PORTC = led;
delay_ms(500);
led <<= 1;
led |= 0b00000001;
}
while(led != 0b11111110) {
PORTC = led;
delay_ms(500);
led >>= 1;
led |= 0b10000000;
}
} 시스템및센서네트워크연구실
// while(1) : 무한 루프
// PORTC : 포트 입출력 레지스터
// delay 함수
// PORTC : 포트 입출력 레지스터
// 쉬프트 후에 0비트에는 ‘0’이 입력되므로, ‘1’로 셋
// PORTC : 포트 입출력 레지스터
// delay 함수
// PORTC : 포트 입출력 레지스터
// 쉬프트 후에 7비트에는 ‘0’이 입력되므로, ‘1’로 셋
12
실습 2
// SW1(PD2)이 누를 때마다 PORTC LED 1개 랜덤 점등
char key, oldkey, led;
char position = 0;
DDRD = 0b00000000;
DDRC = 0b11111111;
// 자리수를 결정하는 변수
// PD2 입력 설정
// PORTC 출력 설정
led = 0b11111110;
PORTC = led;
oldkey = PIND & 0b00000100;
// 0번 비트만 on
// PORTC 출력
// SW1 상태 추출 -> 누르지 않았으므로, 0b00000100
// while(1) : 무한 루프
// SW1 상태 추출
// 누르지 않은 경우 : oldkey – 0b00000100, key – 0b00000100
// 누른 경우 :
oldkey – 0b00000100, key – 0b00000000 -> 이 때만 실행
position = (char) (rand() % 8);
// 랜덤 숫자를 8로 나머지 연산을 수행. 결과는 1 – 7
PORTC = (char) pow(2, position) ^ 0xFF; // pow(2, position) : position 위치에 있는 비트만 1로 설정
// ^ 0xFF : sink 회로이므로 반전 연산
while(1){
key = PIND & 0b00000100;
if(oldkey != 0 && key == 0) {
}
oldkey = key;
delay_ms(100);
// 계속 누르고 있는 경우 : oldkey – 0b00000000, key – 0b00000000
// 손을 뗐을 때 :
oldkey – 0b00000000, key – 0b00000100
// 키의 떨림 현상을 방지하기 위하여 100msec 지연
}
시스템및센서네트워크연구실
13
Interrupt
MCU에서 입력을 받아들이는 방법
폴링(polling) : 사용자가 명령어를 사용하여 입력 핀의 값을 계속 읽어서
변화를 알아내는 것
인터럽트(interrupt) : MCU 자체가 하드웨어적으로 그 변화를 체크하여 변
화시에만 일정한 동작을 하는 것
예 : 시간이 되었을 때 타이머를 울리고자 할 때
• 시계를 눈으로 확인하고 있다가 시간이 되면 타이머 울리는 방법
• 다운 타이머를 설정한 후 시간이 되면, 자동으로 타이머가 울리는 방
법
시스템및센서네트워크연구실
14
인터럽트
CPU 외부의 하드웨어적인 요구에 의해서 정상적인 프로그램의 실행 순
서를 변경하여 보다 시급한 작업을 먼저 수행 한 후에 다시 원래 프로그
램으로 복귀하는 것
• 예 : 책을 읽고 있는 도중에 전화가 와서 책의 읽던 페이지에 책갈피를
끼워 표시해두고 전화를 받은 다음에 다시 표시해 두었던 페이지를
찾아 책을 계속 읽어가는 경우에 비유
인터럽트는 주변장치의 서비스 요청에 CPU가 가장 빠르게 대응할 수 있
는 방법
주변장치로부터 발생시기를 예측하기 어려운 비동기적인 일(event)을
CPU가 빠르게 처리 할 수 있음
주프로그램 루틴
발생
시스템및센서네트워크연구실
주프로그램 루틴
복귀
인터럽트 처리 루틴
15
인터럽트 소스와 벡터 테이블
인터럽트 소스(interrupt source)
인터럽트를 발생시킬 수 있도록 만들어진 것
리셋, 외부 인터럽트, 타이머, SPI, USART, A/D 등
인터럽트 벡터 테이블(interrupt vector table) / 인터럽트 점프 테이블
(interrupt jump table)
인터럽트 발생시 분기 장소를 기록해 놓은 특정 번지의 내용
인터럽트 서비스 루틴(interrupt service routine) / 인터럽트 핸들러(interrupt
handler)
인터럽트 처리 프로그램
시스템및센서네트워크연구실
16
인터럽트 동작
인터럽트 동작 조건
SREG 레지스터의 I비트 (전역 인터럽트 인에이블 비트) 1로 셋
해당 인터럽트 소스에 해당되는 인터럽트 동작 레지스터 셋
인터럽트 동작
SREG 레지스터의 I비트 => 1 & 해당 인터럽트 동작 레지스터 => 1
• 인터럽트 발생시 해당 인터럽트 서비스 루틴으로 점프
• I 비트는 0으로 클리어되며, 모든 인터럽트 무시됨
• 인터럽트 서비스 루틴에 있는 프로그램을 실행하고 난 후, I 비트는
자동적으로 셋 됨
시스템및센서네트워크연구실
17
외부 인터럽트 (external interrupt)
외부 인터럽트
INT0 – INT7 핀에 의하여 발생 (PD0, 1, 2, 3, PE4, 5, 6, 7)
외부 인터럽트가 인에이블(enable)되면, 해당 핀에서 인터럽트가 발생됨
에지 트리거(하강 에지 또는 상승 에지) 또는 레벨 트리거(low 레벨)에 의
해 인터럽트 발생 가능
시스템및센서네트워크연구실
18
External Interrupt 관련 IO register
SREG (status register) : 상태 레지스터
bit 7 : I (초기값 0) : 전역 인터럽트 인에이블 비트
• 모든 인터럽트를 인에이블시키기 위해서 셋 되어야 함
• 인터럽트 발생 후 하드웨어적으로 자동 클리어됨
• 다음 인터럽트 인에이블을 위해서 RETI 명령 또는 소프트웨어적으로 셋 되어야 함
EIMSK (External Interrupt Mask Register)
bit 7 – 0 : INT7 - INT0 : 외부 인터럽트 인에이블 비트 – 설정 비트
• INTn이 셋 되고, I비트가 셋 되어 있을 경우 외부 인터럽트 인에이블
시스템및센서네트워크연구실
19
EICRA & EICRB (External Interrupt Control Register A & B)
ISCn1, ISCn0 : INTn의 인터럽트 트리거 방식을 설정
ISCn1 ISCn0
0
0 INTn의 low 레벨에서 인터럽트 발생
0
1 INTn의 논리적 변화에서 인터럽트 발생
1
0 INTn의 하강 에지에서 인터럽트 발생
1
1 INTn의 상승 에지에서 인터럽트 발생
클럭에 관계없이 비동기적으로 검출
슬립모드를 해제하는 수단으로 사용될 수 있음
시스템및센서네트워크연구실
20
EIFR(External Interrupt Flag Register) : 외부 인터럽트 플래그 레지스터
INTFn : INTn 플래그
• INTn에서 인터럽트 요구 이벤트가 발생하였을 때 해당 비트가 셋 됨
• INTn과 I비트가 셋 되어 있으면 해당 인터럽트 벡터로 점프
• 인터럽트 서비스 루틴이 실행되면 자동으로 클리어, 또는 플래그 비트에 1을 쓰면 클리
어됨
• 레벨 트리거로 설정된 경우에는 항상 클리어되어 있음
시스템및센서네트워크연구실
21
CodeVisionAVR의 인터럽트 서비스 루틴 형식
CodeVisionAVR의 인터럽트 서비스 루틴
형식
interrupt [인터럽트 소스명] void 함수명(void)
{
인터럽트 서비스 루틴
}
인터럽트 소스명
• define EXT_INT0 2
• define EXT_INT1 3
• define EXT_INT2 4
시스템및센서네트워크연구실
22
실습 3
// 외부 인터럽트0(PD0, INT0)에 의한 LED 쉬프트 (에지 트리거)
#include <mega128.h>
unsigned char led = 0b11111110;
// 인터럽트서비스루틴에서 사용되는 변수는 반드시 전역변수로 선언해야 함
void main(void) {
DDRD = 0b00000000;
DDRC = 0b11111111;
PORTC = led;
// PD0 입력 설정
// PORTC 출력 설정
// 포트 C에 초기값 출력
EIMSK = 0b00000001;
EICRA = 0b00000010;
SREG = 0b10000000;
// 외부 인터럽트0 인에이블
// 외부 인터럽트0 하강 에지
// 전역 인터럽트 인에이블 비트 셋
while(1);
}
// 외부 인터럽트0 서비스 루틴
interrupt [EXT_INT0] void external_int0(void) {
led = (led << 1) | 0b00000001;
// 1비트 쉬프트
if(led == 0xFF) led = 0xFE;
// 마지막 비트까지 왔을 때, 0번 비트 on
PORTC = led;
}
시스템및센서네트워크연구실
23
실습 4
// SW1(PD2, INT2)이 눌러지면 왼쪽 쉬프트, SW2(PD3, INT3)가 눌러지면 오른쪽 쉬프트 : 인터럽트 방식
unsigned char led = 0xFE;
void main(void)
{
DDRD = 0b00000000;
DDRC = 0b11111111;
PORTC = led;
// PD2, 3 입력 설정
// PORTC 출력 설정
// 포트 C에 초기값 출력
EIMSK = 0b00001100;
EICRA = 0b10100000;
SREG = 0b10000000;
// 외부 인터럽트2, 3 인에이블
// 외부 인터럽트2, 3 하강 에지
// 전역 인터럽트 인에이블 비트 셋
while(1);
// 무한 루프
}
interrupt [EXT_INT2] void external_int2(void)
{
led = (led<<1) | 0b00000001;
if(led == 0xFF) led = 0xFE;
PORTC = led;
}
interrupt [EXT_INT3] void external_int3(void)
{
led = (led>>1) | 0b10000000;
if(led == 0xFF) led = 0x7F;
PORTC = led;
} 시스템및센서네트워크연구실
// 외부 인터럽트2 서비스 루틴
// 왼쪽 쉬프트
// 외부 인터럽트3 서비스 루틴
// 오른쪽 쉬프트
24
실습 5
else {
PORTC = led;
led = (led>>1) | 0b10000000;
if(led == 0xFF) led = 0x7F;
}
oldkey = key;
delay_ms(500);
// SW1(PD2)을 이용하여, 누르면 왼쪽 쉬프트, 다시 누르면 오른쪽 쉬프트,
// 다시 누르면 전체 off를 반복하도록 프로그램
void main(void)
{
char key, oldkey, flag, led, led_all;
DDRD = 0b00000000;
DDRC = 0b11111111;
// PD2 입력 설정
// PORTC 출력 설정
// 스위치가 2번째 눌러짐
// 오른쪽 쉬프트
}
}
led = 0b11111110;
led_all = 0b11111111;
flag = 0;
oldkey = PIND & 0b0000100;
while(1){
key = PIND & 0b00000100;
if(oldkey != key)
flag = ++flag % 3;
if(flag == 0) {
PORTC = led_all;
led_all ^= 0xFF;
}
else if(flag == 1) {
PORTC = led;
led = (led<<1) | 0b00000001;
if(led == 0xFF) led = 0xFE;
}
시스템및센서네트워크연구실
// 0 - off, 1 - 오른쪽 쉬프트, 2 - 왼쪽 쉬프트
// while(1) : 무한 루프
// PD2 값 읽어오기 - 비트 마스킹 기능
// 스위치가 몇 번째 눌러진 것인지를 체크
// 스위치가 0번째 눌러짐
// 스위치가 1번째 눌러짐
// 왼쪽 쉬프트
25