前言:
本文是根据哔哩哔哩网站上“江协科技51单片机”视频的学习笔记,在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了江协科技51单片机教学视频和链接中的内容。
引用:
51单片机入门教程-2020版 程序全程纯手打 从零开始入门_哔哩哔哩_bilibili
正文:
0. 概述
今天 (2024/06/13)在淘宝上购买了江协科技51单片机开发板套件,就上在上一篇博文里说的自己计划学习下江协科技51单片机开发教程,通过STC51单片机这种MCU这种贴近于裸机的开发来增加对于系统硬件层面知识的了解和掌握。
1. 按键的机械结构
按键的机械结构如下,按下时开关接通,松开时开关断开,实现原理使用通过轻触开关的内部金属弹片受力弹动来实现接通和断开。
2. 电路原理图
我使用的普中51单片机A2开发板上4个独立按键的电路原理图如下所示
按键 | 标注 | 芯片引脚 |
K1 | RXD | 11号引脚 P3.1 |
K2 | TXD | 10号引脚 P3.0 |
K3 | P32/CS1 | 12号引脚 P3.2 |
K4 | P33/CS2 | 13号引脚 P3.3 |
51单片机上电所有IO口默认为高电平
3. 修改Keil5编辑器Tab缩进为4个空格
为了代码对齐和美观,修改Keil5编辑器Tab缩进为4个空格,这样对齐之后的代码看起来更符合之前的习惯。
4. Keil5 <REG52.H>定义的P2_0的bit位
头文件有 <REGX52.H> 和 <REG52.H>,差异是多了一个字母 'X'。
头文件 | 说明 |
<REGX52.H> | <REGX52.H> 头文件中有定义 P2_0, P2_1, ..., P2_7 这些bit位操作 |
<REG52.H> | 而 <REG52.H>只定义了P2对8个bit位一起操作,没有定义P2_0, P2_1, ..., P2_7 这些bit位操作 |
头文件有
<REGX52.H>
<REG52.H>
<REGX52.H> 头文件中有定义 P2_0, P2_1, ..., P2_7 这些bit位操作,而 <REG52.H>只定义了P2对8个bit位一起操作,没有定义P2_0, P2_1, ..., P2_7 这些bit位操作。
5. 机械按键消抖
由于机械按键的物理特性,在按下按键时金属弹片会在很短时间内由于弹性力反复弹跳几次,造成按键输出的电平会在高电平和低电平之间反复抖动几次,这个抖动的时间极短大概再几个毫秒;同理机械按键松开时,按键的金属弹片也会有抖动造成按键输出的电平抖动;
也就是说在机械按键按下和松开的瞬间都会由于机械按键的弹片抖动造成输出电平的跳变。所以需要在按键按下和松开都需要做按键的消抖。
消抖的方式有两种:
- 硬件消抖,需要专门的硬件电路比较麻烦
- 软件消抖,软件检测到按键被按下之后 delay 一段时间,等待抖动的时间结束。
本视频教程使用软件延时delay的方法来进行机械按键的消抖(debounce)。
本节机械按键消抖的源码思路如下:
- 按键按下,检测到C51单片机并口为低电平
- 检测到低电平之后,delay 10毫秒,跳过按键按下后的按键抖动过程
- delay延时结束之后,循环检测按键是否一致按下没有松开,如果按键没有松开的话就检测到C51单片机并口为低电平就一直循环。
- 检测到C51单片机并口为高高电平,表示按键松开,延时10ms跳过按键松开时的按键抖动过程。
- 按键消抖
- 检测松手
- 检测松手的例子,按键按下后不执行操作,一直等待到按下松开后才执行操作。就像我们操作Windows系统鼠标店家一个窗口程序的“最小化”按钮,鼠标按下“最小化”按钮后不松手就一直不执行最小话,在松开鼠标的瞬间才执行窗口的最小化。
- 有两个消抖,按下消抖和松手消抖
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
_nop_();
while(xms--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
P2_0 = 0; //初始值
while(1)
{
if(P3_1 == 0)
{
Delay(10); //按键按下消抖
while(P3_1 == 0); //按键按下后不松开就一直循环等待
Delay(10); //按键松开消抖
P2_0 = ~P2_0;
}
}
}
6. 按键实现显示二进制数据
C51单片机默认上电并口的为高电平。
根据我自己使用的普中科技C51单片机开发板A2型号,我在如下程序里对LEDNum显示的数据进行了镜像翻转。
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
_nop_();
while(xms--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
unsigned char ledNum = 0;
unsigned char ledNumMirror = 0;
unsigned char i = 0;
//P2_0 = 0; //初始值
while(1)
{
if(P3_1 == 0)
{
Delay(10); //按键按下消抖
while(P3_1 == 0); //按键按下后不松开就一直循环等待,检测松手
Delay(10); //按键松开消抖
//P2_0 = ~P2_0;
ledNum++;
ledNumMirror = 0;
//镜像翻转 unsigned char 数据
//因为普中科技STC51 A2 型号单片机开发板的LED灯连接方式,P2_0=0时最左边LED灯亮,P2_7=0时最右侧LED灯亮
//为了满足习惯上左侧为数据高位,右侧为低位的习惯,这里我将LEDNum的值进行了镜像翻转
i = 0;
while(i < 8)
{
if(ledNum & (1 << (7-i)))
ledNumMirror |= (1 << i);
i++;
}
P2 = ~ledNumMirror;
}
}
}
7. 按键实现LED灯移位
根据我自己使用的普中科技C51单片机开发板A2型号,我在如下程序里对LEDNum显示的数据进行了镜像翻转。
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
_nop_();
while(xms--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
unsigned char ledNum = 0;
P2_7 = 0; //初始化
while(1)
{
//按下独立按键 KEY_1 实现LED灯向左移位
if(P3_1 == 0)
{
Delay(10); //按下延时消抖
while(P3_1 == 0); //检测松手,当按键按下没有松开时一直执行循环检测
Delay(10); //松手延时消抖
ledNum++;
if(ledNum >=8)
ledNum = 0;
P2 = ~(1 << (7 - ledNum));
}
//按下独立按键 KEY_2 实现LED灯向右移位
if(P3_0 == 0)
{
Delay(10); //按下延时消抖
while(P3_0 == 0); //检测松手,当按键按下没有松开时一直执行循环检测
Delay(10); //松手延时消抖
if(ledNum == 0)
ledNum = 8;
ledNum--;
P2 = ~(1 << (7 - ledNum));
}
}
}