目标
1. 按K2(独立按键),流水灯LED1点亮,依次点亮,直至全部灯点亮
2. 独立按键(K2,K3),当K2被按下时流水灯按左向右顺序点亮一个灯,按K3则是相反方向,最终通过两个不同的按键完成的双向移动
友情提醒
- 本博客使用的是普中51板子(芯片:STC89C52RC)
- 如果是完全没有接触过,请先浏览 第一站
上手
- 找到自己板子的关于 led与独立按键 的原理图
51原理图(来源:B站江科大,侵权删): - 分析 (按K2(独立按键),流水灯LED1点亮,依次点亮,直至全部灯点亮)
-
单片机按键的简单工作原理是什么?
答:按下一直通电(0),放开停止通电(1)
原理图:
-
如何确认按键按下了一次?
答:该按键对应的引脚数值为0时(例如:K2的引脚 P3_0 == 0 ),但该方式可能导致按一下会出现多次响应,因为按下没松开的瞬间虽然看起来很短,但其实已经足够单片机循环代码很多遍了,而此时由于没松开,所以该引脚一直是0状态,故而导致了多次响应。
解决:利用下降沿判断按键的一次按下
unsigned char btnState;
unsigned char preBtnState = 1;
while(1){
btnState = P3_0; // 读取按键K2状态
if (btnState == 0 && preBtnState != 0) {// 检查下降延
// 按键按下的逻辑
}
}
preBtnState = btnState;
DelaByms(50);// 延时50ms
- 如何依次点亮?
答:<< 运算
- ** 完整代码编写**
#include <REGX52.H>
#include <intrins.h>
void main() {
unsigned char ledSta= 0xFF;
unsigned char btnState;
unsigned char preBtnState = 1;
while(1){
btnState = P3_0; // 读取按键K2状态
if (btnState == 0 && preBtnState != 0) {// 检查下降延
P2 = loop; // 点亮LED
if (ledSta == 0) {
ledSta = 0xFF; // 循环到最高位后重新开始
}else{
ledSta = ledSta << 1; // 左移一位
}
}
preBtnState = btnState;
Dela50ms();// 延时函数上STC-ISP根据自己的芯片型号生成,这里不提供
}
}
-
烧录程序
参考 第一站 -
第二题同理,得代码:
// 独立按键(K2,K3),当K2被按下时流水灯按左向右顺序点亮一个灯,按K3则是相反方向,最终通过两个不同的按键完成的双向移动
#include <REGX52.H>
#include <intrins.h>
void main() {
unsigned char btnStateS2;
unsigned char preBtnStateS2 = 1;
unsigned char btnStateS3;
unsigned char preBtnStateS3 = 1;
unsigned char left = 0xFF;
unsigned char right = 0xFF;
while(1){
btnStateS2 = P3_0;
btnStateS3 = P3_2;
if (btnStateS2 == 0 && preBtnStateS2 != 0) {// S2
if (left == 0) {
left = 0xFF; // 循环重新开始
}else{
left = left << 1; // 左移一位
}
}
if (btnStateS3 == 0 && preBtnStateS3 != 0) {// S3
if (right == 0) {
right = 0xFF;
}else{
right = right >> 1; // 右移
}
}
preBtnStateS2 = btnStateS2;
preBtnStateS3 = btnStateS3;
P2 = left & right; // 点亮LED
Dela100ms();// 延时函数上STC-ISP根据自己的芯片型号生成,这里不提供
}
}