BASIC4MCU | 질문게시판 | 답변 : ATMEGA128 노래 속도
페이지 정보
작성자 master 작성일2019-12-14 20:54 조회3,837회 댓글0건
https://www.basic4mcu.com/bbs/board.php?bo_table=gac&wr_id=11175
본문
// MCU BASIC: https://www.basic4mcu.com// DateTime : 2019-12-14 오후 8:54:18// by Ok-Hyun Park//#include <io.h>//typedef enum{la_0,lasharp_0,si_0,do_1,dosharp_1,re_1,resharp_1,mi_1,fa_1,fasharp_1,sol_1,solsharp_1,la_1,lasharp_1,si_1,do_2,dosharp_2,re_2,resharp_2,mi_2,fa_2,fasharp_2,sol_2,solsharp_2,la_2,lasharp_2,si_2,do_3,dosharp_3,re_3,resharp_3,mi_3,fa_3,fasharp_3,sol_3,solsharp_3,la_3,lasharp_3,si_3,rest}melody_code;//typedef struct{melody_code tone;float leng;}MUSIC_CODE;//#define LENGTH 39//flash MUSIC_CODE musicCode1[]={{ do_2,1},{ do_2,0.5},{ do_2,0.5},{ do_2,1},{ do_2,1},//곰세마리가{ mi_2,1},{ sol_2,0.5},{ sol_2,0.5},{ mi_2,1},{ do_2,1},//한 집에 있어{ sol_2,0.5},{ sol_2,0.5},{ mi_2,1},{ sol_2,0.5},{ sol_2,0.5},{ mi_2,1},{ do_2,1},{ do_2,1},{ do_2,2},// 아빠곰 엄마곰 애기곰{ sol_2,1},{ sol_2,1},{ mi_2,1},{ do_2,1},{ sol_2,1},{ sol_2,1},{ sol_2,2},//아빠곰은 뚱뚱해{ sol_2,1},{ sol_2,1},{ mi_2,1},{ do_2,1},{ sol_2,1},{ sol_2,1},{ sol_2,2},//엄마곰은 날씬해{ sol_2,1},{ sol_2,1},{ mi_2,1},{ do_2,1},{ sol_2,0.5},{ sol_2,0.5},{ sol_2,0.5},{ la_2,0.5},{ sol_2,2},//애기곰은 너무귀여워{ do_3,1},{ sol_2,1},{ do_3,1},{ sol_2,1},{ mi_2,1},{ re_2,1},{ do_2,2} //으쓱 으쓱 잘한다{ 0,0}};int a=0;int baseToneStep[8]={0,2,3,5,7,8,10,12};//#define LA_FREQ 110.#define MULTIPLICATION_FACTOR 1.059463//unsigned int cs[8]={0,1,8,32,64,128,256,1024};//unsigned char tccr0_set[LENGTH]; // tone을 만들기 위한 TCCR0 값unsigned char ocr0_set[LENGTH]; // tone을 만들기 위한 OCR0 값unsigned char i;unsigned int us;unsigned long time10Millisec;unsigned char fndDispHoldVal[4]={ 1,2,3,4};unsigned char fndHexCode[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x27,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};//interrupt[TIM1_COMPA]void Timer1A_cmp_isr(void){++time10Millisec; }//void StartTimer(){time10Millisec=0; TCNT1=0; TIFR=(1<<OCF1A); TIMSK|=(1<<OCIE1A); TCCR1B|=(1<<CS10); TCCR1B|=(1<<CS11);}//void StopTimer(){ TIMSK&=~(1<<OCIE1A); TCCR1B&=~(1<<CS10); TCCR1B&=~(1<<CS11); }//void RestartTimer(){ TIMSK|=(1<<OCIE1A); TCCR1B|=(1<<CS10); TCCR1B|=(1<<CS11); }//---------------------------------------------------------// 음계 ‘라’로 부터 3 옥타브에 걸친 음의 tone을 만들기 위하여 필요한// 타이머 0의 clock selection 필드 값과 OCR0 값을 미리 준비해 둠//---------------------------------------------------------void MakeTone(){float reqFreq,num,freq,reqClks; int i,j,steps;reqFreq=LA_FREQ; // ‘라’ 음의 기준 주파수로 부터 시작함.for(i=0; i<LENGTH; i++){ // 24개 tonereqFreq=LA_FREQ;// 기준 주파수로 부터 몇 단계 떨어져 있는가?steps=i;// tone의 주파수 계산for(j=0; j<steps; j++)reqFreq*=MULTIPLICATION_FACTOR;freq=reqFreq*2; // toggle 함에 따라서 카운터 주파수는 2배가 되어야 함// 한 개의 주기에 16MHz 클럭이 몇 개가 있느가?reqClks=(16.0E6/freq);// 가능한 최대 크기의 OCR0 값을 만들 수 있도록 clock selection 선택for(j=1; j<8; j++){ // 각 prescale 에 대해num=reqClks /((float)cs[j]);if(num<=256.){ tccr0_set[i]=j|0b00011000; ocr0_set[i]=((unsigned char)num)-1; break; } // CTC 모드에서 toggle 출력 // TCCR0 값 찾기 // OCR0 값 찾기}}}//---------------------------------------------------------// 실제 음 tone을 만들기 위하여,TCCR0와 OCR0 에 갓을 써 넣음//---------------------------------------------------------/void SetTone(unsigned char n){ TCCR0=tccr0_set[n]; OCR0=ocr0_set[n]; DDRB.4=1; } // 부저에 연결된 핀을 출력으로//---------------------------------------------------------// 100 millisec 마다 CTC 인터럽트가 발생하도록 함.//---------------------------------------------------------/void InitTimer3(){TCCR3B=(1<<WGM32)|(1<<CS31); // CTC mode // 1/8OCR3AH=19999>>8; OCR3AL=19999&0xFF; // OCR3A=19999ETIFR=(1<<OCF3A); // ETIFR의 OCF3A(비교일치 flag)을 클리어시킴ETIMSK|=(1<<OCIE3A); // 비교 일치 인터럽트 enable}//void ReSetTimer3(int a){switch(a){case 0: OCR3AH=19999>>8; OCR3AL=19999&0xFF; break;case 1: OCR3AH= 9999>>8; OCR3AL= 9999&0xFF; break;case 2: OCR3AH= 6666>>8; OCR3AL= 6666&0xFF; break;}}//---------------------------------------------------------// 타이머 3의 ISR,100 millisec 마다,시간변수 increment//---------------------------------------------------------unsigned char timer3Flag;unsigned int remainCnt;int seq;//interrupt[TIM3_COMPA]void Timer3A_cmp_isr(void){ timer3Flag++; } // 100 msec interval//---------------------------------------------------------// SW1 누르면 플레이 시작//---------------------------------------------------------interrupt[EXT_INT4]void ext4_isr(){if(++a>2)a=0;if(a==0){ PORTA=0xC2; }if(a==1){ PORTA=0x92; remainCnt=1; seq=0; StartTimer(); DDRB.4=1; }if(a==2){ PORTA=0xA2; }ReSetTimer3(a);}//---------------------------------------------------------// SW2 누르면 중단//---------------------------------------------------------interrupt[EXT_INT5]void ext5_isr(){if(++a>3)a=0;if(a==0){ PORTA=0x92; }if(a==1){ PORTA=0x94; }if(a==2){ remainCnt=0; PORTA=0x98; DDRB.4=0; StopTimer(); }if(a==3){ remainCnt=1; PORTA=0x91; DDRB.4=1; RestartTimer(); }}//void InitTimer1(){ TCCR1A=0; TCCR1B=(1<<WGM12); OCR1A=24999; }//#define T2_OCR 16000000.*0.005/1024.//void Timer2Init(){ TCCR2=(1<<WGM21)|(1<<CS22)|(1<<CS20); OCR2=(unsigned char)(T2_OCR)-1; TIMSK|=0x80; }//void InitFnd(){ DDRC=0xFF; DDRG|=0x0F; Timer2Init(); }//unsigned char fndOnVal[4]={0x01,0x02,0x04,0x08};//interrupt[TIM2_COMP]void Timer2_cmp_isr(void){static unsigned char currFndPos=0;PORTG=0x00;PORTC=fndDispHoldVal[currFndPos];if(currFndPos==1)PORTC|=0x80;PORTG=fndOnVal[currFndPos];currFndPos=(++currFndPos)%4;}//void main(){DDRA=0xFF;InitFnd();MakeTone();InitTimer1();InitTimer3();EICRB=0x0A; // falling edge에서 인터럽트 발생EIMSK=0x30; // SW1,SW2 인터럽트 enableSREG|=0x80; // 전체 인터럽트 enablewhile(1){if(timer3Flag){ timer3Flag=0; // every 100 millisecif(remainCnt){if (remainCnt==10){ DDRB.4=0; } // 끝나기 0.1 sec 전에 음 제거else if(remainCnt== 1){if(musicCode1[seq].leng!=0.0){SetTone(musicCode1[seq].tone);remainCnt=(unsigned int)(musicCode1[seq].leng*100.);++seq;}}}--remainCnt;us=time10Millisec;for(i=0; i<4; i++){ fndDispHoldVal[i]=fndHexCode[us%10]; us=us/10; }}}}
//void ReSetTimer3(int a){switch(a){case 0: OCR3AH=19999>>8; OCR3AL=19999&0xFF; break;case 1: OCR3AH= 9999>>8; OCR3AL= 9999&0xFF; break;case 2: OCR3AH= 6666>>8; OCR3AL= 6666&0xFF; break;}}
댓글 0
조회수 3,837등록된 댓글이 없습니다.