用独立按键控制LED灯的亮灭(普中51开发板)

用独立按键控制LED灯总共有四章基础代码,分别是

1.LED灯的亮灭        

2.独立按键控制LED灯的状态

3.独立按键控制LED显示二进制

4.独立按键LED灯的移位

        这是我个人见解,可能有些天赋比较好,时间比较充裕的同学可以举一反三,快速把这四个都写出来,但是我还建议像我这样的新手小白可以分两次学习,学完好好思考一下,打牢基础,这只是我的个人见解。

图1

        接下来我们说第二个,第一个在上一章,有兴趣的小伙伴们可以去我的主页看一下。说到独立按钮控制LED灯的亮灭就要说到独立按钮是机械按钮,在使用的时候会存在按键波动(参考图1),可以用硬件来隔离波动,但是同样也可以用软件来实现。而我们的目的就是怎么写软件去将按下和释放的抖动全部隔离,那就要用到延时函数,抖动时间一般在5-20ms,所以我们的延时变量就控制在50(方便敲代码,请切勿较真)

用ISP生成的代码是1ms,将函数别名的变量设置为50,在句尾加上xms--,就能控制while语句循环50次。

根据自己的喜好设置(楼主有点强迫症,开板子的时候灯必须要灭,所以在第21行将灯设置为低电压,可以不设置),P1_0为第一个独立按键 ,若P1_0==0(接地),则为低电瓶,电路接通,延时20ms,再次判断低电瓶,延时20ms。最后一步的取反运算,则是将LED灯的低电瓶与高电平进行相互切换。

新手学习嵌入式,不惜请勿喷,欢迎大佬在评论区指点一二,也欢迎跟我一样的同学在评论区相互交流,谢谢了。

