AVR单片机设计电子琴程序

更新时间:2023-06-02 14:25:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

电子琴的c语言程序

AVR单片机设计电子琴程序

//-----------------------------------------------------------------

// 名称: 多首电子音乐的选播

//-----------------------------------------------------------------

// 说明: 本例运行时,每次按下K1将切换播放下一首电子音乐,对应的

// LED指示灯将被点亮.

//

//-----------------------------------------------------------------

#define F_CPU 8000000UL //8M晶振

#include <iom16v.h>

#include <macros.h>

#define uchar unsigned char

#define uint unsigned int

//指示灯控制(任一LED点亮时都会关闭其他指示灯)

#define LED1_ON() PORTA=0xFE

#define LED2_ON() PORTA=0xF7

#define LED3_ON() PORTA=0xBF

#define LED4_ON() PORTA=0x7F

//===========================================================

//当前按键序号,该矩阵中序号范围为0-15,16表示无按键

uchar KeyNo=16;

//C调音符频率表(部分)

uint TONE_FRQ[]=

{0,262*8,294*8,330*8,349*8,392*8,440*8,494*8,523*8,587*8,659*8,698*8,784*8,880*8,988*8,1046*8};

//共阳数码管段码表(0~F)

uchar SEG_CODE[]=

{

0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, //0 1 2 3 4 5 6 7

0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E //8 9 A B C D E F

};

//音符延时表,它们分别对应于0~15号音符的输出频率

uint Tone_Delay_Table[] =

{

64021,64103,64260,64400,64524,64580,64684,64777,

64820,64898,64968,65030,65058,65110,65157,65178

};

//第一段(Tone为音符,Time为节拍)

uchar Music1_Tone[] =

{ 3,5,5,3,2,1,2,3,5,3,2,3,5,5,3,2,1,2,3,2,1,1,0xFF };

电子琴的c语言程序

uchar Music1_Time[] =

{ 2,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1,0xFF };

//第二段

uchar Music2_Tone[] =

{ 1,3,3,3,3,5,4,2,5,3,7,6,5,5,7,4,4,3,6,7,2,1,0xFF };

uchar Music2_Time[] =

{ 2,1,1,2,1,1,1,2,1,1,3,2,1,1,2,4,1,1,2,1,1,1,0xFF };

//第三段

uchar Music3_Tone[] =

{ 0,1,2,3,4,5,5,6,7,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0xFF};

uchar Music3_Time[] =

{ 1,1,1,1,1,1,1,1,1,1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1,1,1,1,0xFF};

//第四段1/2拍为底

uchar Music4_Tone[] =

{ 1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,4,3,1,5,6,5,4,3,1,1,5,1,1,5,1,0xFF };

uchar Music4_Time[] =

{ 2,1,1,1,2,1,1,1,2,1,1,2,1,1,3,0.5,0.25,0.5,0.25,1,1,0.5,0.25,0.5,1,1,1,1,3,1,1,3,0xFF }; //======================================

uchar *Music_Tone_Ptr[]={Music1_Tone,Music2_Tone,Music3_Tone,Music4_Tone}, *Music_Time_Ptr[]={Music1_Time,Music2_Time,Music3_Time,Music4_Time}; //音乐片段索引,音符索引

uint Tone_Idx = 0;

//从当前数组中取音符的位置

uint i = 0,j=1,Music_Idx = 0;

//暂停控制

uint FALSE = 0, TRUE = 1, Pause = 1;

//=================================================

void delay_1ms(void)

{

uint i;

for(i=1;i<(uint)(F_CPU*143-2);i++)

;

}

void delay(unsigned int n)

{

unsigned int i;

for(i=0;i<n;i++)

delay_1ms();

}

//=================================================

电子琴的c语言程序

//-----------------------------------------------------------------

// 判断键盘矩阵是否有键按下

//-----------------------------------------------------------------

uchar KeyMatrix_Down()

{

//高4位输出,低4位输入,高4位先置0,放入4行

DDRB=0XF0;

PORTB=0X0F;

delay(1);

return PINB!=0x0f? 1:0;

}

//-----------------------------------------------------------------

// 键盘矩阵扫描子程序

//-----------------------------------------------------------------

void Keys_Scan()

{

//在判断是否有按键按下的函数KeyMatrix_Down中,

//高4位输出,低4位输入,高4位先置0,放入4行

//按键后00001111将变成0000XXXX,X中有1个为0,3个为1

//下面判断按键发生于0~3列中的哪一列

switch(PINB)

{

case 0B00001110: KeyNo=0; break;

case 0B00001101: KeyNo=1; break;

case 0B00001011: KeyNo=2; break;

case 0B00000111: KeyNo=3; break;

default:KeyNo=0xFF;

}

//高4位输入,低4位输出,低4位先置0,放入4列

DDRB=0x0F;

PORTB=0xF0;

delay(1);

//按键后11110000将变成XXXX0000,X中有1个为0,3个为1

//下面对0~3行分别附加起始值0、4、8、12

switch(PINB)

{

case 0B11100000: KeyNo+=0; break;

case 0B11010000: KeyNo+=4; break;

case 0B10110000: KeyNo+=8; break;

电子琴的c语言程序

case 0B01110000: KeyNo+=12; break;

default: KeyNo= 0xFF;

}

}

