❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。⭐️ 专栏主要内容: 主要学习51单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
💑专栏主页:http://t.csdn.cn/HCD8v
本学习过程参考:https://space.bilibili.com/383400717
单片机安装软件、各种资料以及源码的路径:
https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng
提取码:gdzf
文章目录
- 一、本节背景和目标
- 1.1 独立按键的原理(很重要!!!)
- 1.2 本节目标
- 二、独立按键控制LED亮灭
- 三、独立按键控制LED状态
- 四、独立按键控制LED显示二进制
- 五、独立按键控制LED位移
一、本节背景和目标
1.1 独立按键的原理(很重要!!!)
独立按键在开发板上的位置如下图所示,左右到右依次是K1、K2、K3、K4
独立按键的原理图如下所示:
其在MCU上的位置如下所示:
由上面两张图可以知道,独立按键是接在MCU的P3.0口到P3.3口的;
可以看到,独立按键的右端是接地的;这里需要注意,独立按键跟LED灯的原理有区别,LED灯是通过高低电平通电,进而使灯亮;而独立按键不一样,独立按键的一端接地,独立按键就是一个开关;以K1为例,K1右端是GND,左端是RXD,我们知道,单片机在刚上电时,所有i/o口默认都是高电平的;所以当K1按键没有按下时,RXD是高电平,但当K1按键按下时,电路进行了连通,RXD接通了GND,所以RXD此时变成了低电平。
从上一篇文章中我们知道了,在寄存器中写入一个值,该值就会同步到对应的i/o口上;其实反之也成立,即通过寄存器可以读到i/o口的状态,是高电平还是低电平。
所以当按键没有按下时,寄存器读到的该i/o的状态就是高电平(即1);反之,当按键按下时,寄存器就可以读到该i/o口的状态为低电平(即0)
;我们则可以通过寄存器读到的i/o口的状态是高电平还是低电平,就知道按键是按下还是松开了,进一步可以写程序对小灯进行控制。
1.2 本节目标
目标1:独立按键控制LED亮灭
K1控制LED灯D1的亮灭,即按下K1(持续不松开)时D1亮,松开D1时D1灭;如下图所示
目标2:独立按键控制LED状态
还是K1控制D1灯,现象是K1按一下并松开,D1点亮;再按一下并松开,D1灭;再按一下并松开,D1变亮;再按一次并松开,D1灭;如下图
目标3:独立按键控制LED显示二进制
每按下并松开一次K1,LED灯点亮一次,多次按下并松开,实现按照二进制递增的顺序进行点亮;具体的说,可以将8个等比作8个二进制数字,最右边的亮表示1,右边第二个灯亮表示2,右边第三个灯亮表示4,右边第四个灯亮表示8;以此类推;也可以知道,右边第一个和右边第二个灯同时亮表示3(1+2)以此类推;每次按下并松开一次K1,此8个灯中亮起的一个或几个灯组成的数字就加1;如下图所示:
目标4:独立按键控制LED移位
按下K1并松开时,LED灯向左移一位;按下K2时,LED灯向右移一位。
K1每按下一次,LED灯向左移动一位:
K2每按下一次,LED灯向右移动一位:
二、独立按键控制LED亮灭
代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-1 独立按键控制LED亮灭
代码实现:
#include <REGX52.H>
void main()
{
while(1)
{
if(P3_1==0 || P3_0==0) //如果K1按键或K2按键按下
{
P2_0=0; //LED1输出0,点亮
}
else
{
P2_0=1; //LED1输出1,熄灭
}
}
}
代码解释:
P3_1和P3_0分别表示按键K1和按键K2在MCU上的端口;P3_0等于0表示通过寄存器读到的P3_0端口电平状态为低电平,由1.1 独立按键的原理中可知,按键按下时对应的i/o口为低电平,按键松开时对应的i/o口为高电平。所以P3_1==0
表示K2按键按下,P3_0==0
表示K1按键按下。
P2_0=0
表示P2_0端口赋值为低电平,即对应的LED1灯点亮。注意,在上一篇文章的学习中,我们是对P2口整体进行控制,所以使用P2=0xFE
这种方式,这种方式可以一次性控制8个灯的状态;例如P2=0xFE
就表示第一个灯亮,其他的均灭;但是除了对P2口整体进行控制外,我们也可以分别对P2口的8个端口进行控制,例如P2_0=0
则表示第一个灯亮,至于其他七个灯是什么状态,不管。
最终实现的效果就是目标1:K1控制LED灯D1的亮灭,即按下K1(持续不松开)时D1亮,松开D1时D1灭;如下图所示
三、独立按键控制LED状态
代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-2 独立按键控制LED状态
代码实现:
#include <REGX52.H>
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1)
{
if(P3_1==0) //如果K1按键按下
{
Delay(20); //延时消抖
while(P3_1==0); //松手检测
Delay(20); //延时消抖
P2_0=~P2_0; //LED1取反
}
}
}
代码解释:
P3_1==0
表示K1按键按下,上一节已经进行了解释,这里不再解释。
Delay(20)
表示延时20ms,此延时函数的是通过stc-isp生成的,生成过程在上一篇文章中有讲解,这里不再重复叙述。在里面加了参数xms
,是为了能实现延时时间可配置。
至于为什么要设置延时呢?目的是消除按键的抖动,什么事抖动?
通俗的解释,当我们按下按键时,并不会马上接通,可能会进行抖动,如 通->断->通->断
等过程逐渐的接通;当然,在断开时,也不会马上断开,而是断->通->断->通
等过程;这些抖动过程其实是不能作为准确值的,所以要消除抖动。
所以通过延时函数,将抖动期间的动作忽略掉,就可以消除抖动带来的影响,达到的消抖的目的。
最终程序运行的结果就是上面提到的目标2:
还是K1控制D1灯,现象是K1按一下并松开,D1点亮;再按一下并松开,D1灭;再按一下并松开,D1变亮;再按一次并松开,D1灭;如下图
四、独立按键控制LED显示二进制
代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-3 独立按键控制LED显示二进制
代码实现:
#include <REGX52.H>
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
void main()
{
unsigned char LEDNum=0;
while(1)
{
if(P3_1==0) //如果K1按键按下
{
Delay(20); //延时消抖
while(P3_1==0); //松手检测
Delay(20); //延时消抖
LEDNum++; //变量自增
P2=~LEDNum; //变量取反输出给LED
}
}
}
代码解释:
前面的代码都跟上一节一致,就是判断按键按下,且按键松开,以及延时消抖操作。
最主要的是LEDNum++以及P2=~LEDNum
两行代码;下面按照程序的运行过程解释一下这两行代码;
第一次按下并松开K1按键时,进入第一次进入循环,此时LEDNum
是0,所以LEDNum++
后的值即为1(十六进制表示为0x0000 0001
);此时将LEDNum
取反后的值是0x1111 1110
,将这个值给到P2口;这样8个LED灯的状态为:高7位寄存器的值是1,即P20-P26口是高电平,则前7个LED灯都是灭的,同理,最低位的寄存器的值是0,则P27口是低电平,则最后一个LED灯是亮的;
第一次按下并松开K1按键时,进入第二次进入循环,此时LEDNum
是1,所以LEDNum++
后的值即为2(十六进制表示为0x0000 0010
);此时将LEDNum
取反后的值是0x1111 1101
,将这个值给到P2口;这样8个LED灯的状态为:高6位以及最低位的寄存器的值是1,即P20-P25以及P27口是高电平,则前6个LED灯以及第8个LED灯都是灭的,同理,第7个LED灯是亮的;
依次类推,每按下并松开一次K1按键,则二进制数字加1,对应的寄存器和LED灯也都加一。
最终实现的效果就是目标3:独立按键控制LED显示二进制
每按下并松开一次K1,LED灯点亮一次,多次按下并松开,实现按照二进制递增的顺序进行点亮;具体的说,可以将8个等比作8个二进制数字,最右边的亮表示1,右边第二个灯亮表示2,右边第三个灯亮表示4,右边第四个灯亮表示8;以此类推;也可以知道,右边第一个和右边第二个灯同时亮表示3(1+2)以此类推;每次按下并松开一次K1,此8个灯中亮起的一个或几个灯组成的数字就加1;如下图所示:
五、独立按键控制LED位移
代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-4 独立按键控制LED移位
代码实现:
#include <REGX52.H>
void Delay(unsigned int xms);
unsigned char LEDNum;
void main()
{
P2=~0x01; //上电默认LED1点亮
while(1)
{
if(P3_1==0) //如果K1按键按下
{
Delay(20);
while(P3_1==0); //循环直到K1键松开
Delay(20);
LEDNum++; //LEDNum自增
if(LEDNum>=8) //限制LEDNum自增范围
LEDNum=0;
P2=~(0x01<<LEDNum); //LED的第LEDNum位点亮
}
if(P3_0==0) //如果K2按键按下
{
Delay(20);
while(P3_0==0);//循环直到K2键松开
Delay(20);
if(LEDNum==0) //LEDNum减到0后变为7
LEDNum=7;
else //LEDNum未减到0,自减
LEDNum--;
P2=~(0x01<<LEDNum); //LED的第LEDNum位点亮
}
}
}
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
代码解释:
有了前三节的基础,这一节就比较简单了,看注释即可。
最终的效果是实现目 标4:独立按键控制LED移位
按下K1并松开时,LED灯向左移一位;按下K2时,LED灯向右移一位。
K1每按下一次,LED灯向左移动一位:
K2每按下一次,LED灯向右移动一位: