蓝桥杯单片机设计与开发(智障门锁)
内附完整工程 代码仅供参考,如有建议疑问欢迎留言讨论
程序设计部分
智能门锁—任务指导书
开发环境
Keil5
Stc-isp
国兴天长开发板
任务分析
任务逻辑梳理
不多赘述具体逻辑,我直接将我的流程图分享,各位可根据任务指导书梳理
界面设计
根据任务指导书可知,界面(数码管)共有四种:
默认状态
全部熄灭
输入状态
打开状态
修改状态
LED状态:
LED 1 ON
密码错误,点亮5s
LED 7 ON
输入状态,其他状态熄灭
LED 8 ON
修改状态,其他状态熄灭
LED OFF
键盘定义
矩阵键盘4*4 没啥好分析的看图就行
e2prom分析
初次上电检测
根据任务需求,需要设值一个掉电还能保存的标志,用于检测是否为第一次上电
思路:在e2prom中选择一个字节用于存储一个标志,设备启动时读取这个字节,判断该字节是否等于程序中的标志位。如果不是则为初次上电;如果相等则不是初次上电
密码存取
因为按照需求,密码为6位,所以可以连续选取六个连续字节存储谬码;
请参考英文使用手册:
参看CSDN文章:有关iic和at24读写详解(里面详细说了连续读写)
代码实现
首先根据日内瓦公约(毫无瓜西)
数码管的使用:
使用定时器刷新数码管
可以用stcisp一键生成定时器(定时器刷新时间建议500us,低了会影响刷新效果,高了会闪(自己把握))
/*
0-9
10-0xff
11-0xf7 _
12-14 0x8c P
0x86 E
0xc8 n
15 0xc6 C
*/
uchar code seg_table[]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,
0xff,0xf7,0x8c,0x86,0xc8,0xc6};
uchar show_tab[]={10,10,10,10,10,10,10,10}; //显示缓冲区
void seg_show(uchar n) //显示数字(n代表数码管的位)
{
P0=0x00;
Y6;
P0=(0x01<<n);
Y0;
P0=0xff;
Y7;
P0=seg_table[show_tab[n]];
Y0;
}
void Timer0Init(void) //500微秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x66; //设置定时初始值
TH0 = 0xEA; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
void Timer0() interrupt 1
{
static int n=0;
seg_show(n); //循环显示
n++;
if(n==8)
n=0;
}
键盘扫描
键值计算可以参考原理图,列三个3元1次方程组就能解决(解决不了的去小学吧)
/*********4*4键盘扫描***********
对应键值关系
1 2 3 4 S7 S11 S15 S19
5 6 7 8 S6 S10 S14 S18
9 10 11 12 S5 S9 S13 S17
13 14 15 16 S4 S8 S12 S16
***************************/
unsigned char key_scanf()
{
uchar x=0,y=0;
P30=0;P31=0;P32=0;P33=0;
P34=1;P35=1;P42=1;P44=1;
if(!(P34&P35&P42&P44))
{
Delay20us(); //消抖
if(!(P34&P35&P42&P44))
{
if(!P34)
x=4;
if(!P35)
x=3;
if(!P42)
x=2;
if(!P44)
x=1;
P30=1;P31=1;P32=1;P33=1;
P34=0;P35=0;P42=0;P44=0;
if(!P30)
y=1;
if(!P31)
y=2;
if(!P32)
y=3;
if(!P33)
y=4;
while(!(P30&P31&P32&P33));
return (x+4*y-4); //计算键值
}
}
return 0;
}
eeprom函数
#define FIRST_FLAG 0x14 //检测标志
void check_first()
{
uchar temp=0;
LED_OFF(); //关闭led
temp=e2prom_read(0xf5); //读取标志位内容
if(temp==FIRST_FLAG) //如果内容一致,则不是第一次上电
{
read_pas(); //读取存储的密码
//测试部分
// set_tab(10,10,cor_pas[0],cor_pas[1],cor_pas[2],cor_pas[3],cor_pas[4],cor_pas[5]);
// while(1);
return;
}
//首次上电
write_pas(cor_pas); //将密码存入
Delay5ms(); //等待存储
e2prom_write(0xf5,FIRST_FLAG); //写入标志位
}
//读取一个字节
uchar e2prom_read(uchar addr)
{
uchar dat;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(0);
IIC_Stop();
return dat;
}
//写入一个字节
void e2prom_write(uchar addr,dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
//连续写入数组
void write_pas(uchar* tab)
{
unsigned char i=0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(0x10);
IIC_WaitAck();
for(;i<6;i++)
{
IIC_SendByte(tab[i]);
IIC_WaitAck();
}
IIC_Stop();
}
//连续读出数组
void read_pas()
{
unsigned char i=0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(0x10);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
cor_pas[0]=IIC_RecByte();
for(;i<5;i++)
{
IIC_SendAck(0);
cor_pas[i+1]=IIC_RecByte();
}
IIC_Stop();
}
主函数部分
不贴了,最后给出所有文件
所有资料
压缩包目录
demo_smartlock(项目工程)
AT24C02英文资料
AT24C02中文资料
hex文件
REDME
任务指导书
逻辑图
————————————————
版权声明:本文为CSDN博主「不知足额」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45698227/article/details/121807134