//-----------------------------------------------------------------

// 主程序

//-----------------------------------------------------------------

int main()

{//矩阵键盘

DDRB=0xFF;

PORTB=0xFF;

//LED灯

DDRA=0xFF;

PORTA=0xFF; //LED初始时全部关闭

//数码管

DDRC=0xFF;

PORTC=0xBF; //数码管初始显示“-”

DDRD|=BIT(PD7);

PORTD&=~BIT(PD7);

//外部中断

DDRD=~(BIT(PD2)|BIT(PD3)); //中断引脚设为输入

PORTD=BIT(PD2)|BIT(PD3); //中断输入引脚设为内部上拉

MCUCR=0x82; //INT0,INT1均为下降沿触发

GICR=BIT(INT0)|BIT(INT1); //INT0,INT1中断许可

TCCR1A=0x00; //TC1与OC1A不连接,禁止PWM功能

TCCR1B=0x09;//T1预分频:1,CTC模式(比较匹配时TC1自动清零?

SREG=0x80; //开中断

while(1)

{

if(KeyMatrix_Down()==0)

电子琴的c语言程序

{

//暂停控制

if(Pause)

{

continue;

}

TCCR1B=0x01; //T1预分频:1

Tone_Idx=Music_Tone_Ptr[Music_Idx][i];

if(Tone_Idx==0xFF)

{

//delay(2000); 每段音乐播放结束后停顿一段时间

delay(200);

i=0; //回到当前音乐片段的第0个音符

continue; //继续播放

}

//TIMSK|=BIT(TOIE1);

TIMSK=BIT(TOIE1); //启动定时器溢出中断,开始输出当前音符

//音符输出时长(节拍)由各段音乐中的MusicX_Time数组中对应音符的延时值决定 delay(Music_Time_Ptr[Music_Idx][Tone_Idx]*200/26);

//TIMSK&=~BIT(TOIE1);

TIMSK=0x00; //禁止定时器溢出中断,停止当前音符输出

i++; //取音符位置变量i递增

} else//(KeyMatrix_Down()) { if(Pause==0)

{continue;

}

TCCR1B=0x09;//T1预分频:1,CTC模式(比较匹配时TC1自动清零)

if(KeyMatrix_Down()) //有键按下则扫描按键

{Keys_Scan();

}

else continue;

if(KeyNo==0 || KeyNo>16) //按键无效或按下0键则继续

continue;

PORTC=SEG_CODE[KeyNo]; //数码管显示键值

OCR1A=F_CPU/2/TONE_FRQ[KeyNo];

TCNT1=0;TIMSK|= BIT(OCIE1A);

while(KeyMatrix_Down()); //等待释放

//PORTD=0x7F; TIMSK &=~BIT(OCIE1A);

电子琴的c语言程序

}

}

}

//----------------------------------------------------------------- // T1定时器溢出中断控制音符输出

//----------------------------------------------------------------- #pragma interrupt_handler timer1_ovf_isr:9

void timer1_ovf_isr(void)

{

//如果遇到音乐片段结束标志则返回

if(Tone_Idx==0xFF)return;

//根据Tone_Delay_Table[Tone_Idx]设置定时初值 //该初值即决定了输出的频率

TCNT1=Tone_Delay_Table[Tone_Idx];

PORTD^=BIT(PD7);

}

//----------------------------------------------------------------- // 按键触发INT0中断,控制音乐段切换

//----------------------------------------------------------------- #pragma interrupt_handler int0_isr:2

void int0_isr(void)

{

TIMSK=0x00; //禁止定时器溢出中断,音符输出停止 //切换到另一段音乐

if(Music_Idx==3)Music_Idx=0;

else Music_Idx++;

//切换到新的一段音乐后总是从其第0个音符开始输出 i=0;

//打开对应的指示灯

switch(Music_Idx)

{

case 0:LED1_ON();PORTC=SEG_CODE[1]; break; case 1:LED2_ON(); PORTC=SEG_CODE[2];break; case 2:LED3_ON(); PORTC=SEG_CODE[3];break; case 3:LED4_ON(); PORTC=SEG_CODE[4];break; }

delay(10); //在开始另一段音乐输出前暂停1s

}

//----------------------------------------------------------------- // 播放启动/停止控制

电子琴的c语言程序

//----------------------------------------------------------------- #pragma interrupt_handler int1_isr:3

void int1_isr(void)

{

Pause= !Pause;

if(Pause)

{

PORTC=0xFF; //如果停止则关闭数码管

PORTA=0xFF;//如果停止则关闭LED灯

TIMSK=0x00; //停止音符输出

}

else

{

//否则打开对应指示灯

switch(Music_Idx)

{

case 0:LED1_ON();PORTC=SEG_CODE[1]; break; case 1:LED2_ON(); PORTC=SEG_CODE[2];break; case 2:LED3_ON(); PORTC=SEG_CODE[3];break; case 3:LED4_ON(); PORTC=SEG_CODE[4];break; }

TIMSK=BIT(TOIE1);

}

}

// T1定时器比较匹配中断程序,控制音符频率输出 //----------------------------------------------------------------- #pragma interrupt_handler timer1_compa_isr:7 void timer1_compa_isr(void)

{

PORTD^=BIT(PD7);

}

本文来源:https://www.bwwdw.com/article/8z01.html

Top