51 单片机
参考视频:江协科技https://www.bilibili.com/video/BV1Mb411e7re
参考资料:STC官网STC单片机专业供应商 (stcmicro.com)
1. 简介
1.1 概念
什么是单片机
单片机种类
单片机应用
1.2 环境准备
驱动安装
打开普中科技给的资源包里,会有驱动的
如果失败,点击安装失败解决方法
如果驱动已经安装成功了,能够检查到。只要没有黄的感叹号,都是连接成功了
辅助软件安装stc-isp
这边能显示串口号,就说明连接成功了
Keil5 安装
Keil公司是一家业界领先的微控制器(MCU)软件开发工具的独立供应商。Keil公司由两家私人公司联合运营,分别是德国慕尼黑的Keil Elektronik GmbH和美国德克萨斯的Keil Software Inc。Keil公司制造和销售种类广泛的开发工具,包括ANSI C编译器、宏汇编程序、调试器、连接器、库管理器、固件和实时操作系统核心(real-time kernel)。有超过10万名微控制器开发人员在使用这种得到业界认可的解决方案。Keil公司在2005年被ARM公司收购。KEIL软件为适应51内核和ARM内核,KEIL版本分为KEIL C51和MDK-ARM。KEIL MDK目前最新的版本为9.61。
随便写写,都写上就行
Keil5破解
1.3 开发板简介
序号 | 板载资源 | |
---|---|---|
1 | 数码管模块 | 2个四位一体共阴数码管,可显示8位数字字符,如时钟、密码等 |
2 | LCD1602接口 | 兼容LCD1602/LCD9648液晶屏,可显示数字字符等 |
3 | LCD12864接口 | 兼容LCD9648/MiniLCD12864/带字库LCD12864液晶,可显示汉字/图像等 |
4 | 8*8LED点阵 | 可显示数字/字符/图形等 |
5 | LED模块 | 8个LED,可实现流水灯等花样显示 |
6 | 矩阵按键 | 4*4矩阵按键,可作计算器、密码锁等应用的输入装置 |
7 | 红外接收头 | NEC协议,可实现遥控 |
8 | DS18B20温度传感器 | 可实现温度采集控制等 |
9 | NRF24L01接口 | 可实现2.4G远程遥控通信 |
10 | 独立按键 | 4个按键,可作按键输入控制 |
11 | MicroUSB接口 | 可作电源输入、程序下载等 |
12 | USB转TTL模块 | CH340C芯片,可作电脑USB与单片机串口下载和通信 |
13 | 3.3V电源模块 | ASM1117-3.3芯片,将5V转为3.3V供用户使用 |
14 | 电源开关 | 系统电源控制开关 |
15 | ADC/DAC模块 | XPT2046芯片作为ADC,LM358+PWM作为DAC,可采集外部模拟信号和输出模拟电压 |
16 | EEPROM模块 | AT24C02芯片,可存储256字节数据,掉电不丢失 |
17 | 复位按键 | 系统复位 |
18 | 无源蜂鸣器 | 可作报警提示、音乐等 |
19 | DS1302时钟模块 | DS1302芯片,可作时钟发生 |
20 | 步进电机驱动模块 | ULN2003芯片,可作直流电机、28BYJ48步进电机驱动 |
21 | STC89Cxx单片机座及IO | 固定单片机,并将所有I0引出,方便用户二次开发 |
22 | TFTLCD模块接口 | 与3号接口组合可连接TFTLCD触摸屏,可实现酷炫GUI人机 |
23 | 74HC595 | 扩展I0,控制LED点阵 |
24 | 74HC245 | 驱动数码管段选显示 |
25 | 74HC138 | 驱动数码管位选显示 |
2. 入门-LED灯
概念
2-1 点亮一个LED灯
LED灯为啥低点位才亮
由于单片机的I/O口的结构决定了它灌电流能力较强,所以都采用低电平点亮led的方式。其实,采用低电平驱动LED,只是为了简化单片机接口的设计,如果采用接口元件,则高电平驱动和低电平驱动是同样的效果,另外,低电平驱动也简化了控制代码,避免了单片机上电复位时端口置高电平后对led的影响。
LED具有单向导电性,当LED的正端接了高电位,负端连接了低电位,且正负端电位差超过1.8V以上时,LED就会亮起来。
创建项目
选择合适的编译器
创建成功如下所示
编写代码
如果你觉得字体太小,可以按照以下操作
编写代码
#include <REGX52.h>
void main()
{
P2=0xFE; //1111 1110 0表示低点位,LED在低点位的情况下才亮灯
}
解释一下P0啥意思。C51中的sfr,sbit
-
sfr (special function register)特殊功能寄存器声明
例:sfr PO =0x80;物理地址为0x80声明P0口寄存器,
-
sbit (special bit) :特殊位声明
例:sbit PO_1=0x81;或 sbit p0_1=POA1;
声明PO寄存器的第1位
可位寻址/不可位寻址:在单片机系统中,操作任意寄存器或者某一位的数据时,必须给出其物理地址,又因为一个寄存器里有8位所以位的数量是寄存器数量的8倍,单片机无法对所有位进行编码故每8个寄存器中,只有一个是可以位寻址的。对不可位寻址的寄存器,若要只操作其中一位而不影响其它位时,可用“&=”、“=”“^=”的方法进行位操作
点击编译,输出hex文件
编译成功,
查看是否成功输出hex文件,在文件夹的Objects下
上传代码至单片机
重启单片机后,会发现灯亮了
2-2 LED闪烁
根据板子-生成延时代码
编写代码
#include <REGX52.H>
#include <INTRINS.H>
void Delay500ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
_nop_();
i = 4;
j = 129;
k = 119;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1){
P2=0xFE;
Delay500ms();
P2=0xFF;
Delay500ms();
}
}
2-3 LED流水灯
#include <REGX52.H>
#include <INTRINS.H>
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1){
P2=0xFE; // 1111 1110
Delay1ms(500);
P2=0xFD; // 1111 1101
Delay1ms(500);
P2=0xFB; // 1111 1011
Delay1ms(500);
P2=0xF7; // 1111 0111
Delay1ms(500);
P2=0xEF; // 1110 1111
Delay1ms(500);
P2=0xDF; // 1101 1111
Delay1ms(500);
P2=0xBF; // 1011 1111
Delay1ms(500);
P2=0x7F; // 0111 1111
Delay1ms(500);
}
}
3、 独立按键
3-1 独立按键控制LED亮灭
独立按键
#include<REGX52.h>
void main()
{
while(1){
if(P3_1==0){
// 当第一个独立按键被按下时
p2_0=0; // 第一个灯就会亮
}else{
p2_0=1;
}
}
}
简化版
#include<REGX52.h>
void main()
{
P2_0=P3_1;
}
3-2 独立按键控制LED状态
注意事项
所以需要20ms来延时抖动
#include <REGX52.H>
#include <INTRINS.H>
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1){
if(P3_1==0){
Delay1ms(20);
while(P3_1==0);
Delay1ms(20);
P2_0=~P2_0;
}
}
}
3-3 独立按键控制LED显示二进制
#include <REGX52.H>
#include <INTRINS.H>
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1){
if(P3_1==0){
Delay1ms(20);
while(P3_1==0);
Delay1ms(20);
P2--;
}
}
}
3-4 独立按键控制LED移位
#include <REGX52.H>
#include <INTRINS.H>
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
unsigned char LEDnumber;
P2=~0x01;
while(1){
if(P3_1==0){
Delay1ms(20);
while(P3_1==0);
Delay1ms(20);
LEDnumber++;
if(LEDnumber>=8){
LEDnumber=0;
}
P2=~(0x01<<LEDnumber);
}
if(P3_0==0){
Delay1ms(20);
while(P3_0==0);
Delay1ms(20);
if(LEDnumber==0){
LEDnumber=7;
}else{
LEDnumber--;
}
P2=~(0x01<<LEDnumber);
}
}
}
4、数码管
概念
什么是数码管
LED数码管: 数码管是一种简单、廉价的显示器,是由
多个发光二极管封装在一起组成“8”字型的器件
。
按照发光二极管段数可以7段数码管和8段数码管,二者区别呢?就是8段数码管多了一个dp管,表示小数点。
按照发光二极管连接方式,可以分为2种,第一种是,所有的阴极连在一块,叫做
共阴极
,还有一种是,所有的阳极连在一块,叫做共阳极
- 共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极 COM 接到+5V
- 共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM) 的数码管,共阴数码管在应用时应将公共极 COM 接到地线GND上
数码管引脚定义-显示原理
电路设计
为什么需要38译码器
这里我们看到U5 CBA的配置。这里用来把3位数字转换成8位 比如 5 代表3位 101 转换成8位 0001 0000
CBA就表示3位 101 C表示第一位的1 B表示第二位的0 A表示第三位的1
表示选中了LED5
为什么需要74HC245
4-1 静态数码管显示6
让数码管显示6
#include <REGX52.H>
void main()
{
P2_4=1;
P2_3=0;
P2_2=1;
P0=0x7D; //
}
理由如下
- dp表示 数码管上的小数点,因为不需要显示,所以对应的是0
- P07对应高位,P0寄存器正确的读法是 P07-P00 。对应的数据位 0111 1101 对应的16进制位 7D
#include <REGX52.H>
#include <INTRINS.H>
unsigned char NixmeTable[]={
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0x77,0x7C,0x39,0x5E,0x79,0x71,0x00
};
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
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=NixmeTable[number];
}
void main()
{
Nixie(7,2);
while(1){
}
}
4-2 动态数码管显示
#include <REGX52.H>
#include <INTRINS.H>
unsigned char NixmeTable[]={
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0x77,0x7C,0x39,0x5E,0x79,0x71,0x00
};
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
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=NixmeTable[number];
}
void main()
{
while(1){
Nixie(2,1);
Nixie(3,2);
Nixie(4,3);
}
}
这种情况下会出现消影问题
位选 段选 位选 段选 位选 段选 位选 段选 位选 段选
正常情况下, 是一段位选 段选 ,一段 位选 段选 。但是程序运行太快,会出现一段的 段选 位选 ,即橘色的部分。这样子,数字就会串号了
解决办法
位选 段选 清零 位选 段选 清零 位选 段选 清零 位选 段选 清零 位选 段选
#include <REGX52.H>
#include <INTRINS.H>
unsigned char NixmeTable[]={
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0x77,0x7C,0x39,0x5E,0x79,0x71,0x00
};
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
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=NixmeTable[number];
Delay1ms(5);
P0=0x00;
}
void main()
{
while(1){
Nixie(2,1);
Nixie(3,2);
Nixie(4,3);
}
}
单片机直接扫描:硬件设备简单,但是会耗费大量的单片机CPU时间。
专用驱动芯片,内部自带显存,扫描电路,单片机只需要告诉他显示什么即可
5、模块化
5-1 模块化编程
首先进行新建工程
创建Delay.c 文件
#include <INTRINS.H>
void Delay1ms(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
然后创建头文件
创建.h文件后,会发现文件里面啥都没有。所以需要添加已经存在的文件,才能显示
最后发现工程目录为
main文件夹内容
#include <REGX52.h>
#include "Delay.h"
void main()
{
Delay1ms(10);
}
所有函数如下
5-2 LCD1602调试工具
模块化LCD
LCD1602.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
#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
main.c
#include <REGX52.h>
#include "LCD1602.h"
void main()
{
LCD_Init();
LCD_ShowString(1,1,"A");
while(1)
{
}
}
注意事项
- LCD板子没有插进入,千万别返回来擦进入
- 延时函数,LCD1602.h里面的函数得写对
- 变阻器,需要自己调节,调整亮度
- 程序需要重新下载,才能显示
下面是我的错误尝试。引以为戒
6、矩阵键盘
基本概念
- 在键盘中按键数量较多时,为了减少I/0口的用,通常将按键排列成矩阵形式
- 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态
6-1 矩阵键盘显示
项目目录结构如下
MatrixKey.c
#include <REGX52.h>
#include "Delay.h"
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF;
P1_3=0;
if(P1_7==0){
Delay1ms(20);while(P1_7==0);Delay1ms(20);KeyNumber=1;}
if(P1_6==0){
Delay1ms(20);while(P1_6==0);Delay1ms(20);KeyNumber=5;}
if(P1_5==0){
Delay1ms(20);while(P1_5==0);Delay1ms(20);KeyNumber=9;}
if(P1_4==0){
Delay1ms(20);while(P1_4==0);Delay1ms(20);KeyNumber=13;}
//
P1=0xFF;
P1_2=0;
if(P1_7==0){
Delay1ms(20);while(P1_7==0);Delay1ms(20);KeyNumber=2;}
if(P1_6==0){
Delay1ms(20);while(P1_6==0);Delay1ms(20);KeyNumber=6;}
if(P1_5==0){
Delay1ms(20);while(P1_5==0);Delay1ms(20);KeyNumber=10;}
if(P1_4==0){
Delay1ms(20);while(P1_4==0);Delay1ms(20);KeyNumber=14;}
P1=0xFF;
P1_1=0;
if(P1_7==0){
Delay1ms(20);while(P1_7==0);Delay1ms(20);KeyNumber=3;}
if(P1_6==0){
Delay1ms(20);while(P1_6==0);Delay1ms(20);KeyNumber=7;}
if(P1_5==0){
Delay1ms(20);while(P1_5==0);Delay1ms(20);KeyNumber=11;}
if(P1_4==0){
Delay1ms(20);while(P1_4==0);Delay1ms(20);KeyNumber=15;}
P1=0xFF;
P1_0=0;
if(P1_7==0){
Delay1ms(20);while(P1_7==0);Delay1ms(20);KeyNumber=4;}
if(P1_6==0){
Delay1ms(20);while(P1_6==0);Delay1ms(20);KeyNumber=8;}
if(P1_5==0){
Delay1ms(20);while(P1_5==0);Delay1ms(20);KeyNumber=12;}
if(P1_4==0){
Delay1ms(20);while(P1_4==0);Delay1ms(20);KeyNumber=16;}
return KeyNumber;
}
matrixKey.h
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__
unsigned char MatrixKey();
#endif
main.c
#include <REGX52.h>
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"A");
while(1)
{
KeyNum=MatrixKey();
if(KeyNum){
LCD_ShowNum(2,1,KeyNum,2);
}
}
}
6-2 矩阵键盘密码锁
main.c代码如下
#include <REGX52.h>
#include "LCD1602.h"
#include "MatrixKey.h"
unsigned char KeyNum;
unsigned int Password,Count;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Password")