提起51单片机,就绕不过B站up江协科技的教学视频:51单片机入门教程

无论什么时候打开,哪怕是现在AIcoding大行其道的2026年,都能看到几百人同时在线观看,可谓经典经久不衰。
本篇为 51 单片机入门实验的个人学习笔记,内容基于 B 站教学视频整理,主要是基于单片机电路图编程的C语言代码笔记。相关代码工程请前往视频源地址自行下载。Up 主讲解逻辑清晰、由浅入深,非常适合入门同学学习,在此强烈推荐给大家。本文仅作为个人学习记录与参考,细节原理与调试过程建议观看原视频学习,相信会有更大收获。
主要是记录个人的单片机电路图学习笔记和代码心得,本篇对应为入门的2-7实验。
2-1点亮一个LED
电路图:

这是一个共阳极接法的 8 路 LED 指示灯电路,核心由三部分组成:8 个 LED 灯(D1~D8)、
2 个 4 位排阻(RP9、RP10,阻值 470Ω)、连接到单片机 P2 口(P2.0~P2.7)的 IO 口。
如果要只点亮D1,则P2=0xFE。
代码:
c
#include <REGX52.H>
void main()
{
P2=0xFE; //1111 1110
}
现象:仅D1常亮
2-2LED闪烁
主要是通过软件延时计算器生成个延时函数后调用。
代码:
c
#include <REGX52.H>
#include <INTRINS.H>
void Delay50ms(void) //@12.000MHz
{
unsigned char data i, j;
i = 98;
j = 67;
do
{
while (--j);
} while (--i);
}
void main()
{
while(1)
{
P2=0xFE;
Delay50ms();
P2=0xFf;
Delay50ms();
}
}
现象:仅D1闪烁
2-3LED流水灯
主要是生成了个自定义延时时间的函数。
代码:
c
#include <REGX52.H>
#include <INTRINS.H>
void Delayxms(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2; //51单片机晶振执行指令的速度是固定
j = 239; //i=2,j=239时,cpu空转的时间正正好是1毫秒
do
{
while (--j);
} while (--i);
xms--; //xms=xms-1
}
}
void main()
{
while(1)
{
P2=0xFE; //1111 1110
Delayxms(25);
P2=0xFD; //1111 1101
Delayxms(25);
P2=0xFB; //1111 1011
Delayxms(25);
P2=0xF7; //1111 0111
Delayxms(25);
P2=0xEF; //1110 1111
Delayxms(25);
P2=0xDF; //1101 1111
Delayxms(2);
P2=0xBF; //1011 1111
Delayxms(25);
P2=0x7F; //0111 1111
Delayxms(25);
}
}
现象:流水灯效果同时数码管也受影响。
原因:

P22,P23,P24通过74HC138译码器同时控制LED1-8。
流水灯代码直接操作整个 P2 端口,改变了 P2.1/P2.2/P2.3 这三个数码管位选引脚的电平,导致 74HC138 译码器误选通数码管,从而和流水灯效果互相干扰。
3-1独立按键控制LED
实现功能:当K2被按下时,D1常量。
电路图;


