A. c语言题目 锁屏密码,如何避免时间超时,简洁的方法
这就是一道模拟题,不涉及什么算法,不大可能超时。如果超时可能是你方法不对。
#include<stdio.h>
int main()
{
char s[20];
int n;
while(scanf("%d", &n), n!=0)
{
scanf("%s", s);
for(int i=0; i<n; i++)
{
int j = (s[i]-(s[i]<'s'?'a':'b'))/3+2;
if(j>9) j=9;
printf("%d", j);
}
printf("\n");
}
return 0;
}
B. 用单片机C语言控制6位密码锁。要求有一个清除键和确认键,密码输错了会有报警音。请高手帮助了
我找到了一个,来自《51单片机C语言应用技术开发大全》
SCH图正在绘制中。。。
#include <REGX51.H>//51单片机的头文件
typedef unsigned char uchar; //类型定义,定义uchar类型
typedef unsigned int uint; //类型定义,定义uint 类型
//键盘子程序相关说明。
#define BLANKCHAR 10 //定义空白常量
#define PCHAR 11 //定义字符P常量
#define OPENCHAR 12 //定义开锁字符常量
#define ALARMCHAR 13 //定义字符A常量
#define LINECHAR 14 //定义字符-常量
#define BACKKEY 0X0D //定义退格键常量
#define ENTERKEY 0X0F //定义确认键常量
#define LOCKKEY 0X0E //定义闭锁键常量
#define NO_KEY 20 //定义无按键返回值
#define KEYPORT P2 //定义键盘端口
//Delay1Ms
void Delay1Ms()
{
uint i;
for (i=0;i<1000;i++);
}
//定义按键扫描码表 按键扫描时,4位列线和4位行线组成字节数据表
uchar code KEYCODE[]=
{0XEE,0XED,0XEB,0XE7,
0XDE,0XDD,0XDB,0XD7,
0XBE,0XBD,0XBB,0XB7,
0X7E,0X7D,0X7B,0X77};
uchar KeyPre; //保存上次扫描按键的键值
uchar KeyUp;
//用于控制按键去抖动操作。1:扫描时去抖动 2:等待释放 3:释放时去抖动。
#define LEDPORT P0 //定义显示器段码输出端口
#define LEDCON P1 //定义显示器位控制端口
uchar code SEGCODE[]=
{0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,// 0~9的共阳极代码
0xff,//不显示的共阳极段码
0X8C,//字符P的共阳极段码
0X8F,//┝的共阳极段码
0X88,//字符A的共阳极段码
0XBF,//字符-的共阳极段码
};
//定义LED位码控制码
uchar code BITCODE[]={0Xfe,0Xfd,0Xfb,0Xf7,0Xef,0Xdf,0Xbf,0X7f};
uchar DispBuf[6]; //保存显示的字符
bit DispNormal; //控制显示时,是正常显示还是闪烁显示。
uchar DispCnt; //控制闪烁显示时的频率。
#define SHORT_TIME 10 //蜂鸣器响200ms
#define LONG_TIME 100 //蜂鸣器响2s
#define LONGER_TIME 9000 //蜂鸣器响3 minutes
sbit ALARMCON=P3^4; //定义报警控制引脚
bit AlarmEnable; //是否报警或声音提示
uint AlarmTime; //控制报警时间长度
sbit LOCKCON=P3^3; //定义电子锁控制引脚
uchar code PassWord[]={1,2,3,4,5}; //定义初时密码表
uchar PassInBuf[6]; //保存输入的密码字符
uchar PassPosi; //用户输入密码字符存放在PassInBuf[]的位置。
bit TimerBit; //20ms定时时间到
uchar SysMode; //系统所处模式 0:输入密码模式 1:报警模式 2:开锁模式
uchar ErrorCnt; //用户连续输入密码出错次数。
/*
入口参数:
FillChar:写入缓冲区的字符
出口参数:无
*/
void Fill_Buf(uchar FillChar)
{
uchar i;
for(i=0;i<6;i++)
{
DispBuf[i]=FillChar;//用字符FillChar填充DispBuf[i]
PassInBuf[i]=FillChar; //用字符FillChar填充PassInBuf [i]
}
}
void Fill_Buf_P()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=PCHAR;// DispBuf[0]='P'
}
void Fill_Buf_O()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=OPENCHAR; // DispBuf[0]='┝'
}
void Fill_Buf_A()
{
Fill_Buf(LINECHAR); // DispBuf[1..5]= ' -----'
DispBuf[0]=ALARMCHAR; // DispBuf[0]='A'
}
/*
入口参数:
DispPosi:要显示数据的LED号。
DispChar:要显示的内容。
出口参数:无
*/
void Disp_Led_Sin(uchar DispChar,uchar DispPosi)
{
LEDPORT=SEGCODE[DispChar];//输出显示段码
LEDCON&=BITCODE[DispPosi];//输出显示位码
Delay1Ms(); //延时1MS
LEDCON|=0X3F;//关闭显示器
}
/*(2)关闭显示函数Disp_Led_OFF。
函数Disp_Led_OFF在显示器上显示空白字符,主要用在闪烁显示。函数通过6次调用Disp_Led_Sin实现所需功能。代码如下:*/
void Disp_Led_OFF()
{
uchar i;
LEDCON|=0X3F;// 关闭显示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(BLANKCHAR,i);//逐个显示空白字符
}
}
void Disp_Led_All()
{
uchar i;
LEDCON|=0X3F; // 关闭显示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(DispBuf[i],i); //显示DispBuf[]中的数值
}
}
void Disp_LED()
{
DispCnt++;
DispCnt%=10;
if(DispCnt==0)
{
DispNormal=~DispNormal;//200ms将闪烁显示控制位取反
}
if(SysMode==1)
{//报警模式,闪烁显示
if(!DispNormal)
{
Disp_Led_OFF();//显示空白字符
return;
}
}
Disp_Led_All();//显示DispBuf[]中的数值
}
/*
入口参数:
stime:蜂鸣器鸣叫时间。
出口参数:无
*/
void Sys_Speaker(uint stime)
{
AlarmEnable=1;//允许报警
AlarmTime=stime;//报警时间长短
}
void Sys_Alarm()
{
if(AlarmEnable==1)
{//允许报警
ALARMCON=0;//报警
AlarmTime--;
if(AlarmTime==0)
{//停止报警时间到
AlarmEnable=0;
ALARMCON=1;//禁止报警
if(SysMode==1)
{//报警发生在模式1时,要返回模式0
SysMode=0;
Fill_Buf_P();//显示P
}
}
}
}
/*
入口参数:无
出口参数:按键值或无按键
*/
uchar Find_Key()
{
uchar KeyTemp,i;
KEYPORT=0xf0;//行线输出0,列线输出全1
KeyTemp=KEYPORT;//读按键端口值
if(KeyTemp==0xf0)
return NO_KEY;//无键按下,返回
KEYPORT=KeyTemp|0x0f;//列线输出,行线输入
KeyTemp=KEYPORT;//读取按键端口值
for(i=0;i<16;i++)
{
if(KeyTemp==KEYCODE[i])//根据按键端口扫描值,查找按键值
return i;//返回按键值
}
return NO_KEY;
}
/*
入口参数:无
出口参数:按键值或无按键
*/
uchar Scan_Key()
{
uchar KeyTemp;
KeyTemp=Find_Key();//扫描键盘,获得按键值
if(KeyTemp==NO_KEY)
{
if(KeyUp<2)
{//无按键按下,返回
KeyUp=0;
return NO_KEY;
}
if(KeyUp==2)
{//按键要释放,延时去抖动
KeyUp=3;
return NO_KEY;
}
if(KeyUp==3)
{//按键释放,返回键值
KeyUp=0;
return KeyPre;
}
}
else
{
if(KeyUp==0)
{//有键按下,保存键值
KeyUp=1;
KeyPre=KeyTemp;
}
else if(KeyUp==1)
{//去抖动后,再次测到有按键按下
if( KeyPre==KeyTemp)
KeyUp=2;
else
KeyPre=KeyTemp;
} else if(KeyUp==3)
{//等待按键释放
KeyUp=2;
}
}
return NO_KEY;
}
/*
入口参数:
Key:按键值
出口参数:无
*/
void Key_Process(uchar Key)
{
uchar i;
if(Key==NO_KEY)
return ;//无按键,不处理
switch(SysMode)
{
case 0://输入密码
switch(Key)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
DispBuf[PassPosi]=LINECHAR;//显示'-'
PassInBuf[PassPosi]=Key;//保存用户输入的密码
if(PassPosi<5)
PassPosi++;//调整密码输入位置
Sys_Speaker(SHORT_TIME);//发按键提示音
break;
case BACKKEY://退格键
DispBuf[PassPosi]=BLANKCHAR;//显示' '
PassInBuf[PassPosi]=BLANKCHAR;//清除当前位置的密码
if(PassPosi>1)
PassPosi--;//调整显示位置
Sys_Speaker(SHORT_TIME);//发按键提示音
break;
case ENTERKEY://确定按键
for(i=0;i<5;i++)
{//比较用户输入密码与系统预设密码是否一致
if(PassInBuf[i+1]!=PassWord[i])
break;
}
if(i>=5)
{//输入密码正确
Fill_Buf_O();//显示开锁状态
PassPosi=1;
LOCKCON=1;//开锁
ErrorCnt=0;
Sys_Speaker(LONG_TIME);//发长提示音
SysMode=2;//转模式2
}
else
{
ErrorCnt++;//出错次数加一
if(ErrorCnt>2)
{//次数超过3次
ErrorCnt=0;
Fill_Buf_A();//显示报警状态
PassPosi=1;
Sys_Speaker(LONGER_TIME);//发报警音
SysMode=1;
}
else
{//出错次数少于3次,用户重新输入
Fill_Buf_P();
PassPosi=1;
Sys_Speaker(LONG_TIME);
}
}
break;
case LOCKKEY://闭锁键
Fill_Buf_P();//显示P
PassPosi=1;
Sys_Speaker(SHORT_TIME);
break;
}
break;
case 2://开锁状态
if(Key==LOCKKEY)
{//用户按动闭锁按键
Fill_Buf_P();
SysMode=0;
LOCKCON=0;//闭锁
Sys_Speaker(SHORT_TIME);
}
break;
}
}
void Ini_Timer0()
{
TMOD&=0XF0;
TMOD|=0X01;// 初始化T0,模式1
TR0=0;
TH0=(65536-20000)/256;//T0 赋计数初值
TL0=(65536-20000)%256;
TR0=1;//启动T0
ET0=1;//允许T0中断
}
void Timer0() interrupt 1
{
TR0=0;
TH0=(65536-20000)/256; //T0 赋计数初值
TL0=(65536-20000)%256;
TR0=1;
TimerBit=1;//定时时间到
}
void Ini_System()
{
PassPosi=1;
LOCKCON=0;//闭锁
Ini_Timer0();//初始化T0
Fill_Buf_P();
EA=1;//允许系统中断
}
void main()
{
uchar KeyTemp;
Ini_System();
while(1)
{
if (TimerBit==1)
{//定时时间到
Disp_LED();//刷新显示器
Sys_Alarm();//报警处理
KeyTemp=Scan_Key();//扫描按键
Key_Process(KeyTemp);//按键处理
TimerBit=0;
}
}
}
C. c语言单片机密码锁控制程序,用4个按键输入状态分别代表4位二进制数,可组成16种密码,范围0000
用51单片机,假设p1·0至p1·3接4个开关,P2·0接开锁按键S1
While(s1!=0);//等待按开锁按钮
delayms(10);//延时
While(s1==0);//等待按键抬起
mima=0x0F&P1;//读取P1低4位
if(mima==12)lock=1;//如果与设定密码相等开锁
else Fmq=1;//否则,报警
D. 单片机c语言密码锁程序
include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换
#define KeyPort P1
sbit LATCH1=P2^2;//定义锁存使能端口 段锁存
sbit LATCH2=P2^3;// 位锁存
unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};// 显示段码值0~F
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
unsigned char TempData[10]; //存储显示值的全局变量
unsigned char code password[8]={1,2,3,4,5,6,7,8};
//可以更改此密码做多组测试
void DelayUs2x(unsigned char t);//us级延时函数声明
void DelayMs(unsigned char t); //ms级延时
void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数
unsigned char KeyScan(void);//键盘扫描
unsigned char KeyPro(void);
void Init_Timer0(void);//定时器初始化
/*------------------------------------------------
主函数
------------------------------------------------*/
void main (void)
{
unsigned char num,i,j;
unsigned char temp[8];
bit Flag;
Init_Timer0();
while (1) //主循环
{
num=KeyPro();
if(num!=0xff)
{
if(i==0)
{
for(j=0;j<8;j++)//清屏
TempData[j]=0;
}
if(i<8)
{
temp[i]=dofly_DuanMa[num];//把按键值输入到临时数组中
for(j=0;j<=i;j++) //通过一定顺序把临时数组中
//的值赋值到显示缓冲区,从右往左输入
TempData[7-i+j]=temp[j];
}
i++; //输入数值累加
if(i==9)//正常等于8即可,由于我们需要空一个用于清屏,
//清屏时的按键不做输入值
{
i=0;
Flag=1;//先把比较位置1
for(j=0;j<8;j++)//循环比较8个数值,
//如果有一个不等 则最终Flag值为0
Flag=Flag&&(temp[j]==dofly_DuanMa[password[j]]);
//比较输入值和已有密码
for(j=0;j<8;j++)//清屏
TempData[j]=0;
if(Flag)//如果比较全部相同,标志位置1
{
TempData[0]=0x3f; // "o"
TempData[1]=0x73; // "p"
TempData[2]=0x79; // "E"
TempData[3]=0x54; // "n"
//说明密码正确,输入对应操作 显示"open"
}
else
{
TempData[0]=0x79; // "E"
TempData[1]=0x50; // "r"
TempData[2]=0x50; // "r"
//否则显示"Err"
}
}
}
}
}
/*------------------------------------------------
uS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
显示函数,用于动态扫描数码管
输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
如输入0表示从第一个显示。
Num表示需要显示的位数,如需要显示99两位数值则该值输入2
------------------------------------------------*/
void Display(unsigned char FirstBit,unsigned char Num)
{
static unsigned char i=0;
DataPort=0; //清空数据,防止有交替重影
LATCH1=1; //段锁存
LATCH1=0;
DataPort=dofly_WeiMa[i+FirstBit]; //取位码
LATCH2=1; //位锁存
LATCH2=0;
DataPort=TempData[i]; //取显示数据,段码
LATCH1=1; //段锁存
LATCH1=0;
i++;
if(i==Num)
i=0;
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
//TH0=0x00; //给定初值
//TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=(65536-2000)/256; //重新赋值 2ms
TL0=(65536-2000)%256;
Display(0,8); // 调用数码管扫描
}
/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void) //键盘扫描函数,使用行列反转扫描法
{
unsigned char cord_h,cord_l;//行列值中间变量
KeyPort=0x0f; //行线输出全为0
cord_h=KeyPort&0x0f; //读入列线值
if(cord_h!=0x0f) //先检测有无按键按下
{
DelayMs(10); //去抖
if((KeyPort&0x0f)!=0x0f)
{
cord_h=KeyPort&0x0f; //读入列线值
KeyPort=cord_h|0xf0; //输出当前列线值
cord_l=KeyPort&0xf0; //读入行线值
while((KeyPort&0xf0)!=0xf0);//等待松开并输出
return(cord_h+cord_l);//键盘最后组合码值
}
}return(0xff); //返回该值
}
/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
case 0x7d:return 1;break;//1
case 0x7b:return 2;break;//2
case 0x77:return 3;break;//3
case 0xbe:return 4;break;//4
case 0xbd:return 5;break;//5
case 0xbb:return 6;break;//6
case 0xb7:return 7;break;//7
case 0xde:return 8;break;//8
case 0xdd:return 9;break;//9
case 0xdb:return 10;break;//a
case 0xd7:return 11;break;//b
case 0xee:return 12;break;//c
case 0xed:return 13;break;//d
case 0xeb:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;
}
}
E. 密码锁c语言编程代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
intmain()
{
charpassword[10],password2[10];
memset(password,0,sizeof(password));
memset(password2,0,sizeof(password2));
printf("请设置8位数以内密码: ");
scanf("%s",password);
printf("请设置校验密码: ");
scanf("%s",password2);
if(atoi(password2)==atoi(password))
{
printf("密码输入正确!: ");
}
else
{
printf("密码输入错误!: ");
}
return0;
}
F. 求AT89C51单片机控制电子密码锁的程序 最好是C语言
;完成功能说明:
; 基本功能以及OK,可以在线修改密码Ok,开机默认密码:123456,在线可修改
;功能改进说明:
; 将代码继续优化,将其中的清楚按键设置成具有连按功能的按键,对于SET和SET_OUT利用一个按键来做(利用按键的3S长按进入重新设置密码模式,利用相同按键的短击退出密码设置模式),设置报警模式以及退出报警设置,利用剩余的按键来做。;===============================================
;==============MCU:AT89C52=====================
;============名称:电子密码锁===================
;===========程序编写人:DAIVD===================
;=========程序编写时间:2010年8月3日============
;=功能描述:六位数码管显示,4*4矩阵键盘作为外设=
;=====通过矩阵键盘可以输入密码以及修改密码======
;=====通过数码管以及LED显示当前密码锁状态=======
;===============版本:V1.0======================
;=====项目完成时间: ==========
;===============================================
BT0 EQU 20H.0 ;节拍法标志位每个节拍为20MS
CHANGE_PW_FLAG EQU 20H.1 ;重新设置密码标志位
OK_FLAG EQU 20H.2 ;确认密码输入标志位
CLR_FLAG EQU 20H.3 ;清楚输入密码标志位
KEY_REG EQU 20H.4 ;按键按下标志位
FLASHING_FLAG EQU 20H.5 ;闪烁标志位
ONCE_TIME EQU 20H.6 ;第一次进入标志位
MEMORY_FLAG EQU 20H.7 ;修改密码是两次输入第一次需要记忆
DIGITAL_FLAG EQU 21H.0 ;是否需要键入数字标志位
NUM_FLAG EQU 21H.1 ;数字键标志位
;FUNCTION_FLAG EQU 21H.2 ;功能键标志位
D_DONG_FLAG EQU 21H.3 ;消抖标志位
KEY_HAVE_REG EQU 21H.4 ;一次按键多次响应标志位
SET_OUT EQU 21H.5 ;设置密码状态退出标志位
OTI EQU 21H.6 ;第一次进入重置密码模式标志位
COMPARE_EN EQU 21H.7
OTII EQU 22H.0
ALARM EQU 22H.1 ;报警标志位
ALARM_OUT EQU 22H.2 ;报警退出标志位
ORIGINAL_PW_1 EQU 30H ;原始密码存储寄存器
ORIGINAL_PW_2 EQU 31H
ORIGINAL_PW_3 EQU 32H
ORIGINAL_PW_4 EQU 33H
ORIGINAL_PW_5 EQU 34H
ORIGINAL_PW_6 EQU 35H
CURRENT_PW_1 EQU 40H ;当前密码存储器
CURRENT_PW_2 EQU 41H
CURRENT_PW_3 EQU 42H
CURRENT_PW_4 EQU 43H
CURRENT_PW_5 EQU 44H
CURRENT_PW_6 EQU 45H
CURRENT_PW_1_REG EQU 46H ;当前密码暂存器
CURRENT_PW_2_REG EQU 47H ;用于密码修改时比较两次输入是否相同
CURRENT_PW_3_REG EQU 48H
CURRENT_PW_4_REG EQU 49H
CURRENT_PW_5_REG EQU 4AH
CURRENT_PW_6_REG EQU 4BH
DISPLAY_REG_0 EQU 36H ;显示寄存器
DISPLAY_REG_1 EQU 37H
DISPLAY_REG_2 EQU 38H
DISPLAY_REG_3 EQU 39H
DISPLAY_REG_4 EQU 3AH
DISPLAY_REG_5 EQU 3BH
COUNT_0 EQU 3CH ;用于闪烁标志位的计数200MS
TH0_BUFFER EQU 3DH ;定时器赋初值寄存器
TL0_BUFFER EQU 3EH
MAZHI_REG EQU 3DH ;4*4矩阵键盘扫描得到的码值
COUNT_1 EQU 3FH ;用于设置密码标志位的计数超过3S则置一
COUNT_2 EQU 51H ;用于输入密码次数是否超过3次
R2_REG EQU 50H
CHIP_SELECT EQU P1 ;P1作为片选口
OUTPUT EQU P0 ;P0口作为输出口
GREEN_LED EQU P3.4 ;绿灯代表输入密码正确
YELLOW_LED EQU P3.3 ;黄灯代表正在输入密码过程中
RED_LED EQU P3.2 ;红灯代表输入密码错误
SPK EQU P3.1 ;蜂鸣器代表输入密码超过3次报警
ORG 0000H
LJMP START
ORG 0003H ;中断入口地址写RETI防止出现误判对程序影响
RETI
ORG 000BH
LJMP T0_SER
ORG 0013H
RETI
ORG 001BH
RETI
ORG 0023H
RETI
ORG 002BH
RETI
ORG 0030H
START: MOV ORIGINAL_PW_1,#01 ;设置初始密码
MOV ORIGINAL_PW_2,#02
MOV ORIGINAL_PW_3,#03
MOV ORIGINAL_PW_4,#04
MOV ORIGINAL_PW_5,#05
MOV ORIGINAL_PW_6,#06
MOV TMOD,#01H ;设置定时器0工作方式1采用中断方式
SETB EA
SETB ET0
MOV DPTR,#65536-20000
MOV TH0,DPH
MOV TL0,DPL
MOV TH0_BUFFER,DPH
MOV TL0_BUFFER,DPL
SETB TR0
MOV R0,#CURRENT_PW_1 ;对当前密码以及当前密码暂存器赋初值
REFRESH_PW: MOV @R0,#0B9H ;其中当前密码暂存器用于修改密码时
INC R0 ;比较两次重新输入的密码是否相等用
CJNE R0,#04CH,REFRESH_PW
MOV 20H,#00H
MOV 21H,#00H
MOV 22H,#00H
MOV COUNT_0,#00H
MOV COUNT_1,#00H
MOV COUNT_2,#00H
;=========================================
MAIN: JNB BT0,MAIN
CLR BT0
JNB CHANGE_PW_FLAG,LOOP ;判断是否需要修改密码
;===============修改原始密码模式========== ;当CHANGE_PW_FLAG=1表明进入修改密码模式
JB OTII,LP0
SETB OTII
MOV R2,#0
LP0: JNB SET_OUT,LP
MOV R2,#0
LJMP LP4
LP: JNB OK_FLAG,LOOP1 ;判断是否输入密码完成
CLR OK_FLAG
JNB OTI,LP1 ;判断是不是第一次进入要在输入密码正确的前提下
JNB COMPARE_EN,SAVE_MODE ;记录两次输入的密码是否一致才确定是否需要重置
CALL COMPARE_CODE
LJMP LOOP1
SAVE_MODE: CALL SAVE_CODE
LJMP LOOP1
LP1: CALL ENTER_PW_MODE
CJNE R2,#0,LP2
LJMP LOOP1
LP2: CJNE R2,#7,LP3 ;等于7代表原始密码输入正确,下一步记忆新密码
SETB OTI
MOV R2,#0
LJMP LOOP1
LP3: MOV R2,#8
LP4: CLR ALARM_OUT
CLR SET_OUT
CLR OTI ;清零所有内容恢复等待密码输入状态
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
LJMP LOOP1
;===============常规输入密码模式==========
LOOP: CLR SET_OUT ;非设置密码格式下也会扫描到SET_OUT
;防止程序进入设置密码状态下直接退出
JNB ALARM,L1
JB ALARM_OUT,L2
CLR SPK
LJMP LOOP3
L2: SETB SPK
CLR ALARM_OUT
CLR ALARM
LJMP LOOP1
L1: JNB OK_FLAG,LOOP1 ;判断是否输入密码完成
CLR OK_FLAG
CALL ENTER_PW_MODE
;==========================================
LOOP1: JNB CLR_FLAG,LOOP2 ;判断是否需要清除所输入密码
CLR CLR_FLAG
LCALL CLR_INPUT_PW
LOOP2: JNB DIGITAL_FLAG,LOOP3 ;判断是否需要输入密码
CLR DIGITAL_FLAG
LCALL INPUT_PW
LJMP LOOP3
;=========================================
LOOP3: LCALL DISPLAY
LCALL KEY_SCAN
INC COUNT_0
MOV A,COUNT_0
CJNE A,#5,LOOP4
MOV COUNT_0,#0
CPL FLASHING_FLAG
LOOP4:
LJMP MAIN
;=============下面是具体的子程序===========
;================检测密码是否正确==========
ENTER_PW_MODE:
CLR OK_FLAG ;比较是否为零,为零的时候
CJNE R2,#0,ENTER_PW_MODE_0 ;代表还没密码输入,直接跳出
LJMP ENTER_PW_MODE_OUT
ENTER_PW_MODE_0:
CJNE R2,#7,$+3 ;用来比较R2是否为7或者8
JC ENTER_PW_MODE_2
MOV R2,#00 ;如果8在BAD的模式下切换到输入密码状态
LJMP ENTER_PW_MODE_OUT ;如果7在GOOD的模式下切换到输入密码状态
ENTER_PW_MODE_2:
CJNE R2,#6,ENTER_PW_MODE_3 ;如果R2里的数字不为6代表密码位数不够,肯定错
MOV R0,#ORIGINAL_PW_1 ;如果R2里的数字等于6那么在比较是否相同
MOV R1,#CURRENT_PW_1
ENTER_PW_MODE_4:
MOV A,@R0
XRL A,@R1 ;相异或内容相同为0
CJNE A,#00H,ENTER_PW_MODE_3
INC R0
INC R1
CJNE R0,#36H,ENTER_PW_MODE_4
MOV R2,#7 ;如果相同代表密码输入正确GOOD
MOV COUNT_2,#0
LJMP ENTER_PW_MODE_OUT
ENTER_PW_MODE_3:MOV R2,#8 ;如果不相同则代表密码不正确BAD
INC COUNT_2
MOV A,COUNT_2
CJNE A,#3,$+3
JC KK
FUZHI: MOV COUNT_2,#00H
SETB ALARM
KK: MOV R0,#CURRENT_PW_1 ;对当前密码以及当前密码暂存器赋初值
REF_PW: MOV @R0,#0B9H ;其中当前密码暂存器用于修改密码时
INC R0 ;比较两次重新输入的密码是否相等用
CJNE R0,#04CH,REF_PW
ENTER_PW_MODE_OUT:
RET
;==========================================
;=============清除所输入的密码=============
CLR_INPUT_PW:
CLR CLR_FLAG
CJNE R2,#0,CLR_INPUT_PW_0 ;如果为零则不操作
LJMP CLR_INPUT_PW_OUT
CLR_INPUT_PW_0:
CJNE R2,#7,$+3 ;用来比较R2是否为7或者8
JC CLR_INPUT_PW_1
MOV R2,#00 ;如果8在BAD的模式下切换到输入密码状态
LJMP CLR_INPUT_PW_OUT ;如果7在GOOD的模式下切换到输入密码状态
CLR_INPUT_PW_1:
DEC R2 ;正常模式下将R2减一
CLR_INPUT_PW_OUT:
RET
;==========================================
;============输入单位密码子程序============
INPUT_PW: JB NUM_FLAG,INPUT_PW_0
LJMP INPUT_PW_OUT
INPUT_PW_0: CLR NUM_FLAG
CJNE R2,#7,$+3 ;比较R2是否大于7,大于C=0
JC INPUT_PW_2
MOV R2,#01 ;数字键按下输入密码
LJMP INPUT_PW_3_3
INPUT_PW_2: CJNE R2,#6,INPUT_PW_3 ;如果当前R2等于则6位密码已经输满则不操作
LJMP INPUT_PW_OUT
INPUT_PW_3: INC R2
INPUT_PW_3_3: MOV R1,#01
MOV R2_REG,R2 ;根据R2的给相应的位送密码
MOV R0,#CURRENT_PW_1
JMP I_LOOP
I_LOOP1: INC R0
INC R1
I_LOOP: MOV A,R1
CJNE A,R2_REG,I_LOOP1
MOV A,R3
MOV @R0,A
INPUT_PW_OUT: RET
;==========================================
;===============SAVE_CODE==================
SAVE_CODE: CJNE R2,#6,SAVE_CLR ;如果R2不等于6代表密码输入错误直接退出
SAVE_IN: MOV R0,#CURRENT_PW_1_REG ;将输入的新密码先保存在密码暂存区
MOV R1,#CURRENT_PW_1 ;46H
SAVE_IN_LOOP: MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,R1
CJNE A,#46H,SAVE_IN_LOOP
SETB COMPARE_EN
MOV R2,#0 ;密码输入正确则程序处于等待输入状态
LJMP SAVE_OUT
SAVE_CLR: MOV R2,#8
CLR SET_OUT
CLR OTI ;清零所有内容恢复等待密码输入状态
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
SAVE_OUT: RET
;===========================================
;=================COMPARE_CODE==============
COMPARE_CODE: CJNE R2,#6,COMPARE_FAIL ;如果R2不等于6代表上次输入密码数不足6位
COMPARE_IN: MOV R0,#CURRENT_PW_1_REG
MOV R1,#CURRENT_PW_1 ;46H
COMPARE_IN_LOOP:
MOV A,@R1
XRL A,@R0
CJNE A,#00H,COMPARE_FAIL
INC R0
INC R1
MOV A,R1
CJNE A,#46H,COMPARE_IN_LOOP
MOV R0,#ORIGINAL_PW_1
MOV R1,#CURRENT_PW_1 ;46H
TIHUAN_LOOP: MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,R1
CJNE A,#46H,TIHUAN_LOOP
MOV R2,#7
CLR SET_OUT
CLR OTI ;清零所有内容恢复等待密码输入状态
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
LJMP COMPARE_OUT
COMPARE_FAIL: MOV R2,#8
CLR SET_OUT
CLR OTI ;清零所有内容恢复等待密码输入状态
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
COMPARE_OUT: RET
;===========================================
;==================显示子程序==============
DISPLAY: MOV R4,#0
MOV DPTR,#TAB_0
MOV A,R2
RL A
JMP @A+DPTR
TAB_0: AJMP DISPLAY_0
AJMP DISPLAY_1
AJMP DISPLAY_2
AJMP DISPLAY_3
AJMP DISPLAY_4
AJMP DISPLAY_5
AJMP DISPLAY_6
AJMP DISPLAY_7
AJMP DISPLAY_8
DISPLAY_0: MOV DPTR,#TAB_1
LJMP REFRESH_DISPLAY
DISPLAY_1: MOV DPTR,#TAB_2
LJMP REFRESH_DISPLAY
DISPLAY_2: MOV DPTR,#TAB_3
LJMP REFRESH_DISPLAY
DISPLAY_3: MOV DPTR,#TAB_4
LJMP REFRESH_DISPLAY
DISPLAY_4: MOV DPTR,#TAB_5
LJMP REFRESH_DISPLAY
DISPLAY_5: MOV DPTR,#TAB_6
LJMP REFRESH_DISPLAY
DISPLAY_6: MOV DPTR,#TAB_7
LJMP REFRESH_DISPLAY
DISPLAY_7: MOV DPTR,#TAB_8
LJMP REFRESH_DISPLAY
DISPLAY_8: MOV DPTR,#TAB_9
REFRESH_DISPLAY:
MOV R0,#DISPLAY_REG_0
DISPLAY_LOOP:
MOV A,R4
MOVC A,@A+DPTR
MOV @R0,A
INC R4
INC R0
MOV A,R0
CJNE A,#3CH,DISPLAY_LOOP ;此时表明数码管显示的数值已送完
DISPLAY_SHOW:
MOV R0,#DISPLAY_REG_0 ;数码管动态显示
MOV R5,#0FEH
NEXT_0: MOV CHIP_SELECT,R5
MOV A,@R0
MOV OUTPUT,A
LCALL DELAY
MOV OUTPUT,#0FFH
INC R0
MOV A,R5
RL A
MOV R5,A ;片选
CJNE R0,#3CH,NEXT_0
CJNE R2,#0,NEXT_6
MOV P3,#0FFH
LJMP DISPLAY_OUT
NEXT_6: CJNE R2,#7,NEXT_1
CLR GREEN_LED
SETB YELLOW_LED
SETB RED_LED
LJMP DISPLAY_OUT
NEXT_1: CJNE R2,#8,NEXT_2
SETB YELLOW_LED
SETB GREEN_LED
CLR RED_LED
LJMP DISPLAY_OUT
NEXT_2: JNB CHANGE_PW_FLAG,NEXT_3
JNB FLASHING_FLAG,NEXT_4
MOV P3,#0FFH
LJMP DISPLAY_OUT
NEXT_4: MOV P3,#00H
LJMP DISPLAY_OUT
NEXT_3: JNB FLASHING_FLAG,NEXT_5
MOV P3,#0F7H
LJMP DISPLAY_OUT
NEXT_5: MOV P3,#0FFH
DISPLAY_OUT: RET
;=======================================
;============按键扫描程序===============
KEY_SCAN: MOV R3,#00H ;对码表扫描进行初始化可以访问到第一位
JNB D_DONG_FLAG,PANDUAN ;判断是否进行过消抖
LCALL FANZHUAN_SCAN ;反转扫描确定码值
CJNE A,#0FFH,L4 ;如果码值等于0FFH可能是抖动或者按键抬起
L3: CLR D_DONG_FLAG ;表明是按键抬起,此时要对D_DONG_FLAG/
CLR KEY_HAVE_REG ;KEY_HAVE_REG进行清零;;;;;;;;;;
CLR COUNT_1
LJMP KEY_SCAN_OUT
L4: JNB ALARM,KEY_SCAN_1
CJNE A,#0B7H,L3
SETB ALARM_OUT
CLR D_DONG_FLAG
LJMP KEY_SCAN_OUT
PANDUAN: LCALL FANZHUAN_SCAN ;第一次进入没有经过消抖判断是否有按键按下
CJNE A,#0FFH,KEY_SCAN_0 ;对所扫描的码值进行比较如果为0FFH没按键按下
LJMP KEY_SCAN_OUT
KEY_SCAN_0: SETB D_DONG_FLAG ;所扫到的码值不等于0FFH可能是按键按下
LJMP KEY_SCAN_OUT
KEY_SCAN_1:
JNB KEY_HAVE_REG,KEY_SCAN_1_1;一次按键多次响应标志位
CJNE A,#0E7H,KEY_SCAN_1_1_1
INC COUNT_1 ;长按处理
MOV A,COUNT_1
CJNE A,#150,KEY_SCAN_1_1_1
MOV COUNT_1,#00H
SETB CHANGE_PW_FLAG
CLR D_DONG_FLAG
CLR KEY_HAVE_REG
KEY_SCAN_1_1_1:
LJMP KEY_SCAN_OUT
KEY_SCAN_1_1: MOV MAZHI_REG,A
KEY_SCAN_LOOP:
MOV DPTR,#TAB_10
MOV A,R3
MOVC A,@A+DPTR
CJNE A,#0FFH,KEY_SCAN_2 ;如果查出的码表值为0FFH代表已经查完了
MOV R3,#0 ;但是没有符合的就代表是乱码不处理
CLR D_DONG_FLAG
CLR KEY_HAVE_REG
LJMP KEY_SCAN_OUT
KEY_SCAN_2: CJNE A,MAZHI_REG,KEY_SCAN_3 ;比较是哪个键按下
CJNE R3,#10,$+3 ;通过比较后形成小于等于9或者大于9两种情况
JNC COMPARE
SHUZI_MODE: SETB KEY_HAVE_REG
SETB NUM_FLAG
SETB DIGITAL_FLAG
LJMP KEY_SCAN_OUT
COMPARE: SETB KEY_HAVE_REG
CJNE R3,#10,COMPARE_0 ;此时R3内的数值大于9则CY=1
SETB OK_FLAG ;等于10为OK键按下
LJMP KEY_SCAN_OUT
COMPARE_0: CJNE R3,#11,COMPARE_1 ;等于11为清除按键按下
SETB CLR_FLAG
LJMP KEY_SCAN_OUT ;等于12为设置密码按键在长按里面加处理
COMPARE_1: CJNE R3,#13,COMPARE_2 ;等于13为设置密码跳出标志
SETB SET_OUT
LJMP KEY_SCAN_OUT
;COMPARE_2: CJNE R3,#14,COMPARE_3
; SETB ALARM
; LJMP KEY_SCAN_OUT
COMPARE_2: CJNE R3,#14,COMPARE_4
SETB ALARM_OUT
LJMP KEY_SCAN_OUT
COMPARE_4: LJMP KEY_SCAN_OUT ;按键加功能
KEY_SCAN_3: INC R3
LJMP KEY_SCAN_LOOP
KEY_SCAN_OUT:
RET
;=======================================
FANZHUAN_SCAN: MOV P2,#0F0H ;反转扫描确定码值
MOV A,P2
ANL A,#0F0H
MOV B,A
MOV P2,#0FH
MOV A,P2
ANL A,#0FH
ORL A,B
RET
;===============显示的码表==============
TAB_1: DB 0BFH,0BFH,0BFH,0BFH,0BFH,0BFH ;------
TAB_2: DB 0B9H,0BFH,0BFH,0BFH,0BFH,0BFH ;+-----
TAB_3: DB 0B9H,0B9H,0BFH,0BFH,0BFH,0BFH ;++----
TAB_4: DB 0B9H,0B9H,0B9H,0BFH,0BFH,0BFH ;+++---
TAB_5: DB 0B9H,0B9H,0B9H,0B9H,0BFH,0BFH ;++++--
TAB_6: DB 0B9H,0B9H,0B9H,0B9H,0B9H,0BFH ;+++++-
TAB_7: DB 0B9H,0B9H,0B9H,0B9H,0B9H,0B9H ;++++++
TAB_8: DB 090H,0A3H,0A3H,0A1H,0FFH,0FFH ;good
TAB_9: DB 083H,0A0H,0A1H,0FFH,0FFH,0FFH ;bad
TAB_10: DB 0EEH,0DEH,0BEH,07EH,0EDH,0DDH,0BDH,07DH ;4*4矩阵键盘的码表
DB 0EBH,0DBH,0BBH,07BH,0E7H,0D7H,0B7H,77H,0FFH
;=======================================
;==============延时子程序===============
;输入:无
;输出:无
;功能:延时一段时间稳定数码管的显示2.4MS
DELAY:
MOV R7,#30
DL: MOV R6,#40
DJNZ R6,$
DJNZ R7,DL
RET
;=======================================
;============定时器中断服务程序=========
T0_SER:
MOV TMOD,#01H
SETB BT0
MOV TH0,TH0_BUFFER
MOV TL0,TL0_BUFFER
RETI
;=======================================
END
G. 求51单片机C语言编的密码锁程序
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define BIN(a,b,c,d,e,f,g,h) ((a<<7)+(b<<6)+(c<<5)+(d<<4)+(e<<3)+(f<<2)+(g<<1)+(h<<0))
//下面的code表示数组存放在ROM中,因为这个数组的值不需要改写
uchar code KeyCode[16]={15,14,12,8,30,28,24,16,60,56,48,32,120,112,96,64};//值为m*(n+1)的乘积,用于Key()
uchar dis[6];
msdelay(uint x)//延时子函数
{uchar j;
while(x--)
{for(j=0;j<125;j++){;}
}
}
//键盘子程序一,键盘值与数组值对比得到
uchar Key(void)
{uchar temp,m,n,i,j,matrix,k;
P1=0xF0; /*行线电平为高,列线为低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*行仍为高,无按健,退出*/
else msdelay(10);
for(i=1;i<16;i=i*2)
{m=i;
for(j=1;j<16;j=j*2)
{n=(~j)&0x0f;
P1=(m<<4)|n; /*m为P1的行值由i循环得到,n为列值,由j循环并取反得到*/
temp=P1&0xf0;
if (!temp)
{do{temp=P1&0xf0;}while(!temp);
matrix=m*(n+1);/*为避免乘积重复,n+1*/
for(k=0;k<16;k++){if (matrix==KeyCode[k]) return(k);} //KeyCode:见前
return(16);
} //if loop
}//j loop
}//i loop
}//Key end
//用Switch...case语句得到键盘值*/
uchar Key1(void)
{uchar temp,m,n,i,j,matrix;
P1=0xF0; /*行线电平为高,列线为低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*行仍为高,无按健,退出*/
else msdelay(10);
for(i=1;i<16;i=i*2)
{m=i;
for(j=1;j<16;j=j*2)
{n=(~j)&0x0f;
P1=(m<<4)|n;/*m为P1的行值由i循环得到,n为列值,由j循环并取反得到*/
temp=P1&0xf0;
if (!temp)
{do{temp=P1&0xf0;}while(!temp);
matrix=m*(n+1);
switch(matrix) //此方法的基本思路:
{case 15:return(1); break; //由循环得到的m,n值赋于P1端口实现逐个键扫描
case 14:return(2); break; //同时由m,n+1的值相乘得到对应键点de的积
case 12:return(3); break; //m*(n+1)值扫描键点对应而得出键值
case 8:return(4); break; //
case 30:return(5); break; //
case 28:return(6); break; //
case 24:return(7); break; //
case 16:return(8); break;
case 60:return(9); break;
case 56:return(0); break;
case 48:return(10); break;
case 32:return(11); break;
case 120:return(12); break;
case 112:return(13); break;
case 96:return(14); break;
case 64:return(15); break;
default:return(16);
} //switch end
} //if loop
}//j loop
}//i loop
}//Key end
//依次扫描16个按键
uchar Key2(void)
{uchar temp;
P1=0xF0; /*使P1=1111 0000,行线电平为高,列线为低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*读P1=1111 xxxx,表示行仍为高,无按健,退出(x表示不关心)?/
else msdelay(10);
P1=0x1e; /*P1=0001 1110,行一为高,列一为低,扫描第一个按键*/
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(1);}
P1=0x1d; /*P1=0001 1101,行一为高,列二为低,扫描第二个按键,下面扫描其余按键*/
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(2);}
P1=0x1b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(3);}
P1=0x17;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(4);}
P1=0x2e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(5);}
P1=0x2d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(6);}
P1=0x2b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(7);}
P1=0x27;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(8);}
P1=0x4e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(9);}
P1=0x4d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(0);}
P1=0x4b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(10);}
P1=0x47;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(11);}
P1=0x8e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(12);}
P1=0x8d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(13);}
P1=0x8b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(14);}
P1=0x87;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(15);}
return(16); //扫描all按键都未按下,则输出16
}//Key2 end.
////////时钟中断显示子程序
void T0_int() interrupt 1
{static uchar i;
if (i==6){i=0;}
P0=5-i;
P0=P0|(dis[i]<<4);
i++;
TL0=0;
TH0=252;}
void distri(uint disnum)
{uint temp;
dis[0]=0;
dis[1]=disnum/10000;
temp=disnum%10000;
dis[2]=temp/1000;
temp=temp%1000;
dis[3]=temp/100;
temp=temp%100;
dis[4]=temp/10;
dis[5]=temp%10;
}
Main()
{uchar KeyVal,i=0;
TMOD=0x01;
IE=0x82;
TH0=252;
TL0=0;
TR0=1;
distri(0);
do{
KeyVal=Key();
if (KeyVal!=16) dis[1]=KeyVal; //注意:当有按键时才赋于显示位dis[1],否则出错,请分析!
}while(1);
}
H. 请问,用四个独立按键来制作简易密码锁C语言程序该怎么编写
这个可以模拟那种拨码形式的密码锁方式来设计,比如OFO共享单车的拨码方式。
#include<reg51.h>
#define uchar unsigned char
uchar mima[4]={1,2,3,4};
uchar keymm[4]={0,0,0,0};
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
sbit led=P1^4;
bit flag=0;
void delay(uchar a)
{
uchar i;
while(a--)for(i=0;i<120;i++);
}
main()
{
uchar i;
led=1;
while(1)
{
if(key1==0)
{
while(key1==0);
keymm[0]++;
keymm[0]%=10;
}
if(key2==0)
{
while(key2==0);
keymm[1]++;
keymm[1]%=10;
}
if(key3==0)
{
while(key3==0);
keymm[2]++;
keymm[2]%=10;
}
if(key4==0)
{
while(key4==0);
keymm[3]++;
keymm[3]%=10;
}
for(i=0;i<4;i++)
{
if(keymm[i]!=mima[i])break;
if(i==3)flag=1;
}
if(flag)
{
i=10;
while(i--)
{
led=~led;
delay(100);
}
flag=0;
}
}
}
I. 电子密码锁的C语言程序
亲 这程序是我自己当时写的,51单片机1602液晶,可以更改密码。
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit lcden=P2^6;
sbit lcdrs=P2^4;
sbit lcdrw=P2^5;
bit flag;
bit flag1;
bit flag2;
bit flag3;
bit flag4;
uchar a[6];
uchar b[6];
uchar c[6];
uchar num,key,,num1,num2,i,temp,ss,num3,num4,num5,num6;
uchar code table[]=" input password: ";
uchar code table1[]="right!";
uchar code table2[]="error!";
uchar code table3[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code table4[]="wrong!";
uchar code table5[]="change password:";
uchar code table6[]="password again: ";
uchar code table7[]="new passwordsure";
uchar password[]={'0','0','0','0','0','0'};
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{
lcdrs=0;
lcdrw=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date)
{
lcdrs=1;
lcdrw=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<16;num++)
{
write_data(table[num]);
delay(5);
}
//write_com(0x80+0x40);
}
uchar keyscan(void)
{
uchar temp,;
P3=0x7f;
temp=P3&0x7f;
if(temp!=0x7f)
{
delay(1);
P3=0x7f;
temp=P3&0x7f;
if(temp!=0x7f)
{
P3=0x7f;
temp=P3&0x7f;
switch (temp)
{
case 0x7e:=1;break;
case 0x7d:=2;break;
case 0x7b:=3;break;
case 0x77:=4;break;
}
while(temp!=0x7f)
{
P3=0x7f;
temp=P3&0x7f;
}
return ;
}
}
//**********
P3=0xbf;
temp=P3&0xbf;
if(temp!=0xbf)
{
delay(1);
P3=0xbf;
temp=P3&0xbf;
if(temp!=0xbf)
{
P3=0xbf;
temp=P3&0xbf;
switch (temp)
{
case 0xbe:=5;break;
case 0xbd:=6;break;
case 0xbb:=7;break;
case 0xb7:=8;break;
}
while(temp!=0xbf)
{
P3=0xbf;
temp=P3&0xbf;
}
return ;
}
}
//***********
P3=0xdf;
temp=P3&0xdf;
if(temp!=0xdf)
{
delay(1);
P3=0xdf;
temp=P3&0xdf;
if(temp!=0xdf)
{
P3=0xdf;
temp=P3&0xdf;
switch (temp)
{
case 0xde:=9;break;
case 0xdd:=10;break;
case 0xdb:=11;break;
case 0xd7:=12;break;
}
while(temp!=0xdf)
{
P3=0xdf;
temp=P3&0xdf;
}
return ;
}
}
//********
P3=0xef;
temp=P3&0xef;
if(temp!=0xef)
{
delay(1);
P3=0xef;
temp=P3&0xef;
if(temp!=0xef)
{
P3=0xef;
temp=P3&0xef;
switch (temp)
{
case 0xee:=13;break;
case 0xed:=14;break;
case 0xeb:=15;break;
case 0xe7:=16;break;
}
while(temp!=0xef)
{
P3=0xef;
temp=P3&0xef;
}
return ;
}
else
{
=0;
return ;
}
}
}
void changepassword()
{
uchar j=0,k=0,m=0;
flag2=0;
flag3=0;
flag4=0;
write_com(0x01);
delay(10);
write_com(0x0c);
delay(10);
write_com(0x80);
for(num4=0;num4<16;num4++)
{
write_data(table5[num4]);
}
while(!flag2)
{
key=keyscan();
if(key==1||key==2||key==3||key==4||key==5||key==6||key==7||key==8||key==9||key==10)
{
b[j]=table3[key-1];
write_data(table3[key-1]);
delay(10);
write_com(0x80+0x40+3+j);
delay(10);
write_data('*');
j++;
if(j==6)
{
j=0;
flag2=1;
flag3=1;
write_com(0x01);
delay(10);
write_com(0x80);
for(num5=0;num5<16;num5++)
{
write_data(table6[num5]);
}
}
}
}
while(flag3)
{
key=keyscan();
if(key==1||key==2||key==3||key==4||key==5||key==6||key==7||key==8||key==9||key==10)
{
c[k]=table3[key-1];
write_data(table3[key-1]);
delay(10);
write_com(0x80+0x40+3+k);
delay(10);
write_data('*');
k++;
if(k==6)
{
flag3=0;
write_com(0x01);
if((b[0]==c[0])&&(b[1]==c[1])&&(b[2]==c[2])&&(b[3]==c[3])&&(b[4]==c[4])&&(b[5]==c[5]))
{
flag4=1;
password[0]=b[0];
password[1]=b[1];
password[2]=b[2];
password[3]=b[3];
password[4]=b[4];
password[5]=b[5];
write_com(0x80);
//delay(10);
}
}
}
while(flag4)
{
flag4=0;
write_com(0x80);
for(num6=0;num6<16;num6++)
{
write_data(table7[num6]);
}
delay(2000);
write_com(0x80);
for(num=0;num<16;num++)
{
write_data(table[num]);
delay(5);
}
}
}
}
void main()
{
init();
while(1)
{
key=100;
key=keyscan();
if((!flag)&&(!flag1))
{
if((key==1||key==2||key==3||key==4||key==5||key==6||key==7||key==8||key==9||key==10)&&(i<6))
{
write_com(0x0f);
write_com(0x06);
a[i]=table3[key-1];
write_data(table3[key-1]);
delay(10);
write_com(0x80+0x40+4+i);
delay(50);
write_data('*');
i++;
}
}
if((!flag)&&(!flag1))
{
if(key==11)
{
i=0;
if((a[0]==password[0])&&(a[1]==password[1])&&(a[2]==password[2])&&(a[3]==password[3])&&(a[4]==password[4])&&(a[5]==password[5]))
{
flag1=1;
write_com(0x01);
delay(10);
write_com(0x0c);
delay(10);
write_com(0x80+4);
for(num1=0;num1<6;num1++)
{
write_data(table1[num1]);
}
}
else
{
write_com(0x01);
delay(10);
write_com(0x0c);
delay(10);
write_com(0x80+4);
for(num2=0;num2<6;num2++)
{
write_data(table2[num2]);
}
ss++;
if(ss==3)
{
flag=1;
write_com(0x01);
write_com(0x0c);
write_com(0x80+0x40+4);
for(num3=0;num3<6;num3++)
{
write_data(table4[num3]);
}
}
}
}
}
if(key==12)
{
changepassword();
}
}
}
J. 数字密码锁C语言编程
近年来,随着生活水平的不断改善,个人财富日益增长,人们对安全防盗的要求也逐渐提高。安全可靠、使用方便的电子密码锁成了人们防盗的首选。以Max +PlusⅡ(Multiple Array Matrix and ProgrammingLogic User SystemⅡ,多阵列矩阵及可编程逻辑用户系统Ⅱ)为工作平台,使用PLD可编程器件和VHDL语言设计的带音乐的电子密码锁具有密码预置,误码锁死及开锁音乐提示等功能。这种设计不仅简化了系统结构,降低了成本,更提高了系统的可靠和保密性。采用PLD可编程逻辑器件开发的数字系统,可以方便地升级和改进。
1 设计思路
密码锁电路由键盘控制、密码设置和音乐演奏三大功能模块组成,原理如图1所示。Count,Keyvalue,Contrl,Smdisplay构成键盘控制模块,Songer是音乐演奏模块,Set是密码设置模块。
1.1 键盘控制
键盘主要完成向系统输入数据,传送命令等功能。它是一个机械弹性按键开关的集合,利用机械触点的合、断作用产生高、低电平。通过对电平高低状态的检测,以确认按键按下与否。一个电压信号通过机械触点的断开、闭合过程的波形如图2所示。
在该键盘电路中,Count模块提供键盘的行扫描信号Q[3..0]。在没有按键按下时,信号EN为高电平,行扫描输出信号Q[3..0]的循环变化顺序为0001 OO100100 1000 0001(依次扫描4行按键);当有按键按下时,信号EN为低电平,行扫描输出信号Q[3..0]停止扫描,并锁存当前的行扫描值。例如按下第一行的按键,那么Q[3..O]=0001。
Keyvalue模块的主要功能是对输入按键的行信号Q[3..0]和列信号14[3..0]的当前组合值进行判断来确定输入按键的键值。
Contrl模块的主要功能是实现按键的消抖,判断是否有按键按下。确保对按键的提取处于图2所示的闭合稳定时间范围内,这就对本模块的输入时钟信号有一定的要求,在本设计中该模块输入的时钟信号频率为64 Hz。Smdisplay模块主要是完成数码管动态扫描和七段译码显示的功能。
1.2 音乐演奏电路Songer
根据声乐学知识,组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能连续演奏所需的两个基本要素。获得这两个要素所对应的数值以及通过纯硬件的手段来利用这些数值实现所希望乐曲的演奏效果是关键。如图3所示,该电路需要由NOTETABS(音调发生器)、TONETABA、SPEAKER(数控分频器)三个模块组成,分别实现了声音产生、节拍控制、音调控制的功能。
1.3 密码设置
Set模块是实现密码锁功能的核心模块。其主要作用是设置密码,Set为设置密码的有效信号,可以实现修改密码的功能。En为输入密码确认信号,当输入完六位密码后确认输入,一旦输入的密码跟所设置的密码一致时,则输出信号OP有效(高电平);OP控制演奏音乐,此时音乐响起。若密码不正确,则指示输入错误及输入次数,输完三次无效后密码锁锁死,必须由RESET信号(启动信号,给一个低电平)重新打开密码锁功能。
2 电路的VHDL描述
键盘控制电路,音乐演奏电路以及密码设置模块均使用硬件描述语言VHSIC Hardware Description Lan-guage(VHDL)设计而成。例如:TONETABA的VHDL模型如下:
VHDL语言具有很强的电路描述和建模能力,能从多个层次对数字系统进行建模和描述,支持各种模式的设计方法:自顶向下与自底向上或混合方法,从而大大简化了硬件的设计任务,提高了设计效率和可靠性。它同时具有与具体硬件电路无关和与设计平台无关的特性,所以用VHDL进行电子系统设计,设计者可以专心致力于其功能的实现,而不需要对其他相关因素花费过多的时间和精力。
设计步骤
3.1 设计输入
首先在合适的路径下建立本设计的文件夹,然后用VHDL语言编辑Count,Keyvalue,Contrl,Smdisplay等电路,并在Max+PlusⅡ软件中使用文本编辑器输入上述各电路模块的VHDL程序,编译生成各模块;最后在Max+PlusⅡ软件中使用图形编辑器以自底向上的方法编辑原理图。先编辑图3电路,以Singer.gdf命名,其次使用“Create default Symbol”生成Songer模块,然后再编辑如图1所示原理电路图。
3.2 仿真测试及编程下载配置
将设计好的项目存盘,并将其设置成Project。选择目标器件为ACEX系列中的EP1K30QC208-2,启动编译,如果发现编译出现错误,修正后再次编译。编译后即可对波形文件进行仿真,并进行测试和波形分析。分析完成后进行编程下载配置。
3.3 硬件测试
在高电平时,通过键盘的0~F号键进行6位密码输入,密码输入完毕后通过单击确认键进行密码设置确认。当输入的密码与设置的密码一致时,扬声器开始循环演奏乐曲,且数码管SM8显示输入密码的次数,数码管SM7显示密码输入是否正确。如果密码正确,则SM7显示‘0’;如果密码错误,则SM7显示‘E’。数码管SM6~SM1显示输入的6位密码。在密码输入正确开始演奏乐曲时,如果将拨位开关KD4拨向上,则数码管SM8显示乐曲的音符,而此时若将拨位开关KD3拨向上则停止演奏乐曲。发光二极管LED1~LED4显示输入按键的键值,LED16监控是否有按键按下。
4 结 语
使用Max+PlusⅡ软件和VHDL语言设计电路,思路简单,功能明了;不仅可以进行逻辑仿真,还可以进行时序仿真;使用PLD器件不仅省去了电路制作的麻烦,还可以反复多次进行硬件实验,非常方便地修改设计,且设计的电路保密性很强。总之,采用Max+PlusⅡ软件和VHDL语言使得复杂的电子系统的设计变得简单容易,大大提高了设计效率。
如果对您有帮助,请记得采纳为满意答案,谢谢!祝您生活愉快!