基于51单片机的密码锁程序

基于51单片机的密码锁程序,第1张

用STC52编的,下面是C程序,调试已经成功,自己看程序吧……

#include<reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

#define LCD_data P0

sbit SDA=P3^5

sbit SCL=P3^4//24C08控制口设置

sbit LCD_RS = P3^3 //寄存器选择输入

sbit LCD_RW = P3^6 //液晶读/写控制

sbit LCD_EN = P3^7 //液晶使能控制

sbit LCD_PSB = P3^2 //串/并方式控制

sbit FM=P2^4//蜂鸣器控制口

sbit RS=P2^5

sbit T_CLK = P2^0//实时时钟时钟线引脚 //

sbit T_IO = P2^1//实时时钟数据线引脚 //

sbit T_RST = P2^2//实时时钟复位线引脚 //

sbit ds=P2^3

sbit EN=P2^6

sbit ZZ=P2^7

sbit FZ=P3^1

sbit ACC0=ACC^0

sbit ACC7=ACC^7

uint temp1,s_temp //定义整形变量

float f_temp //定义浮点型变量

uchar time[]=" : : "

uchar day[]=" 20 / / ( ) "

uchar temp0[]=" 温度: . 度 "

uchar num,num1,flag,count,a,b

uchar unlock_i//解密标志位

uchar t[4]

uchar t1[4]

void delay_ms(uint z)//长延时

{

uint x,y

for(x=zx>0x--)

for(y=110y>0y--)

}

void delay() //短延时,大约5us

{

}

void reshi()

{

if(RS==1)

{ unlock_i=1

}

else

{

unlock_i=0

}

}

uchar code mima[]={'0','1','2','3','4','5','6','7','8','9','0','*'}

void lcd_xieping0(uchar x,uchar y,uchar date)

void lcd_xieping(uchar x,uchar y,uchar *str)

//********************************************************

//开机显示

//********************************************************

void kjxs()

{

uint i,j

lcd_xieping(0,0,"****************")

lcd_xieping(1,0,"欢迎进入")

lcd_xieping(2,0," 密码锁系统! ")

lcd_xieping(3,0,"****************")

delay_ms(4000)

lcd_xieping(0,0," 系统初始化中 ")

lcd_xieping(1,0,"请稍后…")

lcd_xieping(2,0,"————————")

lcd_xieping(3,0," ")

for(j=3j>0j--)

{

for(i=0i<8i++)

{

lcd_xieping(3,i,"*")

delay_ms(250)

}

lcd_xieping(3,0,"")

}

}

//********************************************************

//12864显示

//********************************************************

void write_cmd(uchar cmd)

{

LCD_RS = 0

LCD_RW = 0

LCD_EN = 0

P0 = cmd

delay_ms(5)

LCD_EN = 1

delay_ms(5)

LCD_EN = 0

}

void write_dat(uchar dat)

{

LCD_RS = 1

LCD_RW = 0

LCD_EN = 0

P0 = dat

delay_ms(5)

LCD_EN = 1

delay_ms(5)

LCD_EN = 0

}

void lcd_xieping0(uchar x,uchar y,uchar date)

{

switch(x)

{

case 0: write_cmd(0x80+y)break

case 1: write_cmd(0x90+y)break

case 2: write_cmd(0x88+y)break

case 3: write_cmd(0x98+y)break

}

write_dat(date)

}

void lcd_xieping(uchar x,uchar y,uchar *str)

{

switch(x)

{

case 0: write_cmd(0x80+y)break

case 1: write_cmd(0x90+y)break

case 2: write_cmd(0x88+y)break

case 3: write_cmd(0x98+y)break

}

while (*str)

{

write_dat(*str)

str++

}

}

void lcd_init()

{

LCD_PSB = 1//并口方式

write_cmd(0x30) //基本指令 *** 作

delay_ms(5)

write_cmd(0x0C) //显示开,关光标

delay_ms(5)

write_cmd(0x01) //清除LCD的显示内容

delay_ms(5)

}

//**************************************************************

// 键盘扫描函数

//**************************************************************

uchar keyscan1()//矩阵键盘扫描函数

