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

【51单片机学习】LED、独立按键

一、点亮一个LED

(一)LED介绍

VCC经过限流电阻连接到LED的正极,通过控制引脚的高低电平来控制LED的亮灭,单片机的TTL电平,高电平是5V低电平时0V,单片机输出高电平LED不点亮,输出低电平LED点亮。

贴片电阻的读数方式

单片机称为MCU,其内部集成了一个CPU,寄存器是一种特殊的存储器,八个分为一组,相当于按钮,每个寄存器都有一根线经过驱动器连接到I/O口,CPU可以通过程序直接访问寄存器,写1对应高电平,写0对应低电平,此时高低电平的问题就转化为了配置P2口的寄存器问题。单片机的操作方式都是CPU通过配置相应的寄存器控制硬件电路,使其能够满足需要的功能。

(二)进制转换

(三)代码示例

#include <REGX52.H>void main()
{//P2 = 0xFE;//1111 1110P2 = 0x55;//0101 0101while(1)//非0即真{}
}

二、LED闪烁

(一)产生延时函数

利用STC-ISP生成延时。

如果直接复制代码的话会报错,为了避免该问题,需要添加头文件 #include <INTRINS.H> 。如果_nop_();大概是1微秒,对精度要求不是很高可以直接删掉_nop_();这行代码。

(二)代码示例