K2对应端口P30,只要P30=0,说明被按下,那么这时给P20赋值0。
注意:除了P0端口外,所有端口在不赋值的情况下值都默认是1.
代码:
c
#include <REGX52.H>
void main()
{
while(1)
{
if(P3_0==0)
{
P2_0=0;
}
else
{
P2_0=1;
}
}
}
3-2独立按键控制LED状态
思路:如果检测到K2被按下,延时20分钟在检测K2,如果松手了,将P20取反。
代码:
c
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1)
{
if(P3_1==0)
{
Delay(20); // Keys away shaking
while(P3_1==0);
Delay(20); // Detection of let go
P2_0=~P2_0;
}
}
}
3-3 独立按键控制LED显示二进制
思路:定义一个char,unsigned char 是 51 单片机常用的变量类型,占用 1 个字节(8 位二进制)。LED低电平有效,让他等于char取反。
代码:
c
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
unsigned char LEDNum=0; // char max num is 255
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
LEDNum++;
P2=~LEDNum;
}
}
}
3-4独立按键控制LED移位
思路:2MHz 晶振执行一行 C 语言 = 几微秒,人眼能看到的最小时间 = 20ms 以上。我们创建1个char记录K1、K2按的情况,K1按了则减,K2按了则加,然后给P2赋值初值使D1亮,根据char执行移位,P2赋值初值使D1亮只有几微秒,人眼看不到D1亮。
代码;
c
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
unsigned char LEDNum; // The global variable
void main()
{
P2=~0x01; //int P2
while(1)
{
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
LEDNum++;
if(LEDNum>=8)
LEDNum=0;
P2=~(0x01<<LEDNum); // 0x01 of P2 need shift to the left LEDNum, and get the not
}
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
if(LEDNum==0)
LEDNum=7;
else
LEDNum--;
P2=~(0x01<<LEDNum);
}
}
}
4-1静态数码管显示
思路:LED8实际上再物理位置是第一个数码管,所以要点亮第一个数码管实际上是拉低LED8,74HC138译码器输出是低电平有效,使其输入P2_4=1;P2_3=1;P2_2=1;。其他同理创建个函数控制某个数码管显示数字0-9和字幕a-f。
电路图:

