原理图:
(原文件名:2.jpg)
附送程序一份:
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit SPK = P3^6; //P3.6外接扬声器
uint FreqTemp;
unsigned char timer0h, timer0l, time;
unsignedchar code num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e};
//--------------------------------------
// 晶振采用11.0592MHz
// 频率-半周期数据表 高八位
code unsigned char FREQH[] = {
0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音1234567
0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, //1,2,3,4,5,6,7,i
0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 234567
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567
// 频率-半周期数据表 低八位
code unsigned char FREQL[] = {
0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音1234567
0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i
0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 234567
0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567
//按键发声代码
code unsigned char jianyin[] =
{1, 2, 3, 2, 2, 3, 3, 2, 3, 4, 2, 3, 5, 2, 3, 6, 2, 3, 7, 2, 3,
1, 3, 3, 2, 3, 3, 3, 3, 3, 4, 3, 3, 5, 3, 3, 6, 3, 3, 7, 3, 3};
//世上只有妈妈好数据表
code unsigned char sszymmh[] = {
6, 2, 3, 5, 2, 1, 3, 2, 2, 5, 2, 2, 1, 3, 2, 6, 2, 1, 5, 2, 1,
6, 2, 4, 3, 2, 2, 5, 2, 1, 6, 2, 1, 5, 2, 2, 3, 2, 2, 1, 2, 1,
6, 1, 1, 5, 2, 1, 3, 2, 1, 2, 2, 4, 2, 2, 3, 3, 2, 1, 5, 2, 2,
5, 2, 1, 6, 2, 1, 3, 2, 2, 2 ,2, 2, 1, 2, 4, 5, 2, 3, 3, 2, 1,
2, 2, 1, 1, 2, 1, 6, 1, 1, 1, 2, 1, 5, 1, 6, 0, 0, 0};
//生日快乐数据表
code unsigned char srkl[]={
5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2,
6,1,2, 4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4, 0,0,0};
//送别部分数据表
code unsigned char sb[] = {
5, 2, 2, 3, 2, 1, 5, 2, 1, 1, 3, 4, 6, 2, 2, 1, 3, 1, 6, 2, 1, 5, 2, 4, 0, 0, 0};//中断定义
void t0int() interrupt 1 //T0中断程序,控制发音的音调
{
TR0 = 0; //先关闭T0
SPK = !SPK; //输出方波, 发音
TH0 = timer0h; //下次的中断时间, 这个时间, 控制音调高低
TL0 = timer0l;
TR0 = 1; //启动T0
}
//延迟函数,即决定半拍数
void delay(unsigned char t) //延时程序,控制发音的时间长度
{
unsigned char t1;
unsigned long t2;
for(t1 = 0; t1 < t; t1++) //双重循环, 共延时t个半拍
for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音
TR0 = 0; //关闭T0, 停止发音
}
//演奏一个音符
void song()
{ TR0 = 0;
TH0 = timer0h; //控制音调
TL0 = timer0l;
TR0 = 1; //启动T0, 由T0输出方波去发音
delay(time); //控制时间长度
}
//生日快乐
void song1()
{
unsigned char k, i;
i = 0;
time = 1;
while(time)
{
k = srkl
+ 7 * srkl[i + 1] - 1; //第i个是音符, 第i+1个是第几个八度
timer0h = FREQH[k]; //从数据表中读出频率数值
timer0l = FREQL[k]; //实际上, 是定时的时间长度
time = srkl[i + 2]; //读出时间长度数值
i += 3;
song(); //发出一个音符
}
}
//世上只有妈妈好
void song2()
{unsigned char k, i;
i = 0;
time = 1;
while(time)
{
k = sszymmh + 7 * sszymmh[i + 1] - 1; //第i个是音符, 第i+1个是第几个八度
timer0h = FREQH[k]; //从数据表中读出频率数值
timer0l = FREQL[k]; //实际上, 是定时的时间长度
time = sszymmh[i + 2]; //读出时间长度数值
i += 3;
song(); //发出一个音符
} //控制时间长度
}
//送别
void song3()
{unsigned char k, i;
i = 0;
time = 1;
while(time)
{
k = sb + 7 * sb[i + 1] - 1; //第i个是音符, 第i+1个是第几个八度
timer0h = FREQH[k]; //从数据表中读出频率数值
timer0l = FREQL[k]; //实际上, 是定时的时间长度
time = sb[i + 2]; //读出时间长度数值
i += 3;
song(); //发出一个音符
} //控制时间长度
}
//键盘扫描
//函数返回 : 按下键:返回0~15、如无键按下:返回16
uchar Keyscan(void)
{
uchar i, j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};
for(j = 0; j < 4; j++) { //循环四次,扫描四行
P1 = Buffer[j]; //在低四位分别输出一个低电平
_nop_();
temp = 0x80; //计划先读出P1.7位
for(i = 0; i < 4; i++) { //循环四次,检查四列
if(!(P1 & temp)) { //从高四位,截取1位
return (i + j * 4); //返回取得的按键值
}
temp >>= 1; //换右边一位
} }
return 16; //没有键按下就返回16
}
//控制数码管显示 p2控制数码管的显位
void Display(uchar k)
{
P2=0xf0;
P0=num[k]; }
// 主函数
void Main(void)
{
uchar Key_Value = 16, Key_Temp1, Key_Temp2;//读出的键值
unsigned char k, i;
TMOD = 0x01; //T0定时方式1
ET0 = 1; //允许T0中断
EX0 = 1; //允许X0中断
EA = 1;
while(1) {
Key_Temp1 = Keyscan(); //读入按键
if(Key_Temp1 != 16) { //有键按下
Display(Key_Value); //显示键值、延时消抖
Key_Temp2 = Keyscan(); //再读一次
if (Key_Temp1 == Key_Temp2) {//两次相等
Key_Value = Key_Temp1; //就确认下来
Display(Key_Value); //显示
//条件选择语句
switch(Key_Value)
{
case 12:
{
song3();
delay(10);
song1();
delay(10);
song2();
delay(10);
};
break;
case 13:
song3();
break;
case 14:
song1();
break;
case 15:
song2();
break;
default:
{
i= Key_Value*3;
k = jianyin + 7 * jianyin[i + 1] - 1; //第i个是音符, 第i+1个几个八度
timer0h = FREQH[k]; //从数据表中读出频率数值
timer0l = FREQL[k]; //实际上, 是定时的时间长度
time = jianyin[i + 2]; //读出时间长度数值
song(); //发出一个音符
} ;
break;
} } } } }
一周热门 更多>