Speaker, Watchdog timer, Sleep 실습 (not updated)
Download
Report
Transcript Speaker, Watchdog timer, Sleep 실습 (not updated)
마이크로프로세서응용설계 - 7
Speaker
Watchdog timer
Sleep
시스템및센서네트워크연구실
1
ATmega128
시스템및센서네트워크연구실
2
LED sink / switch pullup 회로
470
5V
PC0
+5V
PC1
…..
10K
PC7
PD2
104 (0.1uF)
시스템및센서네트워크연구실
3
LCD 회로
#1
+5V
VDD
#2
LCD 밝기 조절
V0
VSS
#3
시스템및센서네트워크연구실
+5
V
LEDA
LEDK
RS
R/W
E
PC0
PC1
PC2
DB4
DB5
DB6
DB7
PC4
PC5
PC6
PC7
4
시스템및센서네트워크연구실
5
LCD 함수
// LCD 초기화 함수
#include <delay.h>
void LCD_init(void)
#define LINE2
#define HOME
#define RSHIFT
#define LSHIFT
#define DISPON
#define DISPOFF
0xC0
0x02
0x1C
0x18
0x0c
0x08
// 2nd Line Move
// Cursor Home
// Display Right Shift
// Display Left Shift
// Display On
// Display Off
{
DDRC = 0xFF;
// 포트 C 출력 설정
PORTC &= 0xFB;
//E = 0;
// 충분한 지연시간을 통한 안정화 과정
delay_ms(15);
Command(0x20);
void LCD_init(void);
void LCD_String(char flash str[]);
void Busy(void);
void Command(unsigned char);
void Data(unsigned char);
// D5=1
delay_ms(5);
Command(0x20);
// D5=1
delay_us(100);
Command(0x20);
// D5=1
// 초기화 과정
Command(0x28);
// function set
Command(0x06);
// entry mode set
Command(0x01);
// all clear
Command(0x0c);
// display on
}
시스템및센서네트워크연구실
6
//데이터 쓰기 함수
void Data(unsigned char byte)
{
Busy();
// 인스트럭션 쓰기 함수
void Command(unsigned char byte)
{
Busy();
// 인스트럭션 상위 바이트
PORTC = (byte & 0xF0);
PORTC &= 0xFE;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 인스트럭션 하위 바이트
PORTC = ((byte<<4) & 0xF0);
PORTC &= 0xFE;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 데이터 상위 바이트
PORTC = (byte & 0xF0);
PORTC |= 0x01;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 데이터
// RS = 0;
// RW = 0;
// E = 1;
// E = 0;
// 데이터 하위 바이트
PORTC = ((byte<<4) & 0xF0);
PORTC |= 0x01;
PORTC &= 0xFD;
delay_us(1);
PORTC |= 0x04;
delay_us(1);
PORTC &= 0xFB;
// 데이터
// RS = 0;
// RW = 0;
// E = 1;
// E = 0;
// 데이터
//RS = 1;
//RW = 0;
//E = 1;
//E = 0;
// 데이터
//RS = 1;
//RW = 0;
//E = 1;
//E = 0;
}
}
// 문자열 출력 함수
void LCD_String(char flash str[])
{
char flash *pStr=0;
// Busy Flag Check -> 일반적인 BF를 체크하는 것이 아니라
// 일정한 시간 지연을 이용한다.
void Busy(void)
{
delay_ms(2);
}
pStr = str;
while(*pStr) Data(*pStr++);
}
시스템및센서네트워크연구실
7
Speaker – 음악 멜로디 연주
음악의 기본 구성
음의 높이(음계, 음정, tone), 음의 길이(박자, beat), 음의 강약, 음의 색깔
음의 높이는 주파수로, 음의 길이는 신호 발생시간으로 조절 가능
음의 강약은 신호 파형의 진폭에 의해, 음의 색깔은 신호 파형에 고조파 성분의
포함 정도나 진폭의 변화에 의해 결정됨
uC에는 음의 높이와 길이는 쉽게 조절이 가능하나, 음의 강약과 색깔은 D/A 컨버
터나 Op Amp 등과 같은 복잡한 회로가 필요
음악 멜로디 연주의 원리
주파수는 타이머의 분주 기능을 이용하여 조절
연주시간은 시간지연 루틴을 사용하여 조절
스피커를 구동하는 파형은 듀티비를 50%에 가깝게 하는 것이 좋음
• 타이머 CTC모드의 토글 동작 이용
시스템및센서네트워크연구실
8
Timer/counter1 & 3 관련 IO 레지스터
TCNT1 & 3 (Timer/Counter1 & 3 Register)
OCR1A, 1B, 1C & 3A, 3B, 3C (Output Compare Register 1A, 1B, 1C, & 3A, 3B, 3C)
TIMSK (Timer/Counter Interrupt Mask Register) / ETIMSK (Extended TIMSK)
TCCR1A (Timer/Counter1 Control Register A)
bit 1, 0 – WGM11, WGM10(Waveform Generation Mode)
bit (7,6), (5,4), (3,2) – COMnA(B,C)1, COMnA(B,C)0
• CTC mode일 때
00 : OCn 차단
01 : 비교 매치에서 OCnA(B,C) toggle 신호
10 : 비교 매치에서 OCnA(B,C) 클리어
11 : 비교 매치에서 OCnA(B,C) 셋
TCCR1B (Timer/Counter1 Control Register B)
bit 4, 3 – WGM13, WGM12(Waveform Generation Mode)
0100 : CTC – TOP : OCR1A
bit 2:0 – CS02:00 (Clock Selection)
010 : 8분주
시스템및센서네트워크연구실
9
음계 및 쉼표의 발생
음계 발생의 원리
음계는 0 – 9 옥타브로 구성
각 옥타브에는 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 등 12개의 음이 존재
이웃하는 두 음계 사이에는 1:212, 즉 1:1.05946의 비율로 주파수가 증가됨
타이머1을 이용한 출력 주파수 계산
• CTC mode 4 사용 : OCR1A를 Top
• 프리스케일러 – 8분주
• fOC1A = 16*106 / (2 * 8 * (1+OCR1A)) = 106 / (1+OCR1A)
• COM1A toggle mode 사용
OCRn
TCNTn
0x00
OCn
음계별 표준주파수와 타이머1에 의한 출력 주파수 (표)
시스템및센서네트워크연구실
10
시스템및센서네트워크연구실
11
음표 및 쉼표 발생의 원리
음표나 쉼표는 각 음계의 연주시간 또는 휴지시간을 나타냄
음표나 쉼표는 상대적인 시간값을 가짐
각 음표의 실제 연주시간은 음표의 종류뿐 아니라 음악의 연주 속도를 표시하는
템포(tempo)에 의하여 결정됨
음표 및 쉼표의 종류와 상대 길이 (표)
프로그램에서는 템포를 1(가장 빠름)에서 7(가장 느림)까지 정의하고, 가장 짧은
연주 시간 단위인 32분 음표를 21ms의 기본 시간으로 정의
• 실제 음표의 연주시간 : 기본 시간 * 상대 길이 * 템포값
시스템및센서네트워크연구실
12
시스템및센서네트워크연구실
13
실습1
악보
-
OC1A(PB5)
시스템및센서네트워크연구실
+
+5V
14
// 학교종이땡땡땡 연주
// note
#define VLOA
9008 // octave 2
#define VLOAX 8580
#define VLOB
8098
#define LOC
#define LOCX
#define LOD
#define LODX
#define LOE
#define LOF
#define LOFX
#define LOG
#define LOGX
#define LOA
#define LOAX
#define LOB
7644
7214
6810
6427
6066
5726
5404
5101
4815
4544
4289
4049
#define MIC
#define MICX
#define MID
#define MIDX
#define MIE
#define MIF
#define MIFX
#define MIG
#define MIGX
#define MIA
#define MIAX
#define MIB
3821
3607
3404
3213
3033
2862
2702
2550
2407
2272
2144
2024
// 도 octave 3
// 레
// 미
// 파
// 솔
// 라
// 시
// 도 octave 4 (기본 음계)
// 레
// 미
// 파
// 솔
// 라
// 시
시스템및센서네트워크연구실
#define HIC
#define HICX
#define HID
#define HIDX
#define HIE
#define HIF
#define HIFX
#define HIG
#define HIGX
#define HIA
#define HIAX
#define HIB
1910
3607
3404
3213
3033
2862
2702
2550
2407
2272
2144
2024
// 도 octave 5
// 레
// 미
// 파
// 솔
// 라
// 시
// note length
#define NOTE32 1*3
#define NOTE16 2*3
#define NOTE16D 3*3
#define NOTE8 4*3
#define NOTE8D 6*3
#define NOTE4 8*3
#define NOTE4D 12*3
#define NOTE2 16*3
#define NOTE2D 24*3
#define NOTE1 32*3
// rest length
#define REST32 1*3
#define REST16 2*3
#define REST16D 3*3
#define REST8 4*3
#define REST8D 6*3
#define REST4 8*3
#define REST4D 12*3
#define REST2 16*3
#define REST2D 24*3
#define REST1 32*3
15
void play_note(unsigned int sound, unsigned int note);
void play_rest(unsigned int rest);
play_note(MIG, NOTE4);
play_note(MIG, NOTE4);
play_note(MIE, NOTE4);
play_note(MIE, NOTE4);
play_note(MID, NOTE2D);
play_rest(REST4);
void main(void)
{
DDRB = 0b00100000;
play_note(MIG, NOTE4);
play_note(MIG, NOTE4);
play_note(MIA, NOTE4);
// OC1A(PD5)에 스피커 연결
unsigned int tempo=0;
// PB5(OC1A) 출력 설정
play_note(MIA, NOTE4);
TCCR1A = 0b01000000; // COM1A1,A0(7,6)-01, mode 4 - CTC모드 / OCR1A (WGM11,10 - 00)
TCCR1B = 0b00001010; // mode 4(WGM13,12 - 01), 프리스케일 = 8
while(1){
tempo = 4;
play_note(MIG, NOTE4);
play_note(MIG, NOTE4);
play_note(MIE, NOTE4);
play_rest(REST4);
// while(1) : 무한 루프
play_note(MIG, NOTE4);
play_note(MIG, NOTE4);
play_note(MIA, NOTE4);
play_note(MIA, NOTE4);
play_note(MIG, NOTE4);
play_note(MIG, NOTE4);
play_note(MIE, NOTE4);
play_rest(REST4);
play_note(MIG, NOTE4);
play_note(MIE, NOTE4);
play_note(MID, NOTE4);
play_note(MIE, NOTE4);
play_note(MIC, NOTE2D);
play_rest(REST4);
delay_ms(1000);
}
}
시스템및센서네트워크연구실
16
void play_note(unsigned int sound, unsigned int note)
{
OCR1A = sound;
TCNT1 = 0x0000;
TCCR1A = 0b01000000;
TCCR1B = 0b00001010;
// COM1A1,A0(7,6)-01, mode 4 - CTC모드 / OCR1A (WGM11,10 - 00)
// mode 4(WGM13,12 - 01), 프리스케일 = 8
delay_ms(note * tempo * 7);
TCCR1B = 0b00001000;
// speaker off
}
void play_rest(unsigned int rest)
{
delay_ms(rest * tempo * 7);
}
시스템및센서네트워크연구실
17
Speaker – 전자 음향 발생
전화벨 음향
320Hz
(25ms)
480Hz
(25ms)
320Hz
(25ms)
320Hz
(25ms)
480Hz
(25ms)
1초 계속
1초 정지
480Hz
(25ms)
1초 계속
119 구급차 소리
480Hz
(500ms)
360Hz
(500ms)
480Hz
(500ms)
360Hz
(500ms)
무한정 반복
시스템및센서네트워크연구실
18
실습 2
// 전화벨 음향
TCCR1B = 0b00001000;
delay_ms(1000);
}
void main(void)
{
unsigned int i=0;
DDRB = 0b00100000;
// CS – 000, speaker off
}
// PB5(OC1A) 출력 설정
TCCR1A = 0b01000000; // COM1A1,A0(7,6)-01, mode 4 - CTC모드 / OCR1A (WGM11,10 - 00)
TCCR1B = 0b00001010; // mode 4(WGM13,12 - 01), 프리스케일 = 8
delay_ms(50);
while(1){
// while(1) : 무한 루프
for(i=0; i<=20; i++) {
TCCR1B = 0b00001010; // CS – 8분주, speaker on
OCR1A = 3124;
delay_ms(25);
// 1M / (1+3124) = 320
OCR1A = 2082;
delay_ms(25);
// 1M / (1+2082) = 480
}
시스템및센서네트워크연구실
19
실습 3
// 119 구급차 음향
TCCR1B = 0b00001000;
delay_ms(1000);
void main(void)
{
unsigned int i=0;
DDRB = 0b00100000;
// CS – 000, speaker off
}
}
// PB5(OC1A) 출력 설정
TCCR1A = 0b01000000; // COM1A1,A0(7,6)-01, mode 4 - CTC모드 / OCR1A (WGM11,10 - 00)
TCCR1B = 0b00001010; // mode 4(WGM13,12 - 01), 프리스케일 = 8
delay_ms(50);
while(1){
// while(1) : 무한 루프
for(i=0; i<5; i++) {
TCCR1B = 0b00001010; // CS – 8, speaker on
OCR1A = 2082;
delay_ms(500);
// 1M / (1+2082) = 480
OCR1A = 2777;
delay_ms(500);
// 1M / (1+2777) = 360
}
시스템및센서네트워크연구실
20
Reset
리셋
리셋이 걸리는 동안 모든 I/O 레지스터는 초기 값으로 설정
프로그램은 처음부터 새로 실행됨
ATmeg1a6의 리셋 소스
Power-on reset
• 전원전압 Vcc가 power-on reset의 임계전압 Vpot보다 낮을 때 발생
External reset
• /RESET 핀에 1.5us 이상의 low 신호가 입력되면 발생
Watchdog reset
• 워치독 타이머가 타임아웃이 될 때 발생
Brown-out reset
• Brown-out 검출기가 enable되어 있고 brown-out 임계전압 Vbot보다 낮을 때 발
생
시스템및센서네트워크연구실
21
Watchdog timer
워치독 타이머의 특징
기능
• 시스템이 프로그램의 착오로 무한 루프에 들어가거나 또는 기계 고장으로 휴
지 상태로 되는 것을 방지하기 위해 프로그램에 의해 설정된 타이머로서 주
어진 일정 시간이 경과하면 워치독 리셋이 발생
• 워치독 타이머를 동작시키면, 프로그래머가 주기적으로 워치독 타이머의 값
을 0으로 리셋시켜야 함. 그렇지 않을 경우, uC가 이상 동작한다고 판단하고,
워치독 타이머가 직접 uC를 H/W 리셋시켜 버림
동작
• 별도의 1MHz 내장 발진기로부터 클럭을 공급받아 동작
• 워치독 타이머 프리스케일러에 의하여 워치독 타이머 리셋의 주기가 설정
• 워치독 타이머 리셋은 WDR 명령에 의해 이루어짐
• 워치독 타이머 리셋없이 리셋 주기가 끝나면 uC는 H/W 리셋됨
시스템및센서네트워크연구실
22
Watchdog timer 관련 IO 레지스터
WDTCR(watchdog timer control register)
bit 4 - WDCE : watchdog change enable
• WDE 비트를 제어하기 전에 셋시켜야 함
• 한번 셋되면, 하드웨어적으로 4클럭 사이클 후에 자동 클리어됨
bit 3 – WDE : watchdog enable
• 셋 되면 워치독 타이머의 기능이 인에이블됨
bit 2:0 – WDP: watchdog prescaler
• 워치독 타이머의 프리스케일
동작 결정
시스템및센서네트워크연구실
23
실습 4
워치독 타이머 리셋 명령 실행
워치독 리셋 주기를 약 0.95초로 설정하고,
타이머/카운터1의 오버플로우 주기를 64분주로 하여 0.26초마다 인터럽트를 발
생시키도록 함
타이머/카운터1의 오버플로우 인터럽트가 발생될 때마다 워치독 타이머를 리셋
(어셈블러 wdr 명령)하여 LED 순차 점멸이 정상적으로 동작하도록 프로그램 작
성
워치독 타이머의 리셋 발생 조건
1. 타이머 오버플로우가 발생되지 않고, 1초가 지나가면, 자동으로 리셋됨
2. 리셋 명령을 사용하는 경우 리셋됨 (리셋 버튼)
레지스터
• WDTCR = 0b00011000
WDTCE(4) = 1, WDE(3) = 1
• WDTCR = 0b00001110
WDE(3) = 1, WDP(2:0) =110 (1024 : 1.0us)
리셋 명령
• #asm (“wdr”)
시스템및센서네트워크연구실
-> 어셈블리 명령어를 C에서 사용할 수 있게 함
24
// 타이머/카운터 오버플로 1 서비스 루틴
#include <mega128.h>
#include <delay.h>
// (1/16us) * 64 * 65536 = 0.26s
interrupt [TIM1_OVF] void timer_int1(void)
char led = 0xFE;
void main(void)
{
DDRC = 0xFF;
PORTC = led;
{
// LED 순차 점멸
led <<= 1;
// 포트 C 출력으로 설정
// 포트 C에 초기값 출력
// 타이머/카운터1 오버플로 인터럽트 초기화
TIMSK = 0x04;
// TOIE1(2) = '1'
TCCR1A = 0x00;
// WGM10(1,0):00, normal mode
TCCR1B = 0x03;
// WGM32(4,3):00, CS(2-0):011 (64분주)
TCNT1 = 0x0000;
// 타이머/카운터1 레지스터 초기값
led |= 0x01;
if(led == 0xFF) led = 0xFE;
PORTC = led;
#asm ("wdr")
// 워치-독 타이머 리셋
}
// #asm (“wdr”)을 제거하고 나서 동작 확인 !
// 워치독 타이머 초기화
WDTCR = 0b00011000;
WDTCR = 0b00001110;
// WDTCE(4) =1, WDE(3) = 1
// WDE(3) = 1, WDP = 110 (1024 : 1.0s)
SREG = 0x80;
// 전역 인터럽트 인에이블 비트 I 셋.
while(1);
// 무한 루프
// 제거하면, 워치독 타이머를 리셋시키지 못하므로,
// 1초가 지난 후에 uC가 H/W 리셋되어 버림
}
시스템및센서네트워크연구실
25
Sleep
Sleep mode
AVR 내에서 사용하지 않는 주변장치를 차단하여 전원을 절약하는 기능
다양한 Sleep mode를 지원하여 사용자가 필요한 모듈만 선택하게 해 줌
Sleep mode에 있는 동안 enable된 인터럽트가 발생하면 sleep mode로부터 해제됨
주요 모드
Idle mode
• MCU의 동작은 정지
• SPI, TWI, USART, 아날로그 비교기, 타이머/카운터, 워치독, ADC, 인터럽트
는 동작
Power-down mode
• 외부 발진기 정지
• 외부 인터럽트, TWI, 워치독은 동작
• 외부 리셋, 워치독 리셋, 외부 인터럽트 등에 의해서만 해제 가능
시스템및센서네트워크연구실
26
Sleep mode 관련 IO 레지스터
MCUCR
bit 5 : SE (sleep mode enable)
• 1일 때 sleep mode enable
• 슬립 모드에 들어갈 시점에 #asm (“SLEEP”) 명령 사용
bit 4, 3, 2: SM2, 1, 0 (sleep model select)
• 000 – idle mode
• 010 – power-down mode
시스템및센서네트워크연구실
27
실습 5
// LED를 한번 왕복 쉬프트시킨 후 sleep 모드로 들어감
// SW1을 누르면 sleep 모드에서 해제된 후, 다시 한번 왕복 쉬프트시킴
char led = 0xFE;
void main(void)
{
DDRC = 0xFF;
// DDRC : 포트 방향 설정 레지스터
MCUCR = 0b00100000;
DDRD = 0b00000000; // PD0, PD1 입력 설정 (SW1, SW2)
EIMSK = 0b00000011; // 외부 인터럽트0, 1 인에이블
EICRA = 0b00001010; // 외부 인터럽트0, 1 하강 에지
SREG = 0b10000000; // 전역 인터럽트 인에이블 비트 셋
PORTC = led;
while(led != 0b11111110) {
delay_ms(500);
led >>= 1;
led |= 0b10000000;
PORTC = led;
}
}
}
// 외부 인터럽트0 서비스 루틴
interrupt [EXT_INT0] void external_int0(void)
{
}
while(1){
// while(1) : 무한 루프
while(led != 0b01111111) {
delay_ms(500);
led <<= 1;
led |= 0b00000001;
PORTC = led;
}
#asm ("SLEEP")
시스템및센서네트워크연구실
28
실습 6
// SW를 누르고 있을 때 알람 발생 및 LCD에 ‘경고’ 출력하고 깜빡거림
// Sleep mode 적용
// 외부 인터럽트0 서비스 루틴
interrupt [EXT_INT0] void external_int0(void)
{
TCCR1B = 0b00001010; // CS – 010
OCR1A = 2082;
void warn_display(void);
void safe_display(void);
// 1M / (1+2082) = 480
warn_display();
delay_ms(500);
void main(void)
{
DDRB = 0b00100000;
// PB5(OC1A) 출력 설정
TCCR1A = 0b01000000; // COM1A1,A0(7,6)-01, mode 4 - CTC모드
// OCR1A (WGM11,10 - 00)
TCCR1B = 0b00001010; // mode 4(WGM13,12 - 01), 프리스케일 = 8
OCR1A = 2777;
// 1M / (1+2777) = 360
Command(CLEAR);
delay_ms(500);
}
DDRD = 0b00000000;
// PD0, PD1 입력 설정 (SW1, SW2)
EIMSK = 0b00000011; // 외부 인터럽트0, 1 인에이블
EICRA = 0b00000000;
// 외부 인터럽트0, 1 레벨 트리거
MCUCR = 0b00100000;
SREG = 0b10000000;
// 전역 인터럽트 인에이블 비트 셋
void warn_display(void)
{
Command(HOME);
LCD_String(“Warning!”);
}
LCD_init();
void safe_display(void)
{
Command(HOME);
LCD_String(“Safe”);
}
while(1) {
// while(1) : 무한 루프
TCCR1B = 0b00010000; // speaker off
safe_display();
#asm (“SLEEP”);
}
}
시스템및센서네트워크연구실
29