单片机c语言密码锁程序

单片机c语言密码锁程序,第1张

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=0j<8j++)//清屏

TempData[j]=0

}

if(i<8)

{

temp[i]=dofly_DuanMa[num]//把按键值输入到临时数组中

for(j=0j<=ij++) //通过一定顺序把临时数组中

//的值赋值到显示缓冲区,从右往左输入

TempData[7-i+j]=temp[j]

}

i++ //输入数值累加

if(i==9)//正常等于8即可,由于我们需要空一个用于清屏,

//清屏时的按键不做输入值

{

i=0

Flag=1//先把比较位置1

for(j=0j<8j++)//循环比较8个数值,

//如果有一个不等 则最终Flag值为0

Flag=Flag&&(temp[j]==dofly_DuanMa[password[j]])

//比较输入值和已有密码

for(j=0j<8j++)//清屏

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 0break//0 按下相应的键显示相对应的码值

case 0x7d:return 1break//1

case 0x7b:return 2break//2

case 0x77:return 3break//3

case 0xbe:return 4break//4

case 0xbd:return 5break//5

case 0xbb:return 6break//6

case 0xb7:return 7break//7

case 0xde:return 8break//8

case 0xdd:return 9break//9

case 0xdb:return 10break//a

case 0xd7:return 11break//b

case 0xee:return 12break//c

case 0xed:return 13break//d

case 0xeb:return 14break//e

case 0xe7:return 15break//f

default:return 0xffbreak

}

}

用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()//修改密码函数

}

}

}

}


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

原文地址: http://outofmemory.cn/yw/7770197.html

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

发表评论

登录后才能评论

评论列表(0条)

保存