{

uchar temp

while(!num)

{P1=0xfe//赋值

temp=P1//读回数据

temp=temp&0xf0 //与运算

if(temp!=0xf0) //判断

{

delay_ms(2) //延时消抖

temp=P1//读回数据

temp=temp&0xf0

if(temp!=0xf0)

{

switch(temp) //多分支选择

{

case 0x70:num=1break //跳出

case 0xb0:num=2break

case 0xd0:num=3break

case 0xe0:num=4break

}

while(temp!=0xf0)

{

temp=P1

temp=temp&0xf0

}//等待按键释放

}

}

P1=0xfd//赋值

temp=P1//读回数据

temp=temp&0xf0 //与运算

if(temp!=0xf0) //判断

{

delay_ms(2) //延时消抖

temp=P1//读回数据

temp=temp&0xf0

if(temp!=0xf0)

{

switch(temp) //多分支选择

{

case 0x70:num=5break //跳出

case 0xb0:num=6break

case 0xd0:num=7break

case 0xe0:num=8break

}

while(temp!=0xf0)

{

temp=P1

temp=temp&0xf0

}//等待按键释放

}

}

P1=0xfb//赋值

temp=P1//读回数据

temp=temp&0xf0 //与运算

if(temp!=0xf0) //判断

{

delay_ms(2) //延时消抖

temp=P1//读回数据

temp=temp&0xf0

if(temp!=0xf0)

{

switch(temp) //多分支选择

{

case 0x70:num=9break //跳出

case 0xb0:num=10break

case 0xd0:num=11break

case 0xe0:num=12break

}

while(temp!=0xf0)

{

temp=P1

temp=temp&0xf0

}//等待按键释放

}

}

}

return(num)//返回值

}

uchar keyscan2()

{

uchar temp

while(!num1)

{P1=0xf7//赋值

temp=P1//读回数据

temp=temp&0xf0 //与运算

if(temp!=0xf0) //判断

{

delay_ms(2) //延时消抖

temp=P1//读回数据

temp=temp&0xf0

if(temp!=0xf0)

{

switch(temp) //多分支选择

{

case 0x70:num1=1break //跳出

case 0xb0:num1=2break

case 0xd0:num1=3break

case 0xe0:num1=4break

}

while(temp!=0xf0)

{

temp=P1

temp=temp&0xf0

}//等待按键释放

}

}

}

return(num1)

}

//**************************************************************

//直流电机

//**************************************************************

void dianjiZZ()

{

EN=1

ZZ=1

FZ=0

}

void dianjiFZ()

{

EN=1

ZZ=0

FZ=1

}

void dianji_stop()

{

EN=0

}

//**************************************************************

//EPPROM

//**************************************************************

void start() //启动信号

{

SDA=1

delay()

SCL=1

delay()

SDA=0

delay()

}

void stop()//停止信号

{

SDA=0

delay()

SCL=1

delay()

SDA=1

delay()

}

void respons() //响应信号

{

uchar i

SCL=1

delay()

while((SDA==1)&&(i<250))

i++

SCL=0

delay()

}

void writebyte(uchar date) //写一个字节

{

uchar i,temp

temp=date

for(i=0i<8i++)

{

temp=temp<<1

SCL=0

delay()

SDA=CY

delay()

SCL=1

delay()

}

SCL=0

delay()

SDA=1//释放总线

delay()

}

uchar readbyte() //读一个字节

{

uchar i,k

SCL=0

delay()

SDA=1

for(i=0i<8i++)

{

SCL=1

delay()

k=(k<<1)|SDA

SCL=0

delay()

}

delay()

return(k)

}

void write(uchar add,uchar date) //在一个地址写一个字节

{

start()

writebyte(0xa0)

respons()

writebyte(add)

respons()

writebyte(date)

respons()

stop()

}

uchar read(uchar add) //在一个地址读一个字节

{

start()

writebyte(0xa0)

respons()

writebyte(add)

respons()

start()

writebyte(0xa1)

respons()

b=readbyte()

respons()

stop()

return(b)

}

//**************************************************************

//时间日期函数

//**************************************************************

void v_WTInputByte(uchar ucDa)

{

uchar i

ACC= ucDa

for(i=8i>0i--)

{

T_IO = ACC0//*相当于汇编中的 RRC

T_CLK = 1

T_CLK = 0

ACC =ACC>>1

}

}

uchar uc_RTOutputByte(void)

{

uchar i

for(i=8i>0i--)

{

ACC = ACC>>1//*相当于汇编中的 RRC

ACC7 = T_IO

T_CLK = 1

T_CLK = 0

}

return(ACC)

}

void v_W1302(uchar ucAddr, uchar ucDa)

