目录
##模式四:点按切换亮灯
#前言
51单片机指兼容英特尔8051的单片机的统称。51单片机在生活中的应用很广泛。以下是我对于51单片机的学习笔记。
#LED的简单操作
##点亮一个LED
1. 在Keil 5中输入以下指令
#include<REGX52.H> //控制LED灯的头文件
void main(){
P2 = 0xfe; //fe表示d1 LED灯
}
P2寄存器中点亮D1二进制表示为‘1111 1110’,用16进制表示则为FE。
同理,若需要点亮D2,则为‘1111 1101’,用16进制表示则为FD。
2. 在stc-isp里下载程序。
程序完成。
##使一个LED灯闪烁
1. 在stc-isp里生成一段延时代码。
2. 使用nop函数需要加入‘intrins.h'头文件。
#include<regx52.h>
#include<intrins.h>
void Delay500ms(void);
void main(){
do{
P2 = 0xFE;
Delay500ms();
P2 = 0xFF;
Delay500ms();
}while(1);
}
void Delay500ms(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
2. 在stc-isp里下载程序。
LED闪烁500ms
##LED流水灯(自定义间隔时间)
#include<regx52.h>
#include<intrins.h>
void Delayxms(unsigned int xms);
void main(){
unsigned int xms = 500;
do{
P2 = 0xFE;
Delayxms(xms);
P2 = 0xFD;
Delayxms(xms);
P2 = 0xFB;
Delayxms(xms);
P2 = 0xF7;
Delayxms(xms);
P2 = 0xEF;
Delayxms(xms);
P2 = 0xDF;
Delayxms(xms);
P2 = 0xBF;
Delayxms(xms);
P2 = 0x7F;
Delayxms(xms);
}while(1);
}
void Delayxms(unsigned int xms) //@12.000MHz
{
while(xms--){
unsigned char data i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
IMG_0581
#51单片机中常用的运算:位运算(图灵完备玩家狂喜版)
- '<<' 按位左移
0100 0011 << 1 == 1000 0110
- '>>' 按位右移
0100 0011 >> 1 == 0010 0001
- '&' 按位与
0001 1000 & 0010 1010 == 0000 1000
- '|' 按位或
0001 1000 & 0010 1010 == 0011 1010
- '^' 按位异或
0001 1000 & 0010 1010 == 0011 0010
- '~' 按位取反
~0001 1000 == 1110 0111
#独立按钮控制LED
##模式一:点按时发光
’regx52.h‘头文件中可以直接控制寄存器的单个位
单片机中默认的IO端口为高电平,所以0代表接通
P3寄存器连接四个独立开关,从左到右依次为P3_1,P3_0,P3_2,P3_3(前两个是反的)
#include <regx52.h>
void main(){
while(1){
if(P3_1 == 0){
P2_0 = 0;
}else{
P2_0 = 1;
}
}
}
LED按键控制1
##模式二:点按切换发光
按键开关存在按键抖动,一般为5~10ms,最多会在20ms内结束,所以添加20ms延时屏蔽按键抖动
#include <regx52.h>
void Delay20ms(void);
void main(){
while(1){
if(P3_1 == 0){
Delay20ms();
while(P3_1 == 0);
Delay20ms();
P2_0 = ~P2_0;
}
}
}
void Delay20ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
LED按键控制2
##模式三:点按切换并显示二进制数
直接对p2寄存器进行操作
#include <regx52.h>
void Delay20ms(void);
void main(){
while(1){
if(~P3_1){
Delay20ms();
while(~P3_1);
Delay20ms();
P2--;
}
}
}
void Delay20ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
LED按键控制3
##模式四:点按切换亮灯
创建num后取反赋值P2
#include <regx52.h>
void Delay20ms(void);
void main(){
unsigned int num = 1;
int count = 0;
while(1){
int num = 1;
int count = 0;
P2 = 0xFE;
while(count < 8){
if(~P3_1){
Delay20ms();
while(~P3_1);
Delay20ms();
num = num<<1;
P2 = ~num;
count ++;
}
}
}
}
void Delay20ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
LED按键控制4
#数码管
##数码管的结构
此51单片机为共阴极数码管,所以可以通过控制阴极来实现控制哪个数码管发光,控制阳极来实现控制数码管的具体显示。正因为数码管的这个特性,所以理论上同一时刻八个数码管只能显示同一个数字。
###阳极端
P0寄存器输入信号到双向缓冲器(用于增大信号和控制信号输入输出对调)后输出给数码管的端口
双向缓冲器引脚功能:
- 1引脚用于判断输出方向(低电平为AtoB,高电平则反之)
- 2-9引脚为A端口参数
- 10引脚为接地负极
- 11-18引脚为B端口参数
- 19,20引脚为正极(整流后)
###阴极端
P22,P23,P24输入到3-8解码器,将八个输出端分别接入八个数码管阴极
##静态数码管显示
构建LEDDisplay函数使数码管显示与主函数分离
例中为在第二个数码管中显示数字‘3’
#include <regx52.h>
void LEDDisplay(unsigned char position,unsigned char num);
void main(){
while(1){
LEDDisplay(2,3);
}
}
void LEDDisplay(unsigned char position,unsigned char num){
unsigned char num_graphic[] = {0x3F, 0x06, 0x5B, 0X4F, 0x66, 0X6D, 0X7D, 0x07,0x7F,0X6F};
switch(position){
case 1:
P2_4 = 0;
P2_3 = 0;
P2_2 = 0;
break;
case 2:
P2_4 = 0;
P2_3 = 0;
P2_2 = 1;
break;
case 3:
P2_4 = 0;
P2_3 = 1;
P2_2 = 0;
break;
case 4:
P2_4 = 0;
P2_3 = 1;
P2_2 = 1;
break;
case 5:
P2_4 = 1;
P2_3 = 0;
P2_2 = 0;
break;
case 6:
P2_4 = 1;
P2_3 = 0;
P2_2 = 1;
break;
case 7:
P2_4 = 1;
P2_3 = 1;
P2_2 = 0;
break;
case 8:
P2_4 = 1;
P2_3 = 1;
P2_2 = 1;
break;
default:
break;
}
P0 = num_graphic[num];
}
##动态数码管显示
前文说过理论上同一时刻数码管显示的数字应该是相同的,但是利用数码管的辉光快速切换亮着的数字与位置,即可达到肉眼看上去是同时亮着的样子。
例中在1号显示‘2’,在2号显示‘3’,在3号显示‘5’。
#include <regx52.h>
#include <intrins.h>
void LEDDisplay(unsigned char position,unsigned char num);
void Delay1ms(void);
void main(){
while(1){
LEDDisplay(2,3);
LEDDisplay(1,2);
LEDDisplay(3,5);
}
}
void Delay1ms(void) //@11.0592MHz
{
unsigned char data i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
void LEDDisplay(unsigned char position,unsigned char num){
unsigned char num_graphic[] = {0x3F, 0x06, 0x5B, 0X4F, 0x66, 0X6D, 0X7D, 0x07,0x7F,0X6F};
switch(position){
case 1:
P2_4 = 0;
P2_3 = 0;
P2_2 = 0;
break;
case 2:
P2_4 = 0;
P2_3 = 0;
P2_2 = 1;
break;
case 3:
P2_4 = 0;
P2_3 = 1;
P2_2 = 0;
break;
case 4:
P2_4 = 0;
P2_3 = 1;
P2_2 = 1;
break;
case 5:
P2_4 = 1;
P2_3 = 0;
P2_2 = 0;
break;
case 6:
P2_4 = 1;
P2_3 = 0;
P2_2 = 1;
break;
case 7:
P2_4 = 1;
P2_3 = 1;
P2_2 = 0;
break;
case 8:
P2_4 = 1;
P2_3 = 1;
P2_2 = 1;
break;
default:
break;
}
P0 = num_graphic[num];
Delay1ms();
P0 = 0; //用于消除移位产生的辉光
}
##数码管驱动方式
- 单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间。
- 专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可。
此单片机为第一种。