BASIC4MCU | 질문게시판 | 답변 : 전화 벨소리랑 FND 코드를 합칠 수 있나요?
페이지 정보
작성자 master 작성일2022-11-20 20:32 조회3,590회 댓글4건본문
벨소리와 세그먼트 구동의 시간 동기를 맞춰야 합니다.
for(i=0;i<20;i++){ // (24.96ms+24.96ms)*20=998.4msfor(j=0;j<12;j++){ PORTB=0x10; _delay_ms(1.04); PORTB=0x00; _delay_ms(1.04); } // 2.08*12=24.96msfor(j=0;j< 8;j++){ PORTB=0x10; _delay_ms(1.56); PORTB=0x00; _delay_ms(1.56); } // 3.12*8=24.96ms}_delay_ms(2000);두 개의 주파수가 약25ms씩 교대로 울리고이 것을 20번 반복해서 1초정도 울린 후2초동안 쉬는군요전체시간은 3초for(digit=0;digit<17;digit++){ // 500ms*17=8500msfor(del=0;del<25;del++){ // 20ms*25=500msfor(sel=0;sel<4;sel++){ // 5ms*4=20msPORTC=fnd[digit+sel]; PORTG=fnd_sel[sel]; _delay_ms(5);}}}0.5초마다 자리를 이동하면서 총 8.5초 동안 전화번호를 표시하고 있습니다.이 시간을 9초로 늘리고 전화벨 소리를 3번 울리면 되겠군요//#include <avr/io.h>#define F_CPU 16000000UL#include <util/delay.h>//unsigned char fnd[]={0x00,0x00,0x00,0x3F,0x06,0x3F,0x40,0x06,0x5B,0x4F,0x66,0x40,0x6D,0x7D,0x27,0x7F,0x00,0x00,0x00,0x00,0x00};//010-1234-5678unsigned char fnd_sel[4]={0x08,0x04,0x02,0x01}; //좌->우로 하고자 한다면 반대로 설정(08,04...)//int main(){int sel,digit,del,j;char togle,c;DDRB=0x10; DDRG=0x0F; DDRC=0xFF;while(1){togle=c=0;for(digit=0;digit<18;digit++){ // 499.2ms*18=8985.6msfor(del=0;del<20;del++){ // 24.96ms*20=499.2mstogle^=1;if(t){for(j=0;j<6;j++){ // 4.16ms*6=24.96msfor(sel=0;sel<4;sel++){ PORTC=fnd[digit+sel]; PORTG=fnd_sel[sel]; if(c<2)PORTB^=0x10; _delay_ms(1.04); } // 1.04ms*4=4.16ms}}else{for(j=0;j<4;j++){ // 6.24ms*4=24.96msfor(sel=0;sel<4;sel++){ PORTC=fnd[digit+sel]; PORTG=fnd_sel[sel]; if(c<2)PORTB^=0x10; _delay_ms(1.56); } // 1.56ms*4=6.24ms}}}if(++c>5)c=0; // 0~1 = 벨소리 // 2~5 = 무음}}return 0;}
댓글 4
조회수 3,590master님의 댓글
master 작성일
만약 시간동기를 맞추기 어렵다면 타이머 인터럽트를 사용해서 구동해야 합니다.
128은 타이머가 4개이므로
하나만 타이머에서 구동해도 되고
둘 다 각각의 타이머로 구동해도 됩니다.
또,
타이머 모드 중에는 자동으로 펄스를 출력해주는 기능이 있습니다.
CTC 토글모드
이 기능을 사용하면 코드가 한결 편해집니다.
PB4는 OC1A 핀이므로 타이머1을 사용하면 됩니다.
TCCR1A=0x40; TCCR1B=9; TCCR1C=0x80; OCR1A=15999; // 2ms
TCCR1A=0x40; TCCR1B=9; TCCR1C=0x80; OCR1A=19999; // 2.5ms
TCCR1A=0x40; TCCR1B=9; TCCR1C=0x80; OCR1A=23999; // 3ms
TCCR1A=0x40; TCCR1B=9; TCCR1C=0x80; OCR1A=31999; // 4ms
1.04ms와 1.56ms는 이 범위에 들어있으니 계산을 해보죠
1.04ms=961.5384615384615Hz
16000000/1/961.5384615384615=16640, OCR1A는 1적은 값을 넣어야 하므로 OCR1A=16639;
1.56ms=641.025641025641Hz
16000000/1/641.025641025641=24960, OCR1A는 1적은 값을 넣어야 하므로 OCR1A=24959;
설정을 정리하면
TCCR1A=0x40; TCCR1B=9; TCCR1C=0x80; OCR1A=16639; // 1.04ms * 2 = 2.08ms = 480.8Hz
TCCR1A=0x40; TCCR1B=9; TCCR1C=0x80; OCR1A=24959; // 1.56ms * 2 = 3.12ms = 320.5Hz
OCR1A값만 변경하면 PB4로 펄스가 출력됩니다.
master님의 댓글
master 작성일
부저 출력만 타이머 사용하는 것으로 적어보죠
DDRB=0x10;
TCCR1A=0x40; TCCR1B=9; TCCR1C=0x80; OCR1A=16639; // 1.04ms * 2 = 2.08ms = 480.8Hz
while(1){
for(j=0;j<20;j++){
TCNT1=0; OCR1A=16639; _delay_ms(25); // 1.04ms * 2 = 2.08ms = 480.8Hz
TCNT1=0; OCR1A=24959; _delay_ms(25); // 1.56ms * 2 = 3.12ms = 320.5Hz
}
_delay_ms(2000);
}
}
이 것도 타이머로 옮긴다면 25ms 인터벌의 타이머를 설정해서 출력하면 되겠죠
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL // 16 MHz
#include <util/delay.h>
//
ISR(TIMER3_COMPA_vect){ // 25ms
static char c=0,togle=0;
togle^=1;
if(togle){ TCNT1=0; OCR1A=16639; } // 1.04ms * 2 = 2.08ms = 480.8Hz
else { TCNT1=0; OCR1A=24959; } // 1.56ms * 2 = 3.12ms = 320.5Hz
//
if(++c>=120){ c=0; TCCR1A=0x40; } // 25ms*120=3000ms
if(c>=20)TCCR1A=0x00; // 25ms*20=500ms // 타이머1 OFF
}
//
int main(){
DDRB=0x10;
TCCR1A=0x40; TCCR1B=0x09; TCCR1C=0x80;
TCCR3B=0x02; TCNT3=15536; ETIMSK=0x04; SREG=0x80; //25ms
while(1){}
}
이제막시작님의 댓글
이제막시작 작성일
시간을 내주어 답변을 해주셔서 감사드립니다. 근데 혹시 써주신 코드에 t값이 선언 안돼 있는데 그냥 제가 선언하고 돌려도 돼겠죠?
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
//
unsigned char fnd[]={0x00,0x00,0x00,0x3F,0x06,0x3F,0x40,0x06,0x5B,0x4F,0x66,0x40,0x6D,0x7D,0x27,0x7F,0x00,0x00,0x00,0x00,0x00};
//010-1234-5678
unsigned char fnd_sel[4]={0x08,0x04,0x02,0x01}; //좌->우로 하고자 한다면 반대로 설정(08,04...)
//
int main(){
int sel,digit,del,j;
char togle,c;
DDRB=0x10; DDRG=0x0F; DDRC=0xFF;
while(1){
togle=c=0;
for(digit=0;digit<18;digit++){ // 499.2ms*18=8985.6ms
for(del=0;del<20;del++){ // 24.96ms*20=499.2ms
togle^=1;
if(t){ <------------------------------------------------------------------------------여기 t값입니다.
for(j=0;j<6;j++){ // 4.16ms*6=24.96ms
for(sel=0;sel<4;sel++){ PORTC=fnd[digit+sel]; PORTG=fnd_sel[sel]; if(c<2)PORTB^=0x10; _delay_ms(1.04); } // 1.04ms*4=4.16ms
}
}
else{
for(j=0;j<4;j++){ // 6.24ms*4=24.96ms
for(sel=0;sel<4;sel++){ PORTC=fnd[digit+sel]; PORTG=fnd_sel[sel]; if(c<2)PORTB^=0x10; _delay_ms(1.56); } // 1.56ms*4=6.24ms
}
}
}
if(++c>5)c=0; // 0~1 = 벨소리 // 2~5 = 무음
}
}
return 0;
}
master님의 댓글
master
if(t){
if(togle){