代码:这里最后是第三位显示11,即b
c
#include <REGX52.H>
unsigned char NixieTable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71, 0x00};
void Nixie(unsigned char Location,Number)
{
switch(Location)
{
case 1:
P2_4=1;P2_3=1;P2_2=1;break;
case 2:
P2_4=1;P2_3=1;P2_2=0;break;
case 3:
P2_4=1;P2_3=0;P2_2=1;break;
case 4:
P2_4=1;P2_3=0;P2_2=0;break;
case 5:
P2_4=0;P2_3=1;P2_2=1;break;
case 6:
P2_4=0;P2_3=1;P2_2=0;break;
case 7:
P2_4=0;P2_3=0;P2_2=1;break;
case 8:
P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number];
}
void main()
{
// P24=1; //Controls a nixie tube
// P23=0;
// P22=1;
// P0=0x7D; //value is 6
Nixie(2,3);
Nixie(1,8);
Nixie(3,10);
Nixie(3,11);
while(1)
{
}
}
4-2动态数码管显示
思路:每隔1ms轮番点亮要点的数码管。
代码:
c
#include <REGX52.H>
unsigned char NixieTable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71, 0x00};
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void Nixie(unsigned char Location,Number)
{
switch(Location)
{
case 1:
P2_4=1;P2_3=1;P2_2=1;break;
case 2:
P2_4=1;P2_3=1;P2_2=0;break;
case 3:
P2_4=1;P2_3=0;P2_2=1;break;
case 4:
P2_4=1;P2_3=0;P2_2=0;break;
case 5:
P2_4=0;P2_3=1;P2_2=1;break;
case 6:
P2_4=0;P2_3=1;P2_2=0;break;
case 7:
P2_4=0;P2_3=0;P2_2=1;break;
case 8:
P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number];
Delay(1); // Shadow elimination
P0=0x00; // reset
}
void main()
{
while(1)
{
Nixie(1,1);
Nixie(2,2);
Nixie(3,3);
}
}
5-1模块化编程
功能:模块化编程使8个数码管显示12345678。
思路:编写main使其每个数码管再8ms的周期每隔1ms显示对应数字。调用编写的两个.c子函数。要搭配.h。
代码:
主函数:
c
#include <REGX52.H>
#include "Delay.h" // 使用双引号,有优先查询工作目录
#include "Nixie.h"
void main()
{
while(1)
{
Nixie(1,1);
Nixie(2,2);
Nixie(3,3);
Nixie(4,4);
Nixie(5,5);
Nixie(6,6);
Nixie(7,7);
Nixie(8,8);
}
}
Delay.c:
c
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
Delay.h:
c
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
Nixie.c:
c
#include <REGX52.H>
#include "Delay.h"
unsigned char NixieTable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71, 0x00};
void Nixie(unsigned char Location,Number)
{
switch(Location)
{
case 1:
P2_4=1;P2_3=1;P2_2=1;break;
case 2:
P2_4=1;P2_3=1;P2_2=0;break;
case 3:
P2_4=1;P2_3=0;P2_2=1;break;
case 4:
P2_4=1;P2_3=0;P2_2=0;break;
case 5:
P2_4=0;P2_3=1;P2_2=1;break;
case 6:
P2_4=0;P2_3=1;P2_2=0;break;
case 7:
P2_4=0;P2_3=0;P2_2=1;break;
case 8:
P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number];
Delay(1); // Shadow elimination
P0=0x00; // reset
}
Nixie.h:
c
#ifndef __NIXIE_H__
#define __NIXIE_H__
void Nixie(unsigned char Location,Number);
#endif
5-2LCD1602调试工具
思路,通过LCD1602.c实现控制在第几行第几个显示数字,字母等内容。Delay.c和.h可以复制粘贴过来。
功能:实现个在第一行前三个位置显示个三位十进制数,每隔1秒加一。
主函数:
c
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
//void main()
//{
// LCD_Init();
// LCD_ShowChar(1,1,'B');
// LCD_ShowString(1,3,"Hello");
// LCD_ShowNum(1,9,123,3);
// LCD_ShowSignedNum(1,13,-66,2);
// LCD_ShowHexNum(2,1,0xA8,2);
// LCD_ShowBinNum(2,4,0xAA,8);
// LCD_ShowChar(2,13,'A');
// while(1)
// {
//
// }
//}
int Result=0;
void main()
{
LCD_Init();
while(1)
{
Result++;
Delay(1000);
LCD_ShowNum(1,1,Result,3);
}
}
LCD1602.c:
c
#include <REGX52.H>
//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
//函数定义:
/**
* @brief LCD1602延时函数,12MHz调用可延时1ms
* @param 无
* @retval 无
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
/**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置开始显示所给字符串
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/**
* @brief 在LCD1602指定位置开始显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~65535
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-32768~32767
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFF
* @param Length 要显示数字的长度,范围:1~4
* @retval 无
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
/**
* @brief 在LCD1602指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}
LCD1602.h:
c
#ifndef __LCD1602_H__
#define __LCD1602_H__
//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
#endif
6-1矩阵键盘
电路图:

功能:让显示屏显示哪个按键被按下。
思路,通过MatrixKey获得按下按键编号,通过按列扫描的方法判断哪个按键被按下。
然后在LCE第二行第三列显示,给其两位数空间。同理Delay和LCD1602可以复制过来,这体现了模块化编程优势。
主函数:
c
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey.h"
unsigned char KeyNum;
void main()
{
LCD_Init();
// LCD_ShowChar(1,1,'B');
LCD_ShowString(1,3,"MatrixKey:");
// LCD_ShowNum(1,9,123,3);
// LCD_ShowSignedNum(1,13,-66,2);
// LCD_ShowHexNum(2,1,0xA8,2);
// LCD_ShowBinNum(2,4,0xAA,8);
// LCD_ShowChar(2,13,'A');
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
LCD_ShowNum(2,3,KeyNum,2);
}
}
}
MatrixKey.c:
c
#include <REGX52.H>
#include "Delay.h"
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF;
P1_3=0; // 补全:P1_3
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
P1=0xFF;
P1_2=0; // 补全:P1_2
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
P1=0xFF;
P1_1=0; // 补全:P1_1
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
P1=0xFF;
P1_0=0; // 补全:P1_0
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber; // 记得返回值!
}
MatrixKey.h:
c
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__
unsigned char MatrixKey();
#endif
6-2矩阵键盘密码锁
实现功能:按键输入密码,按11确认,按12清空输入。
思路:复用之前的Delay,LCD1602,MatrixKey模块。
主函数:
c
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Password, Count;
void main()
{
LCD_Init();
// LCD_ShowChar(1,1,'B');
LCD_ShowString(1,1,"Password:");
// LCD_ShowNum(1,9,123,3);
// LCD_ShowSignedNum(1,13,-66,2);
// LCD_ShowHexNum(2,1,0xA8,2);
// LCD_ShowBinNum(2,4,0xAA,8);
// LCD_ShowChar(2,13,'A');
while(1)
{
KeyNum=MatrixKey();
if(KeyNum)
{
if(KeyNum<=10) // 如果S1~S10按键按下,输入密码
{
if(Count<4) // 密码四位数
{
Password*=10; // 密码左移一位,这样就可以依次输入密码
Password+=KeyNum%10; // 获取一位密码,加入到原密码,此时10为0
Count++;
}
}
LCD_ShowNum(2,1,Password,4);
if(KeyNum==11) // 确认
{
if(Password==4399)
{
LCD_ShowString(1,14,"OK ");
Password=0;
Count=0;55
LCD_ShowNum(2,1,Password,4);
}
else
{
LCD_ShowString(1,14,"ERR");
Password=0;
Count=0;
LCD_ShowNum(2,1,Password,4);
}
}
if(KeyNum==12) //取消
{
Password=0;
Count=0;
LCD_ShowString(1,14," ");
LCD_ShowNum(2,1,Password,4);
}
}
}
}
7-1按键控制流水灯模式
思路:编写Key获得按下按键编号,如果K1按键按下则切换流水灯方向。引入中断函数,每个1ms中断检查模式状态,根据模式状态移位控制流水灯。
复用Delay,新建Key和Timer0。
主函数:
c
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H> // 包含_crol_/_cror_循环移位函数
unsigned char KeyNum,LEDMode;
void main()
{
P2=0xFE;
Timer0_Init();
while(1)
{
KeyNum=Key(); //获取独立按键键码
if(KeyNum) //如果按键按下
{
if(KeyNum==1) //如果K1按键按下
{
LEDMode++; //模式切换,按1下按键是模式1,按2下是模式0,默认模式0
if(LEDMode>=2)LEDMode=0;
}
}
}
}
void Timer0_Routine() interrupt 1 //中断函数标识,含优先级
{
static unsigned int T0Count; //静态变量,拥有局部作用域,全局生命周期
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++; //T0Count计次,对中断频率进行分频
if(T0Count>=500)//分频500次,500ms
{
T0Count=0;
if(LEDMode==0) //模式判断
P2=_crol_(P2,1); //LED输出(循环左移函数,即使流水灯循环左移)
if(LEDMode==1)
P2=_cror_(P2,1);
}
}
/* 此为按键控制LED代码
void main()
{
Timer0_Init();
while(1)
{
KeyNum=Key();
if (KeyNum) //如果按键按下
{
if (KeyNum==1) P2_1=~P2_1;
if (KeyNum==2) P2_2=~P2_2;
if (KeyNum==3) P2_3=~P2_3;
if (KeyNum==4) P2_4=~P2_4;
}
}
}
*/
/* 此为LED1灯每隔1s亮灭
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
Timer0_Init(); //教程中是用TH0=64535/256;TL0=64535%256;,我选择直接用初始化函数,效果一样
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
P2_0=~P2_0;
}
}
*/
Key.c:
c
#include <REGX52.H>
#include "Delay.h"
unsigned char Key()
{
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
Key.h:
c
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();
#endif
Timer0.c:
c
#include <REGX52.H>
void Timer0_Init() //
{
// TMOD=0x01; //0000 0001
TMOD=TMOD&0xF0;//把TMOD的低四位清零,高四位保持不变
TMOD=TMOD|0x01;//把TMOD的最低位置1,高四位保持不变
TF0=0;
TR0=1;
TH0=0xFC;
TL0=0x18;
ET0=1;
EA=1;
PT0=0;
}
Timer0.h:
c
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0_Init(void);
#endif