#include <REGX52.H>
#include <INTRINS.H>void Delay500ms(void)	//@11.0592MHz  括号内的void可省略
{unsigned char data i, j, k;_nop_();//需加定义 是空语句的意思i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}void main()
{P2 = 0xFE;//1111 1110P2 = 0xFF;//1111 1111while(1){P2 = 0xFE;//1111 1110Delay500ms();P2 = 0xFF;//1111 1111Delay500ms();}
}

三、LED流水灯

(一)C51数据类型

在单片机中int类型是16位的,而在计算机中int类型是32位的。
int默认是有符号数,如果要表示无符号数应写为 unsigned int。

(二)代码示例

#include <REGX52.H>
#include <INTRINS.H>void Delay500ms(void)	//@11.0592MHz
{unsigned char data i, j, k;_nop_();//约1us可删去 影响不大 若不删需加头文件i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}void main()
{while(1){P2 = 0xFE;//1111 1110Delay500ms();P2 = 0xFD;//1111 1101Delay500ms();P2 = 0xFB;//1111 1011Delay500ms();P2 = 0xF7;//1111 0111Delay500ms();P2 = 0xEF;//1110 1111Delay500ms();P2 = 0xDE;//1101 1111Delay500ms();P2 = 0xBE;//1011 1111Delay500ms();P2 = 0x7E;//0111 1111Delay500ms();}
}

(三)代码优化

上述代码的延时过于死板,为了使其变得更加灵活,可以先生成一个1毫秒延时函数,在子函数的括号中写入参数并指定变量类型,再写入一个while循环。

#include <REGX52.H>void Delay1ms(unsigned int xms)	//@11.0592MHz 括号内为子函数的形参
{unsigned char data i, j;while(xms){//_nop_();i = 2;j = 199;do{while (--j);} while (--i);//xms = xms-1;xms--;//每执行一次 减少1ms  从而达到输入多少ms就延时多少ms}
}void main()
{while(1){P2 = 0xFE;//1111 1110Delay1ms(500);P2 = 0xFD;//1111 1101Delay1ms(500);P2 = 0xFB;//1111 1011Delay1ms(500);P2 = 0xF7;//1111 0111Delay1ms(500);P2 = 0xEF;//1110 1111Delay1ms(500);P2 = 0xDE;//1101 1111Delay1ms(500);P2 = 0xBE;//1011 1111Delay1ms(500);P2 = 0x7E;//0111 1111Delay1ms(500);}
}

四、独立按键控制LED亮灭

(一)独立按键

按键的一端接到单片机的IO口,另一端接地,单片机上电时,所有IO口默认为高电平,所以当按键未按下时保持高电平,当按键按下时则为低电平,寄存器还可以检测IO口的电平状态,读取高低电平,检测按键是否被按下。

sfr是对八位寄存器进行定义的。

sbit是位寄存器,是对每一位进行控制。

当头文件是REGX时,有对位的声明。

当头文件是REG时,没有对位的声明,需要自己定义声明。

(二)C51数据运算

(三)C51基本语句

if、switch表示选择,for、while表示循环,任何复杂的程序都可以由顺序、选择、循环这三个基本功能实现。

for循环主要用于指定次数的循环。

(四)代码示例

#include <REGX52.H>void main()
{
//	P2 = 0xFE;  控制八位寄存器while(1){if(P3_1 == 0){P2_0 = 0;}else{P2_0 = 1;}}
}

五、独立按键控制LED状态

(一)按键的抖动

不同的按键抖动时间不同,消除抖动可以通过硬件解决(较麻烦),也可以通过软件解决(简单 延时即可)。

(二)代码示例

#include <REGX52.H>void Delay(unsigned int xms)	//@11.0592MHz  0~65535
{unsigned char data i, j;//	_nop_();while(xms){i = 2;j = 199;do{while (--j);} while (--i);	xms--;}}void main()
{while(1){if(P3_1 == 0)//按下一直循环,放开跳出循环,松手后led出现操作{Delay(20);while(P3_1 == 0);//若循环体为空,可直接加分号Delay(20);//消除松手抖动P2_0 = ~P2_0;//按下时执行whlie空语句,松开就跳出循环,执行取反操作,亮灯}}
}

六、独立按键控制LED显示二进制

(一)错误代码

IO口上电默认为高电平 1111 1111,再加1就会产生溢出,变为 0000 0000,此时P2再取反,又会变成 1111 1111。

(二)代码示例

为了避免上述代码中出现的错误,可以定义一个变量,对变量进行操作,最后再将变量送给P2口。无符号字符型unsigned char是8位的二进制的数据,与寄存器恰好对应。

#include <REGX52.H>
void Delay(unsigned int xms)	//@11.0592MHz
{unsigned char data i, j;//	_nop_();while(xms--)//与在程序末尾加xms--是一样的效果{i = 2;j = 199;do{while (--j);} while (--i);}
}void main()
{unsigned char LEDNum = 0;//自定义变量 0~255while(1){if(P3_1 == 0){Delay(20);//注意下这个按键结构,按下通电松开断电,所以要做松手检测while(P3_1 == 0);//这边的while,当你没松手时一直按着按键会就进入while循环,防止一直执行下去,去掉的话你会发现灯会一直闪Delay(20);//			P2++;	1111 1111 -> 0000 0000 -> 1111 1111使得灯一直不亮
//			P2 = ~P2;LEDNum++;P2 = ~LEDNum;}}
}

七、独立按键控制LED移位

#include <REGX52.H>void Delay(unsigned int xms)	//@11.0592MHz
{unsigned char data i, j;//	_nop_();while(xms--)//与在程序末尾加xms--是一样的效果{i = 2;j = 199;do{while (--j);} while (--i);}
}unsigned char LEDNum;  //全局变量若不赋初值则默认为零void main()
{P2 = ~0x01;//上电时进行初始化
//	unsigned char//局部变量定义时需要附初始值while(1){if(P3_1 == 0){Delay(20);while(P3_1 == 0);Delay(20);
/*	0000 0001		0x01<<0		按位左移0000 0010		0x01<<10000 0100		0x01<<20000 1000		0x01<<30001 0000		0x01<<40010 0000		0x01<<50100 0000		0x01<<61000 0000		0x01<<7		*/LEDNum++;if(LEDNum>=8)//越界判断{LEDNum = 0;}P2 = ~(0x01<<LEDNum);//P2口是共阳极 所以给0亮 给1灭}if(P3_0 == 0){Delay(20);while(P3_0 == 0);Delay(20);if(LEDNum == 0)//对于无符号字符型减到0后再减会变成255,为了避免这一现象需要提前进行处理LEDNum = 7;elseLEDNum--;P2 = ~(0x01<<LEDNum);//P2口是共阳极 所以给0亮 给1灭			}}
}
http://www.xdnf.cn/news/15742.html

相关文章:

  • ENSP路由综合实验 + 思科(cisco)/华为(ensp)链路聚合实验
  • C++中的vector(2)
  • 基于Python的口腔正畸健康教育聊天机器人开发与评估研究
  • PyCharm + AI 辅助编程
  • 深度学习图像分类数据集—六十种植物病害分类
  • 基于单片机宠物喂食器/智能宠物窝/智能饲养
  • Typecho博客Ajax评论功能实现全攻略
  • 车载诊断架构 --- OEM对于DTC相关参数得定义
  • FastAPI遇上GraphQL:异步解析器如何让API性能飙升?
  • 【iOS】编译和链接、动静态库及dyld的简单学习
  • 5.组合模式
  • Node.js net.Socket.destroy()深入解析
  • 4.循环结构:让电脑做重复的事情
  • 探秘边缘安全架构设计要点解析
  • Redis 如何保证高并发与高可用
  • 【计算机网络架构】树型架构简介
  • 车载传统ECU---MCU软件架构设计指南
  • Netty网络聊天室及扩展序列化算法
  • 2025年睿抗机器人开发者大赛CAIP-编程技能赛(省赛)-RoboCom 世界机器人开发者大赛-本科组
  • FreeRTOS学习笔记之软件定时器
  • 【初识数据结构】CS61B中的基本图算法:DFS, BFS, Dijkstra, A* 算法及其来历用法
  • Java-77 深入浅出 RPC Dubbo 负载均衡全解析:策略、配置与自定义实现实战
  • CS231n-2017 Lecture3线性分类器笔记
  • 时序数据库选型实战:Apache IoTDB技术深度解析
  • 用逻辑回归(Logistic Regression)处理鸢尾花(iris)数据集
  • 移除debian升级后没用的垃圾
  • 电商商品综合排序:从需求分析到实时计算的全方位指南
  • 鸿蒙与web混合开发双向通信
  • The Missing Semester of Your CS Education 学习笔记以及一些拓展知识(三)
  • HTTP性能优化实战