给51单片机矩阵键盘加上乐音(简易电子琴)

#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;
}

祝大家中秋国庆快乐

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值