01
设计要求
(1)密码为6位长度,初始值是111111。有三次登陆机会,每错一次,红灯及蜂鸣器各亮、响一秒,液晶显示错误信息。错三次后,禁止再登陆。正确登陆后绿灯亮。
(2)可修改密码,但须先正确输入原密码。设置新密码需连续正确输入两次,同时密码须有相应格式,如密码需8位数字。(其余格式,如不能连续8位相同数字、符号*#可作为密码等可根据情况自行设置)。
(3)输入密码时可用*显示已输入密码,用-表示未输入的部分。可设删除按键,可以删除所输入的数字;有取消按键,可以取消修改密码,取消登陆等功能。
02
程序
#include
#include
#include "stdio.h"
#include "string.h"
#define uchar unsigned char
#define uint unsigned int
// 定义LCD引脚
sbit LCM_RW=P2^5;
sbit LCM_RS=P2^6;
sbit LCM_E=P2^7;
#define LCM_Data P0
// 用于检测LCM状态字中的Busy标识
#define Busy 0x80
// 按键定义
sbit K1=P1^0;
sbit K2=P1^1;
sbit K3=P1^2;
sbit K4=P1^3;
sbit K5=P1^4;
sbit K6=P1^5;
sbit K7=P1^6;
sbit K8=P1^7;
sbit red=P2^0;
sbit green=P2^1;
sbit beep=P2^2;
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void Delay5Ms(void);
void keyscan();
void xianshi();
void keyscan1();
void xianshi1();
void T0_init();
uchar jiance_geshi(uchar *a);
unsigned char code shuru[] ={"shuru:"};
unsigned char code right[] = {"right"};
unsigned char code error[] = {"error"};
unsigned char code fail[] = {" fail "};
unsigned char code kongbai[] ={" "};
unsigned char code g1[] = "------";
uchar mima_chushi[6]="111111";
uchar mima[6]="";
uchar mima_xiu[6]="";
// 变量的定义
uchar mima_num;
uchar flag_num,flag_correct,flag_xiugai,flag_error,flag_xiu1,flag_xiu2,flag_quxiao;
// 5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
void delay(unsigned int i)
{
unsigned int j;
unsigned char k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
// 写数据
void WriteDataLCM(unsigned char WDLCM)
{
// 检测忙
ReadStatusLCM();
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
// 若晶振速度太高可以在这后加小的延时
LCM_E = 0;
// 延时
LCM_E = 0;
LCM_E = 1;
}
// 写指令
// BuysC为0时忽略忙检测
void WriteCommandLCM(unsigned char WCLCM, BuysC)
{
// 根据需要检测忙
if (BuysC) ReadStatusLCM();
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
// 读数据
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}
// 读状态
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
// 检测忙信号
while (LCM_Data & Busy);
return(LCM_Data);
}
// LCM初始化
void LCMInit(void)
{
LCM_Data = 0;
// 三次显示模式设置,不检测忙信号
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); // 显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); // 关闭显示
WriteCommandLCM(0x01,1); // 显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}
// 按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) //Y 为1 则是第二行
{
Y &= 0x1;
X &= 0xF; // 限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; // 当要显示第二行时地址码+0x40;
X |= 0x80; // 算出指令码
WriteCommandLCM(X, 1); //发命令字
WriteDataLCM(DData); //发数据
}
// 按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF;
// 限制X不能大于15,Y不能大于1
//若到达字串尾则退出
while (DData[ListLength]>0x19)
{
// X坐标应小于0xF
if (X <= 0xF)
{
// 显示单个字符
DisplayOneChar(X, Y, DData[ListLength]);
ListLength++;
X++;
}
}
}
void qing_shuzu(uchar *a)
{
uchar i,length;
length=strlen(a);
for(i=0;i4)
{
return 0;
}
else return 1;
}
void main()
{
mima_num=0;
flag_xiu2=0;
beep=0;
T0_init();
LCMInit();
DisplayListChar(0, 0, shuru);
DisplayListChar(6, 0, g1);
while(1)
{
if(flag_xiu2==1) //
{
WriteCommandLCM(0x01,1); //显示清屏
DisplayListChar(0, 0, shuru);
DisplayListChar(6, 0, g1);
flag_xiu2=0;
}
keyscan();
xianshi();
if(mima_num==6) //6位输完 开始检测
{
if(strcmp(mima,mima_chushi)==1) //strcmp
{
DisplayListChar(0, 1, error);//错误 strcmp为1 因为mima_chushi 在code区
red=0;
beep=1;
flag_num++; //错误次数
mima_num=0;
TR0=1;
}
else
{
green=0;
TR0=1; //开启定时器
mima_num=0;
flag_correct=1;
}
}
luoji_xianshi();
if(flag_correct)
{WriteCommandLCM(0x01,1); //显示清屏
DisplayListChar(0, 0, right);}
else DisplayListChar(0, 0, shuru);
while(flag_correct) //进入登陆装填
{
if(flag_xiu2==0){
keyscan1();
if(flag_quxiao) //修改密码取消按键
{
DisplayListChar(0,1,kongbai);
flag_quxiao=0;
}
if(flag_xiugai==1)
{
keyscan();
xianshi1();
if(mima_num==6)
{
if(!jiance_geshi(mima)) //检测密码是否符合格式 1表示符合
{
DisplayListChar(9, 0, error); //0 不符合 才显示错误
flag_xiugai=0;
qing_shuzu();
}
else
{
DisplayListChar(0, 1, " second:" );
strcpy(mima_xiu,mima); //符合进入下一步
flag_xiu1=1;
mima_num=0; //为下一次保存密码准备
while(flag_xiu1)
{
keyscan();
xianshi1();
if(mima_num==6)
{
if(strcmp(mima,mima_xiu)==0) //strcmp 比较这两次密码是否一致
{
strcpy(mima_chushi,mima);
flag_xiu1=0;
delay(1000);
mima_num=0;
flag_xiugai=0;
flag_xiu2=1;
}
else
{
DisplayListChar(6, 0, "mistake ");
flag_xiu1=0;
mima_num=0;
flag_xiugai=0;
}
}
}
}
}
}
}
}
}
}
/*中断服务程序*/
void timer0() interrupt 1
{
uchar count;
TH0 =0x4b;
TL0 =0xfd; //50ms
count++;
if (count == 20) //1S
{
count=0;
red=1;
beep=0;
green=1;
TR0=0;
}
}
03
具体操作流程、源码、原理图百度网盘链接:
链接:https://pan.baidu.com/s/1hrss6_tFSxNTgNKiGJiclg
提取码:xxzk