分享一个自己上周做的课程设计:密码锁不仅有基本的功能,还有实现密码正确电机正转三圈,反转三圈。
以下是电路仿真截图及工程文件截图以及视频演示。有需要的可以自行下载。
开机时实物照片
密码正确时实物照片
仿真电路原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序(hex文件):
- #include<reg51.h>
- #include"lcd.h"
- #define GPIO_KEY P1
- #define uint unsigned int
- #define INT8U unsigned char
- unsigned char KeyValue,flag,key;
- //用来存放读取到的键值
- unsigned char KeyState;
- //用来存放按键状态
- unsigned char PuZh[]="H082";
- unsigned char time[]=" TIME5 ";
- unsigned char key_right[]="right";
- unsigned char key_error[]="error";
- unsigned char right_dat[]="9999";
- unsigned char dat[]="0123456789HBCDEF";
- unsigned char key_dat[4]={0};
- void Delay10ms(char time); //延时10ms
- void KeyDown(); //检测按键函数
- void test(); //密码检测函数
- void STEP_MOTOR_FFW(INT8U n);
- void STEP_MOTOR_REV(INT8U n);
-
- void clock_write(uchar ad,uint s);
- sbit LED0= P2^3;
- sbit BEEP= P2^2;
- unsigned char FFW[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};
- unsigned char REV[]={0X09,0X08,0X0C,0X04,0X06,0X02,0X03,0X01};
- INT8U second;
- INT8U second=5;
- INT8U int_time;
- /*******************************************************************************
- * 函 数 名 : main
- * 函数功能 : 主函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void main(void)
- {
- unsigned char i,j;
- LcdInit();
- KeyState=0;
- TMOD=0X01;
- EA=1;
- ET0=1;
- TH0=(65536-46083)/256;
- TL0=(65536-46083)%256;
- TR0=0;
- int_time=0;
- for(i=0;i<16;i++)
- {
- LcdWriteData(PuZh[i]);}
- Delay10ms(3000); //等待3秒
- LcdWriteCom(0x01);
- while(1)
- {
- KeyDown();
- if(KeyValue==11) // 密码不显示
- {
- LcdWriteCom(0x01);
- LcdWriteCom(0x80+0x40);
- key=0;
- }
- if(KeyState)
- {
- KeyState=0;
- LcdWriteCom(0x80+0x40+key);
- if(KeyValue<11)
- {
- LcdWriteData(dat[KeyValue]);
- key_dat[key]=dat[KeyValue];
- key++;
- if(key==4)
- {
- test();key=0;
- }
- }
- }
- }
- }
- /*******************************************************************************
- * 函 数 名 : KeyDown
- * 函数功能 : 检测有按键按下并读取键值
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void KeyDown(void)
- {
- char a,j;
- GPIO_KEY=0x0f;
- if(GPIO_KEY!=0x0f)
- {
- Delay10ms(1);
- if(GPIO_KEY!=0x0f)
- {
- KeyState=1;
- //测试列
- GPIO_KEY=0X0F;
- switch(GPIO_KEY)
- {
- case(0X07): KeyValue=0;break;
- case(0X0b): KeyValue=1;break;
- case(0X0d): KeyValue=2;break;
- case(0X0e): KeyValue=3;break;
- }
- //测试行
- GPIO_KEY=0XF0;
- Delay10ms(1);
- switch(GPIO_KEY)
- {
- case(0X70): KeyValue=KeyValue;break;
- case(0Xb0): KeyValue=KeyValue+4;break;
- case(0Xd0): KeyValue=KeyValue+8;break;
- case(0Xe0): KeyValue=KeyValue+12;break;
- }
- if(KeyValue==12) //密码显示
- {
- LcdWriteCom(0x80);
- for(j=0;j<10;j++) LcdWriteData(PuZh[j]);
- for(j=0;j<4;j++)
- {
- LcdWriteCom(0x80+0x40+j);
- LcdWriteData(key_dat[j]);
- }
- }
- if(KeyValue==13) // 重新输入密码
- {
- LcdWriteCom(0x01);
- LcdWriteCom(0x80); key=0;flag=0;
- for(j=0;j<10;j++) LcdWriteData(PuZh[j]);
- for(j=0;j<4;j++) key_dat[j]=0;
- }
- while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
- {
- Delay10ms(1);
- a++;
- }
- a=0;
- }
- }
- }
- /*******************************************************************************
- * 函 数 名 : Delay10ms
- * 函数功能 : 延时函数,延时10ms
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Delay10ms(char time) //误差 0us
- {
- unsigned char a,b,c;
- for(c=time;c>0;c--)
- for(b=38;b>0;b--)
- for(a=130;a>0;a--);
- }
- /*******************************************************************************
- * 函 数 名 : test
- * 函数功能 : 密码检测函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void test()
- { uint x;
- INT8U N=3;
- char i,j;
- for(i=0;i<4;i++)//密码检测
- {
- if(right_dat[i]==key_dat[i]) flag++;
- }
- if(flag==4) //密码正确
- {
-
- for(j=0;j<5;j++) LcdWriteData(key_right[j]);
- for(x=0;x<100;x++) //光声控制
- {Delay10ms(1);BEEP=~BEEP;}
- BEEP=1;
- LED0=0;
- STEP_MOTOR_FFW(N); //电机
- TR0=1;
- for(j=0;j<16;j++) //倒计时
- {
- LcdWriteData(time[j]);}
- clock_write(0x80,second);
- }
- else //密码错误
- {
- flag=0;
- LcdWriteCom(0x80+0x46);
- Delay10ms(50);
- for(j=0;j<5;j++) LcdWriteData(key_error[j]);
- }
- }
- void STEP_MOTOR_FFW(INT8U n) //电机
- { INT8U i,j;
- for(i=0;i<5*n;i++)
- { for(j=0;j<8;j++)
- {P3=FFW[j];
- Delay10ms(25);}} }
- void STEP_MOTOR_REV(INT8U n)
- { INT8U i,j;
- for(i=0;i<5*n;i++)
- { for(j=0;j<8;j++)
- {P3=REV[j];
- Delay10ms(25);}} }
- void clock_write(uchar ad,uint second) //倒计时
- { LcdWriteCom(ad);
- LcdWriteData(second);
- Delay10ms(100);}
- void T0_interserve(void) interrupt 1
- { INT8U N=3;
- TH0=(65536-46083)/256;
- TL0=(65536-46083)%256;
- int_time++;
- if(int_time==20)
- { int_time=0;
- second--;}
- if(second==0)
- {STEP_MOTOR_REV(N);}
-
- }
- #include"lcd.h"
- /*******************************************************************************
- * 函 数 名 : Lcd1602_Delay1ms
- * 函数功能 : 延时函数,延时1ms
- * 输 入 : c
- * 输 出 : 无
- * 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
- *******************************************************************************/
- void Lcd1602_Delay1ms(uint c) //误差 0us
- {
- uchar a,b;
- for (; c>0; c--)
- {
- for (b=199;b>0;b--)
- {
- for(a=1;a>0;a--);
- }
- }
-
- }
- /*******************************************************************************
- * 函 数 名 : LcdWriteCom
- * 函数功能 : 向LCD写入一个字节的命令
- * 输 入 : com
- * 输 出 : 无
- *******************************************************************************/
- #ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
- void LcdWriteCom(uchar com) //写入命令
- {
- LCD1602_E = 0; //使能
- LCD1602_RS = 0; //选择发送命令
- LCD1602_RW = 0; //选择写入
-
- LCD1602_DATAPINS = com; //放入命令
- Lcd1602_Delay1ms(1); //等待数据稳定
- LCD1602_E = 1; //写入时序
- Lcd1602_Delay1ms(5); //保持时间
- LCD1602_E = 0;
- }
- #else
- void LcdWriteCom(uchar com) //写入命令
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 0; //选择写入命令
- LCD1602_RW = 0; //选择写入
- LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //写入时序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- // Lcd1602_Delay1ms(1);
- LCD1602_DATAPINS = com << 4; //发送低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //写入时序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 数 名 : LcdWriteData
- * 函数功能 : 向LCD写入一个字节的数据
- * 输 入 : dat
- * 输 出 : 无
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdWriteData(uchar dat) //写入数据
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //选择输入数据
- LCD1602_RW = 0; //选择写入
- LCD1602_DATAPINS = dat; //写入数据
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //写入时序
- Lcd1602_Delay1ms(5); //保持时间
- LCD1602_E = 0;
- }
- #else
- void LcdWriteData(uchar dat) //写入数据
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //选择写入数据
- LCD1602_RW = 0; //选择写入
- LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //写入时序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- LCD1602_DATAPINS = dat << 4; //写入低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //写入时序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 数 名 : LcdInit()
- * 函数功能 : 初始化LCD屏
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x38); //开显示
- LcdWriteCom(0x0c); //开显示不显示光标
- LcdWriteCom(0x06); //写一个指针加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //设置数据指针起点
- }
- #else
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x32); //将8位总线转为4位总线
- LcdWriteCom(0x28); //在四位线下的初始化
- LcdWriteCom(0x0c); //开显示不显示光标
- LcdWriteCom(0x06); //写一个指针加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //设置数据指针起点
- …………
- …………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
全部资料51hei下载地址:
多功能密码锁.rar
(14.8 MB, 下载次数: 210)
|