#include "reg52.h"
#include "intrins.h"
#define P1Key P1 // 矩阵键盘连在P1上
sbit beef = P2 ^ 5; // 蜂鸣器引脚
unsigned char soundIndex = 0; // 全局变量,记录要播放的声音的下标,每次中断重装都会使用用它,修改它就能在下一次中断修改蜂鸣器的声音频率
// 11.0592MHz晶振的定时器重装值
unsigned int listenArr[] = {
63775, 63967, 64138, 64216, 64360, 64489, 64603, // 低音1-7
64655, 64751, 64837, 64876, 64948, 65012, 65069, // 中音1-7
65096, 65144, 65186, 65206, 65242, 65274, 65303 // 高音1-7
};
void timerInit(void); //定时器0初始化
void Delay10ms(void); //延时 按键消抖用
unsigned char getValue_Key(void); //扫描矩阵按键 读取按键状态。也是控制发出停止蜂鸣器发声的入口。
void main()
{
unsigned char value = 0;
timerInit();
while (1)
{
while (value = getValue_Key())
{
// 这里可以读到按下的按键进行其它操作
//这里value 在 1 - 16 之间
}
}
}
void timerInit()
{
TMOD |= 0x01;
TH0 = 65535 / 256; // 这里初始值不是很重要
TL0 = 65535 % 256;
ET0 = 0; // 这里先不打开定时器0的中断允许,ET0可以用来控制蜂鸣器发声和停止
EA = 1; // 打开总中断
TR0 = 1; // 定时器0开始工作
}
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
// 读取矩阵键盘按下状态
// 返回 0 --> 没按下按键; 返回 1-16 -->按下对应的按键
//从普通的逐行逐列扫描在最后部分稍作改变得到
unsigned char getValue_Key()
{
char keyValue = 0;
P1Key = 0x0f;
if (P1Key != 0x0f)
{
Delay10ms(); // 消抖
if (P1Key != 0x0f)
{
keyValue = 0;
P1Key = 0x0f;
switch (P1Key) // 判断按下了哪一列
{
case 0x07:keyValue = 1;break;
case 0x0b:keyValue = 2;break;
case 0x0d:keyValue = 3;break;
case 0x0e:keyValue = 4;break;
}
P1Key = 0xf0;
switch (P1Key) // 判断按下了哪一行
{
case 0x70:keyValue = keyValue + 0;break;
case 0xb0:keyValue = keyValue + 4;break;
case 0xd0:keyValue = keyValue + 8;break;
case 0xe0:keyValue = keyValue + 12;break;
}
while (P1Key != 0xf0) // 等待按键松开
{
if (ET0 == 0) // 加个判断,可以让下边两条代码只执行一次。
{
soundIndex = keyValue + 4; // 按键只有16个,播不了21个声音,只能放弃5个,这里放弃了低音1-5 例如按下16 就是下标20(第21个)的高音7
ET0 = 1; // 在修改下标变量 soundIndex 后,定时器就会自动找对应的重装值。同时中断打开后蜂鸣器有了持续的脉冲,就能发出声音了
}
};
ET0 = 0; // 按键松开后关闭定时器中断,无源蜂鸣器就不响了。
}
}
else
keyValue = 0;
return keyValue;
}
void timer0() interrupt 1 // 定时器0中断函数
{
TH0 = listenArr[soundIndex] / 256; // 如果soundIndex变量改变,蜂鸣器的发声频率也会改变
TL0 = listenArr[soundIndex] % 256;
beef = !beef;
}
祝大家中秋国庆快乐