{

T_RST = 0

T_CLK = 0

T_RST = 1

v_WTInputByte(ucAddr)/* 地址,命令 */

v_WTInputByte(ucDa)/* 写1Byte数据*/

T_CLK = 1

T_RST =0

}

uchar uc_R1302(uchar ucAddr)

{

uchar ucDa

T_RST = 0

T_CLK = 0

T_RST = 1

v_WTInputByte(ucAddr)// 地址,命令 //

ucDa = uc_RTOutputByte()// 读1Byte数据 //

T_CLK = 1

T_RST =0

return(ucDa)

}

void Init1302(void)

{

v_W1302(0x8e,0x00) //控制写入WP=0

v_W1302(0x80,0x80)

v_W1302(0x90,0xa9)

v_W1302(0x80,0x00) //秒

v_W1302(0x82,0x24) //分

v_W1302(0x84,0x12) //时

v_W1302(0x86,0x29) //日

v_W1302(0x88,0x10) //月

v_W1302(0x8a,0x05) //星期

v_W1302(0x8c,0x10) //年 //

v_W1302(0x8e,0x80)

}

void donetime(void)

{

uchar d

d=uc_R1302(0x87)

day[10]=(d&0x0f)+48

day[9]=((d>>4)&0x03)+48

d=uc_R1302(0x89)

day[7]=(d&0x0f)+48

day[6]=((d>>4)&0x01)+48

d=uc_R1302(0x8b)

day[13]=(d&0x07)+48

d=uc_R1302(0x8d)

day[4]=(d&0x0f)+48

day[3]=(d>>4)+48

d=uc_R1302(0x81)

time[15]=(d&0x0f)+48

time[14]=(d>>4)+48

d=uc_R1302(0x83)

time[12]=(d&0x0f)+48

time[11]=(d>>4)+48

d=uc_R1302(0x85)

time[9]=(d&0x0f)+48

time[8]=(d>>4)+48

}

//**************************************************************

//温度检测函数

//**************************************************************

void dsreset(void)//18B20复位,初始化函数

{

uint i

ds=0

i=103

while(i>0)i--

ds=1

i=4

while(i>0)i--

}

bit tempreadbit(void) //读1位函数

{

uint i

bit dat

ds=0i++ //i++ 起延时作用

ds=1i++i++

dat=ds//读数据

i=8while(i>0)i--

return (dat)

}

uchar tempread(void) //读1个字节

{

uchar i,j,dat

dat=0

for(i=1i<=8i++)

{

j=tempreadbit()

dat=(j<<7)|(dat>>1) //读出的数据最低位在最前面,这样刚好一个字节在DAT里

}

return(dat)

}

void tempwritebyte(uchar dat) //向18B20写一个字节数据

{

uint i

uchar j

bit testb

for(j=1j<=8j++)

{

testb=dat&0x01 //判断最后一位是1还是0

dat=dat>>1

if(testb) //写 1

{

ds=0

i++i++

ds=1

i=8while(i>0)i--

}

else

{

ds=0 //写 0

i=8while(i>0)i--

ds=1

i++i++

}

}

}

void tempchange(void) //DS18B20 开始获取温度并转换

{

dsreset()//初始化,每次对18B20的 *** 作都首先要初始化

delay_ms(1)

tempwritebyte(0xcc) // 写跳过读ROM指令

tempwritebyte(0x44) // 写温度转换指令

}

void get_temp() //读取寄存器中存储的温度数据

{

uchar a,b

dsreset() //初始化

delay_ms(1)

tempwritebyte(0xcc) // 写跳过读ROM指令

tempwritebyte(0xbe) //写读指令

a=tempread()//读低8位

b=tempread()//读高8位

temp1=b

temp1<<=8 //两个字节组合为1个字

temp1=temp1|a

f_temp=temp1*0.0625 //温度在寄存器中为12位 分辨率位0.0625°

}

//**************************************************************

//解密函数

//**************************************************************

void unlock()

