当前位置: 首页 > article >正文

【51单片机零基础-chapter3:按键:独立按键|||附带常见C语句.逻辑运算符】

将unsigned char var=0;看作沟通二进制和十进制的桥梁
var是8位,初始为0000 0000;
同时可以进行十进制的运算

逻辑运算

在这里插入图片描述
在这里插入图片描述
位运算

& 按位与(有0则0)
| 按位或(有1则1)
~ 按位非
^ 按位异或(相同则1,不同为0)
<<按位左移 >>按位右移

位运算符解释:
0011 1100
<<1 则变为
0111 1000
本质就是去掉最高K个位,最低K个位补充为0
右移同理,最低位k个全舍弃,最高位补充k个0
0011 1100
>>2
0000 1111

0011 1100 & 0010 0110
0010 0100

在这里插入图片描述
但是有符号数中负数的右移相当于填个1
在这里插入图片描述

单片机管脚指IO口
前面的LED灯有高低电平才会亮
单片机上电,所有IO口默认高电平
所以独立按键如果按下则低电平,没有按下默认高电平
寄存器写值会送到IO口
寄存器检测IO口电平,又会读回寄存器中
松开按键读寄存器则是高电平1,按下则读的是0
所以检测管脚电平高低,可以知道是否按下了按键.

#include <REGX52.H>
void main(){
	P2=0xfe;			//MIN bit=0;other bit =1;
	while(1){
	;
	}
}

不难看出,这个点亮单个灯是通过控制寄存器实现的
但是需要给其它位赋值(8位为一组),即通过P2赋值
但我们只想操作最低位,不干涉别的位数强行赋值.
如何制定一位来控制?
打开头文件不难看到有指定位的方法
在这里插入图片描述
原来P2寄存器有指定的变量!
P2-0to7有八个引脚的赋值变量
所以有:

不使用0x十六进制全位赋值,指定控制某个位
#include <REGX52.H>
void main(){
	//P2=0xfe;			//MIN bit=0;other bit =1;
	P2_0=0;//1-7 bit is unknown,but maybe default 1
	while(1){
	;
	}
}

0是低电平,默认有高电平,此时存在一高一低,所以第一个灯会点亮,而其他的因为没有赋值默认为1不会点亮因为这些灯全是高电平.
此时你写了寄存器,那么就会被送到IO口
IO口产生的电平也会被送到寄存器从而得知0与1

独立按键

翻看手册,看到K1按键的口是RXD
在这里插入图片描述
在这里插入图片描述
所以K1-RXD-P3_1(P3_1,0,2,3)这个设计有点老了,本应该是0123对应K1234

#include <REGX52.H>
void main(){
//p2是灯,p3是按键,pk_num的num指的是第几个,一般从0开始,但是p3是1023顺序,p2是正常的0123
	while(1){
			if(P3_1==0){//如果按键是低电平,那么说明按下了
				P2_7=0;//点亮
			}else{
				P2_7=1;//高电平,说明是默认值高电平没有按下,那么不点亮
			}
	}
}

按键抖动

在这里插入图片描述
对于独立按键,由于单片机检测频率不同于家用电器,单片机是可以监测到抖动的,因为按键的小铁片有弹性,不会马上变成稳定状态从而低电平,按下或松开都会发生5-10ms的抖动,这个抖动会导致频繁的被单片机监测到,从而造成按一下相当于按多次的情况,需要避免.
消抖方法:
1.硬件(不会)
2.软件,首次监测到执行,然后接下来5-10ms的抖动用延时单片机检测(delay啥也不干)来处理(首次按下瞬间,松开瞬间后都要消抖)

