🎀 文章作者:二土电子
🐸 期待大家一起学习交流!
一、任务要求
设计一款密码锁,通过串口输入输出信息。需要实现以下功能
- 开机提示“欢迎使用智能密码锁系统”,换行回车后显示“请输入密码”
- 输入六位任意字符密码,不能是汉字。如果密码正确,返回“密码正确,已开门”。如果密码错误,返回“密码错误,您还有*次输入机会”
- 如果连续三次输入密码错误,提示“三次密码错误,警报!”。此时,LED闪烁报警
- 如果输入“Enter(空格)Admin(空格)Mode”,返回“已进入管理员模式”,换行之后显示“请输入管理员密码”。输入密码正确后,提示“管理员密码正确”,进入管理员模式。管理员密码默认为“147258”。如果管理员密码输入错误,提示“管理员密码错误”
- 进入管理员模式后,提示“请输入新密码”。输入完成一次后提示“请再次输入新密码”。连续两次输入正确后,提示“密码修改成功”,自动退出管理员模式。如果两次密码不一致,会提示“连续两次输入密码不同,请重新输入”。如果新密码与原密码相同,会提示“新密码请勿与原密码相同”
- 如果输入内容错误,会提示“Error!”,回车加换行
二、实现方法
2.1 输入密码判断
首先有一个默认密码“123456”。将密码存储到一个数组中。接收到输入密码后,利用for循环,挨个比较串口接收数组中接收输入的密码是否与密码数组中密码相同。相同的话,提示“密码正确,已开门”。如果错误,累计错误次数,提示“密码错误,您还有*次输入机会”。如果三次输入任意一次正确,会将之前累计的错误次数清零。如果三次输入均错误,提示“三次密码错误,警报!”。此时,LED闪烁报警。2.2 管理员模式
如果串口接收中断中接收到内容后,利用for循环,挨个对比指令是否为进入管理员模式指令。如果是进入管理员模式指令,返回“已进入管理员模式”,换行回车后显示“请输入管理员密码”。密码的判断方法与最开始的输入密码相同。2.3 修改密码
进入管理员模式且正确输入密码后,可以修改密码。修改密码时,第一次输入后会首先拿新密码与原密码比较。如果新密码与原密码相同,返回“新密码请勿与原密码相同”。如果第二次输入密码后,判断与第一次的密码手抖相同。如果两次输入的密码相同,提示“密码修改成功”。然后自动退出管理员模式。三、程序设计
3.1 输入密码判断
如果接收到的内容长度为六位,而且此时不是管理员模式。会对输入的密码进行判别。正确返回正确信息,错误提示错误信息。连续三系错误,提示报警。同时,LED闪烁。三次中任意一次输入正确,清零错误累计次数。程序设计如下
// 输入密码判断
void PassWord_Judge (void)
{
u8 tempVar = 0; // 临时循环变量
u8 judgeRes = 0; // 判别结果
// 非管理员模式下输入密码
if (gAdminFlag == 0 && gPassWordFlag == 1 && gPassWordChargeFlag == 0)
{
// for循环判断密码是否正确
for (tempVar = 0;tempVar < 6;tempVar ++)
{
// 任意一位密码错误,就说明密码错误
if (gReceFifo[tempVar] != gPassWord[tempVar])
{
judgeRes = 1;
}
}
// 提示密码正确
if (!judgeRes)
{
printf ("密码正确,已开门\r\n");
gPassWordErrorCunt = 0; // 清零密码错误计数变量
}
// 密码错误
else
{
gPassWordErrorCunt = gPassWordErrorCunt + 1; // 密码错误计数变量加1
// 连续三次密码错误,报警
if (gPassWordErrorCunt >= 3)
{
printf ("三次密码错误,警报!\r\n");
gPassWordErrorCunt = 0; // 清零密码错误计数变量
// LED闪烁报警
tempVar = 5;
while (tempVar > 0)
{
Med_Led_StateReverse(LED1); // LED闪烁
delay_ms(200);
tempVar --;
}
}
else
{
printf ("密码错误,您还有%d次输入机会\r\n",3 - gPassWordErrorCunt);
}
judgeRes = 0; // 清零判别结果
}
gPassWordFlag = 0; // 清零输入密码标志位
Clear_Rece(); // 清空接收数组
}
// 管理员模式下输入密码
if (gAdminFlag == 1 && gPassWordFlag == 1 && gPassWordChargeFlag == 0)
{
// for循环判断密码是否正确
for (tempVar = 0;tempVar < 6;tempVar ++)
{
// 任意一位密码错误,就说明密码错误
if (gReceFifo[tempVar] != gAdminPassWord[tempVar])
{
judgeRes = 1;
}
}
// 提示密码正确
if (!judgeRes)
{
printf ("管理员密码正确\r\n");
printf ("请输入新密码\r\n");
gPassWordChargeFlag = 1; // 修改密码标志位置1
}
else
{
printf ("管理员密码错误\r\n");
judgeRes = 0; // 清零判别结果
}
gPassWordFlag = 0; // 清零输入密码标志位
gAdminFlag = 0; // 清零进入管理员模式标志位
Clear_Rece(); // 清空接收数组
}
}
密码判断有两种,一种是非管理员模式的密码判断,一种是管理员模式密码判断。编程时利用标志位进行了区分。
3.2 进入管理员模式
利用for循环,当接收内容长度为18(进入管理员模式指令加回车换行,共18个)时,判断指令是否与进入管理员指令相同。以此来判断是否需要进入管理员模式。程序设计如下
/*
*==============================================================================
*函数名称:Uart_Rece_Pares
*函数功能:解析串口接收内容
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
extern u8 gAdminFlag; // 进入管理员模式标志位
extern u8 gPassWordFlag; // 输入为密码的标志位
void Clear_Rece (void); // 清空串口接收数组
u8 gAdminMode[16] = "Enter Admin Mode";
void Uart_Rece_Pares(void) // 串口接收内容解析函数
{
u8 tempVar = 0; // 临时循环变量
// 接收内容长度为6
if (gReceCount == 8)
{
gPassWordFlag = 1; // 接收内容为密码
}
// 接收到进入管理员模式指令
else if (gReceCount == 18)
{
for (tempVar = 0;tempVar < 16;tempVar ++)
{
// 错误指令
if (gReceFifo[tempVar] != gAdminMode[tempVar])
{
printf ("Error!\r\n");
}
}
printf ("已进入管理员模式\r\n");
printf ("请输入管理员密码\r\n");
// 进入管理员模式标志位置1
gAdminFlag = 1;
Clear_Rece(); // 清空接收内容
}
// 错误指令
else
{
printf ("Error!\r\n");
Clear_Rece(); // 清空接收内容
}
}
这里把判断是否为输入密码的程序也加进来了,比较简单,就不再单独介绍了。
3.3 修改密码
修改密码只需要定义一个数组用来接收新密码。第一次接收到新密码后,与原密码对比。如果与原密码相同,返回对应信息。如果不同,提示“请再次输入新密码”。然后再拿接收数组中的新输入密码与第一次输入的密码对比,相同提示“密码修改成功”。程序设计如下
// 修改密码
void PassWord_Charge (void)
{
u8 tempVar = 0; // 临时循环变量
u8 judgeRes = 0; // 判别结果
// 第一次输入新密码
if (gPassWordChargeFlag == 1 && gPassWordFlag == 1)
{
// for循环判断新密码是否与原密码相同
for (tempVar = 0;tempVar < 6;tempVar ++)
{
if (gReceFifo[tempVar] != gPassWord[tempVar])
{
judgeRes = 1;
}
}
// 新密码与原密码相同
if (!judgeRes)
{
printf ("新密码请勿与原密码相同\r\n");
judgeRes = 0; // 清零判别结果
}
else
{
// for循环用新密码覆盖原密码
for (tempVar = 0;tempVar < 6;tempVar ++)
{
gPassWord[tempVar] = gReceFifo[tempVar];
}
gPassWordChargeFlag = 2; // 标志位变为2,提示下一次准备再次确认新密码
printf ("请再次输入新密码\r\n");
}
gPassWordFlag = 0; // 清零输入密码标志位
Clear_Rece(); // 清空接收数组
}
// 第二次输入新密码
if (gPassWordChargeFlag == 2 && gPassWordFlag == 1)
{
// for循环判断新密码是否与上次输入的新密码相同
for (tempVar = 0;tempVar < 6;tempVar ++)
{
if (gReceFifo[tempVar] != gPassWord[tempVar])
{
judgeRes = 1;
}
}
// 连续两次输入新密码相同
if (!judgeRes)
{
printf ("密码修改成功\r\n");
gPassWordChargeFlag = 0; // 清零修改密码标志位
}
else
{
printf ("连续两次输入密码不同,请重新输入\r\n");
}
gPassWordFlag = 0; // 清零输入密码标志位
Clear_Rece(); // 清空接收数组
}
}
四、问题总结
4.1 输入内容一直提示Error
这个原因是清除接收数组的位置不对。在while(1)轮询中有一个清除接收数组,导致还未进行判断,接收内容就已经被清除。清除接收数组内容,一定要放在每一个if判断里面,而不能放在外面。
4.2 密码判断一直错误
原因是程序中存储密码的数组定义错误。最开始的定义方法如下
u8 gPassWord[6] = {
1,2,3,4,5,6}; // 密码,初始为123456
u8 gAdminPassWord[6] = {
1,4,7,2,5,8}; // 管理员密码,147258
这么定义,数组中的每一位数就是数字,而不是字符。如果想定义成字符,应该像下面这样定义
u8 gPassWord[6] = {
'1','2','3','4','5','6'}; // 密码,初始为123456
u8 gAdminPassWord[6] = {
'1','4','7','2','5','8'}; // 管理员密码,147258