文章目录
- 一、功能简介
- 二、软件设计
- 三、实验现象
- 联系作者
一、功能简介
本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED模块、DS18B20温度传感器、SG90舵机、红外遥控、矩阵按键、EEPROM等。
主要功能:
系统运行后,OLED显示RTC日期时间和温度;
键盘解锁:可使用矩阵键盘S1-S10键输入数字
0-9,初始密码为012345,当密码输入有误可按下S11键撤回,输入完成后可按下S12键解锁,若密码正确则开锁,舵机启动。若密码错误,OLED显示错误信息,当错误次数超过3次则锁死一段时间后重新输入。当按下S13键可修改密码,进入密码修改界面首先需校验旧密码,当输入旧密码正确,才可进入新密码设置。可按下S16键返回主界面。密码支持掉电不丢失。
红外遥控解锁:使用红外遥控器,按下第一个键(该键对应HEX为A2),则一键解锁。
二、软件设计
/*
作者:嗨小易(QQ:3443792007)
*/
//系统参数初始化
void sys_parm_init(void)
{
u8 i=0;
sys_ctrl.mode=0;
sys_ctrl.err_cnt=0;
sys_ctrl.psw_flag=0;
sys_ctrl.psw_resive=0;
sys_ctrl.psw_bit=0;
//初始密码0-5
if(AT24CXX_ReadOneByte(255)!=0x28)
{
AT24CXX_WriteOneByte(255,0x28);
//写入初始密码到EEPROM
for(i=0;i<PSW_BITNUM;i++)
{
sys_ctrl.save_psw[i]=i;
AT24CXX_WriteOneByte(i,sys_ctrl.save_psw[i]);
}
}
else
{
//读取EEPROM内密码数据
for(i=0;i<PSW_BITNUM;i++)
{
sys_ctrl.save_psw[i]=AT24CXX_ReadOneByte(i);
}
}
}
//系统时钟温度显示模块
void sys_rtc_temp_show(void)
{
u8 buf[5];
static u8 i=0;
OLED_Clear();
OLED_ShowString(0,0, "2023-08-22 Week5",16);
OLED_ShowString(0,20, " 12:16:56",16);
OLED_ShowString(0,40," Temp: C",16);
while(sys_ctrl.mode==0)
{
//温度获取
i++;
if(i%1==0)
sys_ctrl.temp=DS18B20_GetTemperture()*10;
//日期显示
buf[0]=calendar.w_year/1000+0x30;
buf[1]=calendar.w_year%1000/100+0x30;
buf[2]=calendar.w_year%1000%100/10+0x30;
buf[3]=calendar.w_year%1000%100%10+0x30;
buf[4]='\0';
OLED_ShowString(0,0,buf,16);
buf[0]=calendar.w_month/10+0x30;
buf[1]=calendar.w_month%10+0x30;
buf[2]='\0';
OLED_ShowString(5*8,0,buf,16);
buf[0]=calendar.w_date/10+0x30;
buf[1]=calendar.w_date%10+0x30;
buf[2]='\0';
OLED_ShowString(8*8,0,buf,16);
buf[0]=calendar.week%7+0x30;
buf[1]='\0';
OLED_ShowString(15*8,0,buf,16);
//时间显示
buf[0]=calendar.hour/10+0x30;
buf[1]=calendar.hour%10+0x30;
buf[2]='\0';
OLED_ShowString(3*8,20,buf,16);//时
buf[0]=calendar.min/10+0x30;
buf[1]=calendar.min%10+0x30;
buf[2]='\0';
OLED_ShowString(6*8,20,buf,16);//分
buf[0]=calendar.sec/10+0x30;
buf[1]=calendar.sec%10+0x30;
buf[2]='\0';
OLED_ShowString(9*8,20,buf,16);//秒
//温度显示
buf[0]=sys_ctrl.temp/100+0x30;
buf[1]=sys_ctrl.temp%100/10+0x30;
buf[2]='.';
buf[3]=sys_ctrl.temp%100%10+0x30;
buf[4]='\0';
OLED_ShowString(7*8,40,buf,16);
//检测是否按下键,进入密码输入界面
if(KEY_Matrix_Scan()!=0)
{
sys_ctrl.mode=1;
break;
}
OLED_Refresh_Gram();//刷新显存
}
}
//密码输入界面显示
void psw_input_show(void)
{
OLED_Clear();
OLED_ShowString(0,0,"Password:",16);
}
//修改密码时输入校验密码界面显示
void adjust_input_show(void)
{
OLED_Clear();
OLED_ShowString(0,0,"Calib Psw:",16);
}
//设置新密码界面显示
void set_new_psw_show(void)
{
OLED_Clear();
OLED_ShowString(0,0,"New Psw:",16);
}
//一键解锁界面显示
void one_click_unlock_show(void)
{
OLED_Clear();
OLED_ShowString(0,0,"One click unlock",16);
OLED_ShowString(0,20,"OK...",16);
}
//修改密码时,密码校验
void sys_psw_resive(void)
{
u8 key=0;
//在密码设置有效
if(sys_ctrl.psw_resive)
{
//初始化参数值
sys_ctrl.psw_bit=0;
sys_ctrl.err_cnt=0;
sys_ctrl.psw_flag=0;
memset(sys_ctrl.psw,0,PSW_BITNUM);//清除输入数据
adjust_input_show();//修改密码时输入校验密码界面显示
while(sys_ctrl.psw_resive)
{
//键盘扫描
key=KEY_Matrix_Scan();
if(key>0)//按键输入
{
BEEP_Alarm(100,100);//提示音
if(key<=10)//数字键0-9
{
if(sys_ctrl.psw_bit<PSW_BITNUM)//最多输入密码位数
{
sys_ctrl.psw[sys_ctrl.psw_bit]=key-1;//记录输入密码
sys_ctrl.psw_bit++;//输入位数累加
//密码可见
if(PASSWORD_SHOW_HIDE)
//显示输入密码
OLED_ShowNum((9+sys_ctrl.psw_bit)*8,0,sys_ctrl.psw[sys_ctrl.psw_bit-1],1,16);
//密码不可见
else
OLED_ShowString((9+sys_ctrl.psw_bit)*8,0,"*",16);
}
}
else if(key==11)//撤回键
{
sys_ctrl.psw[sys_ctrl.psw_bit-1]=10;//将所需撤回的数据设置为无效数
OLED_ShowString((9+sys_ctrl.psw_bit)*8,0," ",16);//将撤销位置显示空位
sys_ctrl.psw_bit--;
if(sys_ctrl.psw_bit<0)sys_ctrl.psw_bit=0;
}
else if(key==12)//确定键
{
sys_ctrl.psw_flag=0;
sys_ctrl.psw_bit=0;
//输入密码与存储密码比较
if(memcmp(sys_ctrl.psw,sys_ctrl.save_psw,PSW_BITNUM)==0)
sys_ctrl.psw_flag=1;//密码正确
memset(sys_ctrl.psw,0,PSW_BITNUM);//清除输入数据
//密码正确,开锁
if(sys_ctrl.psw_flag==1)
{
sys_ctrl.err_cnt=0;
OLED_ShowString(0,20,"Password OK! ",16);
OLED_Refresh_Gram();//刷新显存
delay_ms(1000);
break;//进入新密码设置程序
}
//如果密码错误
else
{
sys_ctrl.err_cnt++;//错误次数累计
OLED_ShowString(0,20,"Password Error!",16);
OLED_Refresh_Gram();//刷新显存
//密码输入错误次数超限
if(sys_ctrl.err_cnt>=ERROR_PASSWORD_CNT)
{
sys_ctrl.err_cnt=0;
OLED_ShowString(0,0,"Too many errors!",16);
OLED_ShowString(0,20,"Please wait...",16);
OLED_Refresh_Gram();//刷新显存
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
}
else delay_ms(1000);
adjust_input_show();//修改密码时输入校验密码界面显示
}
}
else if(key==16)//退出键
{
sys_ctrl.psw_resive=0;
sys_ctrl.mode=0;//回到时钟温度显示模式
break;
}
}
OLED_Refresh_Gram();//刷新显存
}
}
}
//应用控制系统
void app_sys_ctrl_demo(void)
{
u8 i=10;
LED_Init();
USART1_Init(115200);
AT24CXX_Init();
OLED_Init();
KEY_Matrix_Init();
BEEP_Init();
DS18B20_Init();
RTC_Init();
Hwjs_Init();
//获取稳定数据
while(i--)
{
sys_ctrl.temp=DS18B20_GetTemperture()*10;
delay_ms(100);
}
TIM4_Init(200,36000-1); //定时100ms
TIM3_CH2_PWM_Init(20000-1,71); //周期20ms
steer_control(0);
sys_parm_init();//系统参数初始化
while(1)
{
sys_rtc_temp_show();//系统时钟温度显示模块
sys_psw_unlock_show();//系统解锁显示模块
sys_psw_resive();//修改密码时,密码校验
sys_new_psw_set();//新密码设置
}
}
三、实验现象
B站演示视频:https://space.bilibili.com/444388619
联系作者
专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。