<think>我们参考了站内引用,特别是引用[1]和引用[2],它们描述了红外遥控器对板载资源的控制以及红外接收头使用NEC协议解码。用户的问题是关于普中A2开发板使用红外遥控的八个按键控制LED和蜂鸣器的方法。 根据引用[1]和[2],我们知道: - 按下“1”时,LED快速闪烁。 - 按下“2”时,LED慢速闪烁。 - 按下“3”时,蜂鸣器鸣叫。 - 按下“4”时,LED呈现呼吸效果。 - 按下“5”时,数码管从10s开始倒计时一直到0,倒计时完成后,蜂鸣器鸣叫。 但是用户要求的是八个按键,而引用中只提到了5个按键(1-5)。因此,我们需要扩展其他按键的功能(例如6、7、8等)来控制LED和蜂鸣器,或者重复利用已有按键,但用户要求八个按键,所以我们需要定义8个按键(可能包括0-9中的8个,或者其他按键)。 另外,引用[3]提供了开发板的一些硬件信息,包括STC89C52单片机、红外接收头、蜂鸣器、LED等连接信息。我们需要根据这些信息来编写代码。 由于普中A2开发板的具体电路可能有所不同,但常见的是: - 红外接收头一般连接在单片机的某个IO口(例如P3^2,即外部中断0)。 - LED可能连接在P2口(8个LED)或者某个端口。 - 蜂鸣器可能连接在某个IO口(例如P1^5)。 根据这些信息,我们可以设计一个程序框架: 1. 初始化:设置红外接收、LED端口、蜂鸣器端口、定时器等。 2. 红外解码:使用外部中断和定时器中断来实现NEC协议的解码(通常NEC协议的数据格式为:引导码+32位数据,包括地址、地址反码、命令、命令反码)。 3. 根据解码得到的按键值(命令码),执行相应的功能。 由于引用中没有给出具体的按键键值,我们需要用户自行获取或者假设。通常,我们可以通过串口打印出接收到的键值,然后记录下8个按键对应的键值。 下面是一个示例代码框架(基于STC89C52,使用Keil C51编写): ```c #include <reg52.h> #include <intrins.h> // 定义红外接收头引脚 sbit IRIN = P3^2; // 定义LED端口(假设连接在P2口) #define LED_PORT P2 // 定义蜂鸣器引脚 sbit BEEP = P1^5; // 根据实际电路调整 // 红外解码相关变量 unsigned char IrValue[4]; // 存储解码后的4字节数据(地址、地址反码、命令、命令反码) unsigned char Time; // 用于计时 bit IrProceed = 0; // 红外处理标志 unsigned char IrCommand; // 存储命令码 // 函数声明 void InitIR(); // 初始化红外接收 void DelayMs(unsigned int x); // 延时函数 void Beep(); // 蜂鸣器鸣叫 void LedFlashFast(); // LED快速闪烁 void LedFlashSlow(); // LED慢速闪烁 void LedBreath(); // LED呼吸效果 void main() { // 初始化 LED_PORT = 0xFF; // 初始(假设低电平点) BEEP = 0; // 蜂鸣器不响(根据电路,可能为1不响,具体看电路) InitIR(); // 初始化红外接收 while(1) { if (IrProceed) { // 如果接收到红外数据 IrCommand = IrValue[2]; // 取命令码(根据NEC协议,第三字节为命令) IrProceed = 0; // 清除标志 // 根据命令码执行不同功能 switch(IrCommand) { case 0x45: // 假设按键1的键值为0x45 LedFlashFast(); break; case 0x46: // 按键2 LedFlashSlow(); break; case 0x47: // 按键3 Beep(); break; case 0x44: // 按键4 LedBreath(); break; // 继续添加其他按键... // 例如按键5:数码管倒计时(这里用户要求控制LED和蜂鸣器,所以可能不实现数码管?) // 但根据用户要求,我们只控制LED和蜂鸣器,所以定义8个按键分别控制不同的LED和蜂鸣器效果。 // 假设按键5:0x40,我们实现一个LED流水 case 0x40: // LED流水 break; case ...: // 其他按键 default: break; } } } } // 初始化红外接收 void InitIR() { IT0 = 1; // 设置外部中断0为下降沿触发 EX0 = 1; // 使能外部中断0 EA = 1; // 总中断使能 IRIN = 1; // 初始化引脚 } // 外部中断0服务函数(红外接收) void IR_ISR() interrupt 0 { unsigned char j, k; unsigned int count = 0; // 等待引导码的低电平9ms while(!IRIN) { // 低电平 DelayMs(1); count++; if (count >= 1000) { // 超时退出 return; } } // 高电平4.5ms count = 0; while(IRIN) { DelayMs(1); count++; if (count>=500) { return; } } // 开始接收4字节数据 for (j=0; j<4; j++) { for (k=0; k<8; k++) { count = 0; while(!IRIN) { // 等待低电平过去(0.56ms) DelayMs(1); count++; if (count>=50) { return; } } count = 0; while(IRIN) { // 等待高电平,根据高电平持续时间判断是0还是1 DelayMs(1); count++; if (count>=50) { return; } } // 如果高电平持续时间大于1ms,则为1,否则为0 if (count > 5) { // 大约1.12ms为1,0.56ms为0 IrValue[j] |= (0x80>>k); } else { IrValue[j] &= ~(0x80>>k); } } } // 校验地址和命令 if (IrValue[0]!=~IrValue[1] || IrValue[2]!=~IrValue[3]) { return; // 校验失败 } IrProceed = 1; // 设置标志,表示接收到有效数据 } // 延时函数(粗略延时) void DelayMs(unsigned int x) { unsigned int i, j; for(i=x; i>0; i--) for(j=110; j>0; j--); } // 蜂鸣器鸣叫函数 void Beep() { unsigned int i; for(i=0; i<200; i++) { BEEP = ~BEEP; DelayMs(1); } BEEP = 0; // 关闭蜂鸣器(根据电路,可能为1) } // LED快速闪烁 void LedFlashFast() { unsigned char i; for(i=0; i<10; i++) { LED_PORT = 0x00; // 全 DelayMs(100); LED_PORT = 0xFF; // 全 DelayMs(100); } } // LED慢速闪烁 void LedFlashSlow() { unsigned char i; for(i=0; i<5; i++) { LED_PORT = 0x00; DelayMs(500); LED_PORT = 0xFF; DelayMs(500); } } // LED呼吸效果(使用PWM) void LedBreath() { unsigned int i, j; // 逐渐变 for(i=0; i<100; i++) { LED_PORT = 0x00; // for(j=0; j<i; j++) { DelayMs(1); } LED_PORT = 0xFF; // for(j=0; j<100-i; j++) { DelayMs(1); } } // 逐渐变暗 for(i=100; i>0; i--) { LED_PORT = 0x00; for(j=0; j<i; j++) { DelayMs(1); } LED_PORT = 0xFF; for(j=0; j<100-i; j++) { DelayMs(1); } } } ``` 注意:以上代码仅作为框架,实际使用时需要根据开发板的硬件连接进行调整,特别是LED和蜂鸣器的控制引脚。另外,红外解码部分需要根据实际遥控器的键值进行修改。通常,我们可以通过串口打印出IrValue[2](命令码)来确定每个按键的值。 由于用户要求八个按键,我们可以在switch语句中增加8个case,每个case对应一个按键值,并实现不同的LED和蜂鸣器效果(例如,不同的闪烁模式、蜂鸣器不同频率的声音等)。 此外,呼吸效果使用简单的延时实现PWM,可能不够平滑,可以使用定时器中断来产生更精确的PWM。 由于引用[3]中提到开发板有多个资源,但用户只要求LED和蜂鸣器,所以我们只关注这两个外设。 §§相关问题§§ 1. 如何获取红外遥控器各个按键的键值? 2. 如何调整红外解码的精确性? 3. 如何优化呼吸效果的PWM控制? 4. 如何同时控制多个LED的不同状态? </think> ### 普中A2开发板红外遥控控制LED和蜂鸣器实现方法 根据您提供的引用内容和普中A2开发板特性,实现红外遥控八个按键控制LED和蜂鸣器的步骤如下: #### 1. **硬件连接** - 红外接收头连接到开发板的P3^2引脚(外部中断0) - LED组连接到P2端口(8个LED) - 蜂鸣器连接到P1^5引脚(根据引用[3]) ```c sbit IRIN = P3^2; // 红外接收引脚 sbit BEEP = P1^5; // 蜂鸣器控制引脚 #define LED P2 // LED端口 ``` #### 2. **红外解码实现(NEC协议)** ```c unsigned char IrValue[4]; // 存储解码数据 bit IrProceed = 0; // 解码完成标志 void InitIR() { IT0 = 1; // 下降沿触发 EX0 = 1; // 使能外部中断0 EA = 1; // 总中断使能 IRIN = 1; // 初始化引脚 } void IR_ISR() interrupt 0 { unsigned int count = 0; // 引导码检测(9ms低电平+4.5ms高电平) while(!IRIN && count < 200) { count++; Delay10us(5); } if(count >= 200) return; count = 0; while(IRIN && count < 180) { count++; Delay10us(5); } // 接收32位数据 for(int i=0; i<4; i++) { for(int j=0; j<8; j++) { count = 0; while(!IRIN && count<60) { count++; Delay10us(5); } count = 0; while(IRIN && count<30) { count++; Delay10us(5); } IrValue[i] >>= 1; if(count > 8) IrValue[i] |= 0x80; // 判断数据位 } } IrProceed = 1; // 解码完成 } ``` #### 3. **按键功能映射** 根据引用[1]扩展8个按键功能: | 按键 | 功能描述 | 控制代码示例 | |------|--------------------------|--------------------------| | 1 | LED快速闪烁 | `LED = ~LED; delay(100)` | | 2 | LED慢速闪烁 | `LED = ~LED; delay(500)` | | 3 | 蜂鸣器鸣叫 | `BEEP = 1; delay(500)` | | 4 | LED呼吸效果 | PWM调光实现 | | 5 | 倒计时+蜂鸣器(需扩展) | 数码管显示+蜂鸣器 | | 6 | LED流水向右 | 移位操作`LED>>=1` | | 7 | LED流水向左 | 移位操作`LED<<=1` | | 8 | 全/全切换 | `LED = ~LED` | #### 4. **主程序逻辑** ```c void main() { InitIR(); while(1) { if(IrProceed) { switch(IrValue[2]) { // 判断按键码 case 0x45: // 按键1 for(int i=0; i<10; i++) { LED = 0x00; DelayMs(100); LED = 0xFF; DelayMs(100); } break; case 0x46: // 按键2 // 类似实现慢闪 break; case 0x47: // 按键3 BEEP = 1; DelayMs(500); BEEP=0; break; // 添加其他按键处理... } IrProceed = 0; // 清除标志 } } } ``` #### 5. **关键注意事项** 1. **红外键值获取**:需先读取各按键的NEC编码值(通过串口打印`IrValue[2]`) 2. **硬件适配**: - 确认LED共阳/共阴连接方式 - 蜂鸣器需无源蜂鸣器(引用[3]) 3. **资源冲突**: - 使用串口调试时需移除CH340短接片(引用[3]) - 避免P3^2同时用于其他功能 > 实际键值因遥控器型号而异,建议先用测试程序获取键值[^2]。呼吸效果可通过PWM占空比调节实现,倒计时功能需结合定时器和数码管驱动[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值