该题目是作者课程设计时所写题目,隔了段时间了,之前一直放到自己的网站上的,现在网站资源过期了,就放到这里保存了。
题目要求如下:
内容及要求 以MCS-51单片机为核心,设计一个通过面板键盘输入密码的数字式密码锁控制系统,具体要求如下: ① 密码通过面板键盘输入,由4~6位数字组成; ② 输入的密码与密钥相符时,控制3相6拍微型步进电机正转到开锁传感器到位,三次不符时,声光报警; ③ 开锁后5秒,检查关门传感器,若到位则控制3相6拍微型步进电机正转锁门,否则报警提示; ④ 密钥可以通过面板键盘更新; ⑤ 采用液晶显示器显示密码输入过程、密码输入错误等相关信息。 |
⑥ 拓展与创新。
这个题目的内容也不是很多,就是输入密码,如果正确则驱动电机转动开门(只驱动电机,其他的没搞),还有就是开门后要检测门是否关上以及是否长时间未关门。关门检测使用到了接近开关传感器(使用简单,近距离金属靠近则会有电平变化,就可以进行操作)。
本题目很多都是用到定时去处理一些东西,不是很灵活,而且代码有些冗余,所以改进空间还是很大的。
话不多说直接放代码和电路图以及框图。
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_DATAPINS P0 //显示屏的定义
#define GPIO_KEY P1
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
sbit LED_GREEN=P2^2;
sbit LED_RED=P2^3;
sbit SPEAKER=P3^3;
sbit JJKG=P3^4;
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;
sbit motorA = P1^0;
sbit motorB = P1^1;
sbit motorC = P1^2;
sbit motorD = P1^3;
char code table[]="INPUT:";
char code jianzhi[]="0123456789ABCDEF" ;
char code zhebi[]="************* ";
char code baocuo[]="ERROR";
char code dengdai[]="WAIT";
char code zaicishuru[]="INPUT AGAIN";
char code door[]="DOOR IS OPEN" ;
char code xinmima[]="SET SECRETE";
char code successful[]="SUCCESS";
char code Warnning[]="WARNING!";
char code GM[]="ATTENTION";
char code lock[]="------LOCK------" ;
char code ss[]="****************";
char code root[]="ROOT: *****" ;
//char kaimen[5]={1,2,3,4,5};
char kaimen[5];
char guanliyuan[5]={1,1,1,1,1};
char cunchumima[5];
char tz_flag;
uchar gm_flag=0;
uchar cuowu_flag=0;
uchar pd_flag;
uchar xunhuancishu;
uchar s=0;
uchar sp_flag=0;
uchar ks_flag=1;
uchar gl_flag=0;
uchar tiaozhuan_flag=0;
int data num[5];
uchar km_flag=1;
uchar n;
uchar i;
uchar k;
uchar m=0;
uchar j;
uchar r;
uchar guanmenjishi;
uchar password[5];
uint hang;
uint lie;
uint _flag_=0,cp=0;
void Delay1ms(uint c);
void Read_Busy() ;
void write_data(uchar date) ; //LCD1602写入8位命令子函数
void write_com(uchar com) ; //LCD1602写入8位数据子函数
void init(); //LCD1602初始化子程序
uint count(uint hang,uint lie);
void tishixinxi();
void addr_x_y(uint x,uint y);
void display(uint x,uint y,uint z);
void mimadisplay();
void keyboard(); //键盘按键扫描函数
void chenggong();
void shibai();
void mima();
void xiugaimima();
void JG();
void fanzhuan();
void guanmenbaojin();
void spchengxu();
void delay(uint t) ;
void zhengzhuan();
//--声明全局变量--//
void I2C_Delay10us();
void I2C_Start(); //起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
void I2C_Stop(); //终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
uchar I2C_SendByte(uchar dat, uchar ack);//使用I2c读取一个字节
uchar I2C_ReadByte(); //通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,保持发送信号I2C_SDA保持稳定
/*********************IIC.c*************************************/
//延时:1us
void timer_init()
{
TMOD=0x01;
TL0=0xb0;
TH0=0x3c;
ET0=1;
EA=1;
}
void timer_1() interrupt 1
{
TL0=0xb0;
TH0=0x3c;
cp++;
if(cp==100){
cp=0;
_flag_=1;
}
TR0=1;
}
void I2C_Delay10us()
{
uchar a, b;
for(b=1; b>0; b--)
{
for(a=2; a>0; a--);
}
}
// 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
void I2C_Start()
{
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
I2C_SDA = 0;
I2C_Delay10us();//保持时间是>4us
I2C_SCL = 0;
I2C_Delay10us();
}
//终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
void I2C_Stop()
{
I2C_SDA = 0;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间大于4.7us
I2C_SDA = 1;
I2C_Delay10us();
}
//通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间, 保持发送信号I2C_SDA保持稳定
uchar I2C_SendByte(uchar dat, uchar ack)
{
uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。
for(a=0; a<8; a++)//要发送8位,从最高位开始
{
I2C_SDA = dat >> 7; //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
dat = dat << 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间>4.7us
I2C_SCL = 0;
I2C_Delay10us();//时间大于4us
}
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
{
b++;
if(b > 200) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
{
I2C_SCL = 0;
I2C_Delay10us();
return 0;
}
}
I2C_SCL = 0;
I2C_Delay10us();
return 1;
}
// 使用I2c读取一个字节
uchar I2C_ReadByte()
{
uchar a = 0,dat = 0;
I2C_SDA = 1; //起始和发送一个字节之后I2C_SCL都是0
I2C_Delay10us();
for(a=0; a<8; a++)//接收8个字节
{
I2C_SCL = 1;
I2C_Delay10us();
dat <<= 1;
dat |= I2C_SDA;
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
return dat;
}
//函数功能 : 往24c02的一个地址写入一个数据
void At24c02Write(unsigned char addr,unsigned char dat)
{
I2C_Start();
I2C_SendByte(0xa0, 1);//发送写器件地址
I2C_SendByte(addr, 1);//发送要写入内存地址
I2C_SendByte(dat, 0); //发送数据
I2C_Stop();
}
// 读取24c02的一个地址的一个数据
unsigned char At24c02Read(unsigned char addr)
{
unsigned char num;
I2C_Start();
I2C_SendByte(0xa0, 1); //发送写器件地址
I2C_SendByte(addr, 1); //发送要读取的地址
I2C_Start();
I2C_SendByte(0xa1, 1); //发送读器件地址
num=I2C_ReadByte(); //读取数据
I2C_Stop();
return num;
}
void Delay1ms(uint c)
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
void Read_Busy()
{
uchar busy;
P0 = 0xff;
LCD1602_RS = 0;
LCD1602_RW = 1;
do
{
LCD1602_E = 1;
busy = P0;
LCD1602_E = 0;
}while(busy & 0x80);
}
void write_com(uchar com) //写入命令
{
Read_Busy();//判断忙
LCD1602_E=0;
LCD1602_RS=0;
LCD1602_RW=0;
P0=com;
Delay1ms(5);
LCD1602_E=1;
Delay1ms(5);
LCD1602_E=0;
}
void write_data(uchar date) //写入数据
{
Read_Busy();//判断忙
LCD1602_E=0;
LCD1602_RS=1;
LCD1602_RW=0;
P0=date;
Delay1ms(5);
LCD1602_E=1;
Delay1ms(5);
LCD1602_E=0;
}
void init() //LCD初始化子程序
{
Delay1ms(5);
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
} //1602显示
void keyboard() //键盘按键扫描函数
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f)//检测4行中哪一行按键是否按下
{
Delay1ms(10); //延时消抖
if(GPIO_KEY != 0x0f) //再次检测4行中哪一行按键是否按下
{
switch(GPIO_KEY) //根据IO的值来确定哪一行按键按下
{
case(0x07): lie=1; break;
case(0x0b): lie=2; break;
case(0x0d): lie=3; break;
case(0x0e): lie=4; break;
}
}
}
GPIO_KEY = 0xf0;
if(GPIO_KEY != 0xf0) //检测4列中哪一列按键是否按下
{
Delay1ms(10); //延时消抖
if(GPIO_KEY != 0xf0) //再次检测4列中哪一列按键是否按下
{
switch(GPIO_KEY) //根据IO的值来确定哪一列按键按下
{
case(0x70): hang=4; break;
case(0xb0): hang=3; break;
case(0xd0): hang=2; break;
case(0xe0): hang=1; break;
}
}
while((i<50)&&(GPIO_KEY != 0xf0))
{
i++;
Delay1ms(10);
}
i=0;
}
num[m]=count(hang,lie);
if(num[m]==10)
xiugaimima();
m++;
}
uint count(uint hang,uint lie)
{
if(hang==1&&lie==1)
n=15;
if(hang==1&&lie==2)
n=0;
if(hang==1&&lie==3)
n=14;
if(hang==1&&lie==4)
n=13;
if(hang==2&&lie==1)
n=1;
if(hang==2&&lie==2)
n=2;
if(hang==2&&lie==3)
n=3;
if(hang==2&&lie==4)
n=12;
if(hang==3&&lie==1)
n=4;
if(hang==3&&lie==2)
n=5;
if(hang==3&&lie==3)
n=6;
if(hang==3&&lie==4)
n=11;
if(hang==4&&lie==1)
n=7;
if(hang==4&&lie==2)
n=8;
if(hang==4&&lie==3)
n=9;
if(hang==4&&lie==4)
n=10;
return n;
}
void tishixinxi()
{
init();
write_com(0x80);
for(i=0;i<6;i++)
write_data(table[i]);
write_com(0x80+7);
for(i=0;i<5;i++)
write_data(zhebi[i]);
}
void mima()
{
if(pd_flag==1) {
j=0;
m=0;
if(km_flag==1)
chenggong();
if(km_flag==0)
shibai();
}
}
void addr_x_y(uint x,uint y) //列,行,写坐标,定位置
{
uchar temp=0x80;
if(y)
{
temp|=0x40;
}
temp|=x;
write_com(temp);
}
void display(uint x,uint y,uint z) //显示数字
{
addr_x_y(x,y);
write_data(z+0x30);
}
void mimadisplay() //密码显示
{
while(j<5)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
{
keyboard();
password[j]=num[j];
display(j+7,0,password[j]); //显示输入的密码
if(password[j]!=kaimen[j])
km_flag=0;
j++;
}
}
pd_flag=1;
mima();
}
void main() //*****************************************************************************
{
timer_init();
tishixinxi();
for(i=0;i<5;i++){
cunchumima[i]=At24c02Read(0x02+i) ;
Delay1ms(10);
}
for(i=0;i<5;i++)
kaimen[i]=cunchumima[i];
Delay1ms(5);
while(1){
mimadisplay() ;
}
}
void chenggong() //*************************
{
init();
write_com(0x80+5);
Delay1ms(5);
for(i=0;i<4;i++)
{
write_data(dengdai[i]);
Delay1ms(5);
}
zhengzhuan();
}
void shibai() //********************
{
init();
cuowu_flag++;
sp_flag++;
if(cuowu_flag==3)
JG();
write_com(0x80);
for(i=0;i<5;i++)
write_data(baocuo[i]);
Delay1ms(100);
if(sp_flag==5)
spchengxu();
write_com(0x80+0x40);
for(i=0;i<11;i++)
write_data(zaicishuru[i]);
LED_RED=0;
Delay1ms(1000);
LED_RED=1;
km_flag=1;
tishixinxi();
mimadisplay();
}
void xiugaimima()
{
init();
j=0;
write_com(0x80);
for(i=0;i<11;i++)
write_data(xinmima[i]);
Delay1ms(500);
do //*******************************************************
{ ks_flag=1;
j=0;
m=0;
init();
write_com(0x80);
for(i=0;i<11;i++)
write_data(root[i]) ;
Delay1ms(10);
while(j<5)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
{
keyboard();
Delay1ms(10);
password[j]=num[j];
display(j+6,0,password[j]); //显示输入的密码
if(password[j]!=guanliyuan[j])
ks_flag=0;
j++;
}
}
if(ks_flag==1)
break;
}while(1) ;//***************************************
Delay1ms(500);
j=0;
m=0;
init();
for(i=0;i<6;i++)
write_data(table[i]);
while(j<5)
{GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
{
keyboard();
password[j]=num[j];
display(j+7,0,password[j]); //显示输入的密码
At24c02Write(0x02+j,password[j]);
Delay1ms(10);
kaimen[j]=password[j];
j++;
}
}
init();
Delay1ms(200);
write_com(0x80);
for(i=0;i<7;i++)
write_data(successful[i]);
LED_GREEN=0;
LED_RED=0;
Delay1ms(500);
LED_GREEN=1;
LED_RED=1;
tishixinxi();
Delay1ms(300);
j=0;
m=0;
mimadisplay();
}
void JG()
{
for(xunhuancishu=0;xunhuancishu<5;xunhuancishu++)
{
init();
write_com(0x80+5);
for(i=0;i<5;i++)
write_data(baocuo[i]);
SPEAKER=0;
LED_RED=0;
Delay1ms(500);
init();
SPEAKER=1;
LED_RED=1;
Delay1ms(100);
write_com(0x80+4);
for(i=0;i<8;i++)
write_data(Warnning[i]);
SPEAKER=0;
LED_RED=0;
Delay1ms(500);
}
SPEAKER=1;
LED_RED=1;
km_flag=1;
cuowu_flag=0;
tishixinxi();
mimadisplay();
}
void guanmenbaojin()
{
for(xunhuancishu=0;xunhuancishu<5;xunhuancishu++)
{
if(JJKG==0)
{
SPEAKER=1;
break;
}
init();
write_com(0x80+5);
for(i=0;i<9;i++)
write_data(GM[i]);
SPEAKER=0;
LED_RED=0;
Delay1ms(500);
if(JJKG==0)
{
SPEAKER=1;
break;
}
init();
SPEAKER=1;
LED_RED=1;
Delay1ms(100);
write_com(0x80+4);
for(i=0;i<8;i++)
write_data(Warnning[i]);
SPEAKER=0;
LED_RED=0;
Delay1ms(1000);
if(JJKG==0)
{
SPEAKER=1;
break;
}
}
while(1)
{
if(JJKG==0)
{
uint q;
motorA = 0;
motorB = 0;
motorC = 0;
motorD = 0;//因为P1口管脚复位初始默认高电平(内外都接有上拉电阻),本人先将四相电位置低电平
for(q=0;q<4;q++)
{
for(r=0;r<150;r++)
{
for(i = 1;i < 10; ++i)//用for循环实现几秒以上的延时函数,用while循环不能实现
{
motorD = 1;
motorA = 1;
delay(20);
} //AB通电1ms
motorD = 0;
motorA = 0; //AB关电
for(i = 1;i < 10; ++i)
{
motorC = 1;
motorD = 1;
delay(20);
}//BC通电1ms
motorC = 0;
motorD = 0; //BC关电
for(i = 1;i < 10; ++i)
{
motorB = 1;
motorC = 1;
delay(20);//CD通电1ms
}
motorB = 0;
motorC = 0;//CD关电
for(i = 1;i < 10; ++i)
{
motorA = 1;
motorB = 1;
delay(20);//DA通电1ms
}
motorA = 0;
motorB = 0;//DA关电
}
}
motorA = 1;
motorB = 1;
motorC = 1;
motorD = 1;
break;
}
}
SPEAKER=1;
LED_RED=1;
km_flag=1;
gm_flag=1;
cuowu_flag=0;
tishixinxi();
mimadisplay();
}
void spchengxu()
{
init();
Delay1ms(20);
write_com(0x80);
for(i=0;i<16;i++)
write_data(lock[i]);
Delay1ms(10);
write_com(0x80+0x40);
for(i=0;i<16;i++)
write_data(ss[i]);
Delay1ms(10);
while(1)
{
j=0;
m=0;
while(j<1)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
{
keyboard();
password[j]=num[j];
if(password[j]==14)
gl_flag=1;
j++;
}
}
Delay1ms(10);
if(gl_flag==1)
break;
}
init();
write_com(0x80);
for(i=0;i<11;i++)
write_data(root[i]) ;
Delay1ms(10);
write_com(0x80+0x40);
for(i=0;i<16;i++)
write_data(lock[i]);
Delay1ms(500);
do
{ ks_flag=1;
j=0;
m=0;
while(j<5)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
{
keyboard();
Delay1ms(10);
password[j]=num[j];
display(j+6,0,password[j]); //显示输入的密码
if(password[j]!=guanliyuan[j])
ks_flag=0;
j++;
}
}
init();
write_com(0x80);
for(i=0;i<11;i++)
write_data(root[i]) ;
Delay1ms(10);
write_com(0x80+0x40);
for(i=0;i<16;i++)
write_data(lock[i]);
Delay1ms(10);
if(ks_flag==1)
break;
}while(1) ;
j=0;
m=0;
SPEAKER=1;
LED_RED=1;
km_flag=1;
gm_flag=0;
ks_flag=1;
gl_flag=0;
sp_flag=0;
cuowu_flag=0;
tishixinxi();
mimadisplay();
}
void delay(uint t)
{
while(t--);
}
void fanzhuan()
{
uint q;
motorA = 0;
motorB = 0;
motorC = 0;
motorD = 0;//因为P1口管脚复位初始默认高电平(内外都接有上拉电阻),本人先将四相电位置低电平
for(q=0;q<4;q++)
{
for(r=0;r<150;r++)
{
for(i = 1;i < 10; ++i)//用for循环实现几秒以上的延时函数,用while循环不能实现
{
motorD = 1;
motorA = 1;
delay(20);
} //AB通电1ms
motorD = 0;
motorA = 0; //AB关电
for(i = 1;i < 10; ++i)
{
motorC = 1;
motorD = 1;
delay(20);
}//BC通电1ms
motorC = 0;
motorD = 0; //BC关电
for(i = 1;i < 10; ++i)
{
motorB = 1;
motorC = 1;
delay(20);//CD通电1ms
}
motorB = 0;
motorC = 0;//CD关电
for(i = 1;i < 10; ++i)
{
motorA = 1;
motorB = 1;
delay(20);//DA通电1ms
}
motorA = 0;
motorB = 0;//DA关电
}
}
motorA = 1;
motorB = 1;
motorC = 1;
motorD = 1;
mimadisplay();
}
void zhengzhuan()
{
uint q;
motorA = 0;
motorB = 0;
motorC = 0;
motorD = 0;//因为P1口管脚复位初始默认高电平(内外都接有上拉电阻),本人先将四相电位置低电平
for(q=0;q<4;q++)
{
for(r=0;r<150;r++)
{
for(i = 1;i < 10; ++i)//用for循环实现几秒以上的延时函数,用while循环不能实现
{
motorA = 1;
motorB = 1;
delay(20);
} //AB通电1ms
motorA = 0;
motorB = 0; //AB关电
for(i = 1;i < 10; ++i)
{
motorB = 1;
motorC = 1;
delay(20);
}//BC通电1ms
motorB = 0;
motorC = 0; //BC关电
for(i = 1;i < 10; ++i)
{
motorC = 1;
motorD = 1;
delay(20);//CD通电1ms
}
motorC = 0;
motorD = 0;//CD关电
for(i = 1;i < 10; ++i)
{
motorD = 1;
motorA = 1;
delay(20);//DA通电1ms
}
motorD = 0;
motorA = 0;//DA关电
} }
motorA = 1;
motorB = 1;
motorC = 1;
motorD = 1;
init();
write_com(0x80);
for(i=0;i<12;i++)
write_data(door[i]);
LED_GREEN=0;
Delay1ms(2000);
LED_GREEN=1;
cuowu_flag=0;
km_flag=1;
tishixinxi();
timer_init();
TR0=1;
while(1){
if(_flag_==1){
TR0=0;
_flag_=0;
break;
}
else if(JJKG==0) {
TR0=0;
break;
}
}
/*for(i=0;i<200;i++)
{
Delay1ms(10);
} */
if(JJKG==0) fanzhuan();
if(JJKG!=0) guanmenbaojin();
mimadisplay();
}
电路图:
主程序框图:
视频效果展示:
IMG_3054
IMG_3052