{

uchar in,i

if(num==0)

{

lcd_xieping(0,0,"**密码锁系统**")

lcd_xieping(1,0,"—————————")

lcd_xieping(2,0," 请输入密码: ")

lcd_xieping(3,0,"")

for(i=0i<4i++)

{

t1[i]=keyscan1()

lcd_xieping(3,i,"*")

num=0

}//输密码

}

in=keyscan1()

if(in==12)//in-确定键标志位

{

in=0

num=0

if((t1[0]==t[0])&&(t1[1]==t[1])&&(t1[2]==t[2])&&(t1[3]==t[3]))

{

flag=1//解密成功与否标志位

//unlock_i=1

a=0//功能键标志

lcd_xieping(0,0,"**密码锁系统** ")

lcd_xieping(1,0,"——————————")

lcd_xieping(2,0,"密码正确!")

lcd_xieping(3,0," 您的身份已确认")

delay_ms(1500)

lcd_xieping(1,0,"————————")

lcd_xieping(2,0,"功能 I 开锁")

lcd_xieping(3,0," II修改密码")

}

else

{

flag=0

count++

if(count==3)

{

count=0

num=1

lcd_xieping(1,0,"——————————")

lcd_xieping(2,0,"您的机会已用完 ")

lcd_xieping(3,0,"对不起**无法进入")

FM=0

delay_ms(1000)

FM=1

}

}

}

}

//**************************************************************

// 修改密码函数

//**************************************************************

void xiugaimima()

{ uchar i,j,l,im,ib

uchar t2[4]

uchar t3[4]

num=0

lcd_xieping(1,0,"————————")

lcd_xieping(2,0,"请输入新密码: ")

lcd_xieping(3,0,"")

for(i=0i<4i++)

{

t2[i]=keyscan1()

lcd_xieping0(3,i,mima[num])

num=0

}

im=keyscan1()

if(im==12)//im,in,ib,同为确定键标志位

{

im=0

num=0

lcd_xieping(1,0,"————————")

lcd_xieping(2,0,"请再次输入新密码")

lcd_xieping(3,0,"")

for(i=0i<4i++)

{

t3[i]=keyscan1()

lcd_xieping0(3,i,mima[num])

num=0

}

}

ib=keyscan1()

if(ib==12)

{

ib=0

num=0

if(t2[0]==t3[0]&&t2[1]==t3[1]&&t2[2]==t3[2]&&t2[3]==t3[3])

{

t[0]=t3[0]

t[1]=t3[1]

t[2]=t3[2]

t[3]=t3[3]

lcd_xieping(1,0,"————————")

lcd_xieping(2,0,"祝贺您!")

lcd_xieping(3,0," 密码修改成功 ")

flag=0

for(j=0j<4j++)

{

l=j+1

write(l,t[j])

delay_ms(10)

}//24C08写数据

delay_ms(1000)

}

else

{

lcd_xieping(2,0,"两次输入密码不同")

lcd_xieping(3,0," 密码修改失败 ")

flag=1

delay_ms(500)

}

}

}

//**************************************************************

//显示函数

//**************************************************************

void xianshi()

{

donetime()

tempchange()

get_temp()

s_temp=f_temp*100

temp0[7]=(s_temp/1000)+48

temp0[8]=(s_temp%1000/100)+48

temp0[10]=(s_temp%100/10)+48

temp0[11]=(s_temp%10)+48

lcd_xieping(0,0,"**密码锁系统** ")

lcd_xieping(1,0,temp0)

lcd_xieping(2,0,day)

lcd_xieping(3,0,time)

num=0

}

//**************************************************************

//开锁函数

//**************************************************************

void kaisuo()

{

uchar i

lcd_xieping(2,0,"开锁中…… ")

lcd_xieping(3,0,"——耐心等待——")

for(i=3i>0i--)

{

FM=0

delay_ms(100)

FM=1

delay_ms(100)

flag=0

}

dianjiZZ()

delay_ms(10000)

dianji_stop()

lcd_xieping(2,0,"—开锁过程结束—")

lcd_xieping(3,0,"请开门")

delay_ms(5000)

dianjiFZ()

delay_ms(10000)

dianji_stop()

flag=0

}

//**************************************************************

//主函数

//**************************************************************

void main()

{

uchar m

unlock_i=1

lcd_init() //液晶初始化

//Init1302()

kjxs() //开机显示

for(m=0m<4m++)

{

t[m]=read(m+1)

delay_ms(10)

}//24C08读数据

while(1)

{

reshi()

if(!unlock_i)

{

unlock()//解密函数

}

else

{

xianshi()//时间、日期、温度显示函数

}

if(flag==1)

{

num1=0

a=keyscan2()

if(a==1)

{

kaisuo()//开锁函数

}

if(a==2)

{

xiugaimima()//修改密码函数

}

}

}

}

用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;//否则,报警


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/7742027.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-09
下一篇 2023-04-09

发表评论

登录后才能评论

评论列表(0条)

保存