BASIC4MCU | 질문게시판 | 답변 : ADC를 통해 변환한 가변저항 값으로 피아노 연주하기 질문
페이지 정보
작성자 master 작성일2022-12-01 08:47 조회595회 댓글2건본문
#define F_CPU 16000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//
#define STOP 0
#define START 1
#define INIT 2
//
#define C1 523 // 도
#define D1 587 // 레
#define E1 659 // 미
#define F1 699 // 파
#define G1 784 // 솔
#define A1 880 // 라
#define B1 988 // 시
#define C2 C1*2 // 도
#define DLY_4 4
//
unsigned char mode_sel=0;
//
const unsigned char Segment_Data[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x27,0x7F,0x6F};
char COLUMN[4]={0,0,0,0};
//
unsigned char count_int=0;
unsigned int Seconds=0,Minutes=0,Hours=0;
//
int state=STOP;
int SHOW_NUMBER=0,SHOW_NUMBER12=0,SHOW_NUMBER34=0;
//
volatile int Doremi[8]={C1,D1,E1,F1,G1,A1,B1,C2};
volatile int Doremi_length[8]={DLY_4,DLY_4,DLY_4,DLY_4,DLY_4,DLY_4,DLY_4,DLY_4};
volatile unsigned char TIMERvalue=0xFF;
volatile int freq=1000,i,j;
//
unsigned int adc_data;
//---------------------------------------
void ShowDigit(int i,int digit){
PORTC=~(0x01<<digit);
PORTA=Segment_Data[i];
if(mode_sel==1 && digit==1)PORTA|=0x80;
}
//
void Show_Display(unsigned int number){
COLUMN[0]=(Minutes%100)/10;
COLUMN[1]=(Minutes%10);
COLUMN[2]=(Seconds%100)/10;
COLUMN[3]=(Seconds%10);
for(int i=0;i<4;i++){ ShowDigit(COLUMN[i],i); _delay_ms(2); }
}
//
void Show_stop_watch_Display(int number){
COLUMN[0]=number/1000;
COLUMN[1]=(number%1000)/100;
COLUMN[2]=(number%100)/10;
COLUMN[3]=(number%10);
for(int i=0;i<4;i++){ ShowDigit(COLUMN[i],i); _delay_ms(2); }
}
//
void mode0_clock(){
Show_Display(Seconds);
if(Seconds>=60){ Seconds=0;
if(++Minutes>=60){ Minutes=0; if(++Hours>=24)Hours=0; }
}
}
//
void Run(void){
switch(state){
case STOP : break;
case START: if(++SHOW_NUMBER34>99){ SHOW_NUMBER34=0; if(++SHOW_NUMBER12>99)SHOW_NUMBER12=0; } break;
case INIT : SHOW_NUMBER12=0,SHOW_NUMBER34=0,state=STOP; break;
}
}
//
void Shimpyo(int time){ for(int i=0;i<time;i++)_delay_ms(50); }
//
void Cutoff_Play(void){ _delay_ms(300); TIMERvalue=255; _delay_ms(20); }
//
void piano_up(void){
for(int i=0;i<8;i++){
freq=Doremi[i];
TIMERvalue=255-(1000000/(8*freq));
Shimpyo(Doremi_length[i]);
Cutoff_Play();
}
}
//
void piano_play(){
adc_data=ADC; // adc_data=ADCW; 컴파일러 버전에 따라서 다름
if(adc_data<128){
freq=Doremi[0];
TIMERvalue=255-(1000000/(8*freq));
Shimpyo(Doremi_length[0]);
Cutoff_Play();
}
}
//
void mode1_stop_watch(){
Run();
SHOW_NUMBER=SHOW_NUMBER12*100+SHOW_NUMBER34;
Show_stop_watch_Display(SHOW_NUMBER);
}
//
void mode2_piano(){ piano_up(); _delay_ms(1000); }
//
void mode3_piano_play(){ piano_play(); }
//
ISR(TIMER0_OVF_vect){
if(++count_int==244){ count_int=0; PORTG^=0x03; Seconds++; }
}
//
ISR(TIMER2_OVF_vect){
if(mode_sel==2){ TCNT2=TIMERvalue; PORTB^=0x10; }
}
//
ISR(INT0_vect){ if(++mode_sel>3)mode_sel=0; }
//
ISR(INT1_vect){
if(mode_sel==1){ if(state==STOP)state=START; else state=STOP; }
}
//
ISR(INT2_vect){ if(mode_sel==1)state=INIT; }
//
int main(void){
DDRA=0xff; DDRB=0x10; DDRC=0xff; DDRG=0x03;
TCCR0=0x06; TCCR2=0x04; TIMSK=0x41;
ADCSRA=0xE7;
EICRA=0x3F; EIMSK=0x07; SREG|=0x80;
while(1){
switch(mode_sel){
case 0: mode0_clock(); break;
case 1: mode1_stop_watch(); break;
case 2: mode2_piano(); break;
case 3: mode3_piano_play(); break;
default:mode0_clock(); break;
}
}
}
ADC 값 체크는 한 곳에서만 하고 있는 거죠?if(adc_data<128){이 체크로 음계를 어떻게 나누는지 모르겠지민코드를 정리 해드렸으니 디버깅 잘 하시기 바랍니다.긴 소스를 모드 이해햐서 수정을 해드리긴 시간상 어렵습니다.
댓글 2
조회수 595KHYDH님의 댓글
KHYDH 작성일바쁘신 와중에도 친절히 답변 달아주셔서 감사합니다!!
KHYDH님의 댓글
KHYDH 작성일정말 죄송하지만 특정 이유로 인해 혹시 글 삭제해주실 수 있을까요?? 감사하고 죄송합니다..