#include <REGX52.H>
void Delay(unsigned int x)		//@12.000MHz
{
	while(x--){
		unsigned char i, j;
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main(){
	while(1){
			if(P3_1==0){//检测到按键的第一瞬间,马上执行按键消抖
					Delay(15);
					while(P3_1==0);//如果没放手则一直等待
					//松手对应从while出来的一瞬间,马上执行松手消抖
					Delay(15);
				//消抖完毕,此时执行点亮操作
					//P2_7=0;
					P2_7=~P2_7;//按位取反也可点亮,特别适合开关逻辑,p2_7原来是1则变为0,若再按则0变为1熄灭
			}
	}
}

按一下,灯光移动一下

8个位置避免溢出,取余解决
灯光移动,以0000 0001逻辑左移解决
这是第k次按,则0000 0001<<k赋给灯光P2

#include <REGX52.H>
void Delay(unsigned int x);

void main(){
	unsigned char ledvar=0;//because un char is 8bits data , and compatible with register data(8 bits)
	while(1){
		//default all bits is 1: just as 1111 1111
			if(P3_1==0){
				Delay(5);while(P3_1==0);Delay(5);
				++ledvar;
				ledvar%=8;
				P2=~(0x01<<ledvar);
			}
	}
}

void Delay(unsigned int x)		//@12.000MHz
{
	while(x--){
		unsigned char i, j;
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

稍作更改得到
按键1得到右移,按键2得到左移
主要还是在代码的逻辑
因为最终的显示取决于P2每位的值,以便赋予各管脚高低电平
而P2由0x01即0000 0001的每轮左右得到,这是0x01是不变的
关键在于移的位数
如果本轮左移动了7位,那么下一轮左移就左移6位即可(通过右移的位数偏差,实现当轮左移的逻辑)

void main(){
	unsigned char ledvar=0;//because un char is 8bits data , and compatible with register data(8 bits)
	while(1){
		//default all bits is 1: just as 1111 1111
			if(P3_1==0){
					Delay(5);while(P3_1==0);Delay(5);
					++ledvar;
					ledvar%=8;
					P2=~(0x01<<ledvar);
			}
			else if(P3_0==0){
					Delay(5);while(P3_0==0);Delay(5);
					--ledvar;
					ledvar%=8;
					P2=~(0x01<<ledvar);			
			}
	}
}

按键实现二进制灯光模拟:

按k次,二进制是多少,则亮对应的灯
逻辑上,初始全0,恰好无符号字符var就是8位,刚好适合,那么初始置为0,既有0000 0000的数据
此时++,有:
0000 0001第一次
0000 0010第二次
0000 0011第三次按下

1111 1111
0000 0000

核心代码
void main(){
	unsigned char ledvar=0//because un char is 8bits data , and compatible with register data(8 bits)
	while(1){
		//default all bits is 1: just as 1111 1111
			if(P3_1==0){
					Delay(5);while(P3_1==0);Delay(5);
					++ledvar;
					p2=~ledvar;
			}
	}
}

今天晚上单片机刚到,先结束一个章节.
收工,刷抖音去了


http://www.kler.cn/a/466780.html

相关文章:

  • 场馆预定平台高并发时间段预定实现V1
  • 云架构:考量与框架
  • Java 关键字【synchronized】
  • 【机器学习:一、机器学习简介】
  • HTML-列表标签
  • Linux 基础七 内存
  • 中国科技产业化促进会深入深圳企业调研
  • gesp(C++一级)(17)洛谷:B4062:[GESP202412 一级] 温度转换
  • 在Linux系统中使用字符图案和VNC运行Qt Widgets程序
  • IDEA Plugins中搜索不到插件解决办法
  • 自动化测试常考的面试题+答案汇总(持续更新)
  • React 网络请求优化
  • CVSS漏洞评分系统曝出严重缺陷
  • 【源码+文档+调试讲解】“健康早知道”微信小程序
  • 生成对抗网络 (Generative Adversarial Network, GAN) 算法MNIST图像生成任务及CelebA图像超分辨率任务
  • 深入理解 Android 中的 ComponentInfo
  • Hive集群安装部署
  • Markdown中流程图的用法
  • 解决 HTML 表单输入框与按钮对齐问题
  • LeetCode 力扣 热题 100道(二十三)找到字符串中所有字母异位词(C++)
  • issue问题全解
  • 从摩托罗拉手机打印短信的简单方法
  • 深入 Redis:高级特性与最佳实践
  • 下载Stegsolve.jar后运行报错 ”Error: Unable to access jarfile stegslove. ”
  • Hive分区表添加字段
  • 设计模式-创建型设计模式总结