STM32实战项目—密码锁

简介: 本文完整详细地介绍了一个密码锁项目的要求,设计思路,程序实现,问题总结和成果展示内容。


🎀 文章作者:二土电子
🐸 期待大家一起学习交流!


一、任务要求

设计一款密码锁,通过串口输入输出信息。需要实现以下功能

  • 开机提示“欢迎使用智能密码锁系统”,换行回车后显示“请输入密码”
  • 输入六位任意字符密码,不能是汉字。如果密码正确,返回“密码正确,已开门”。如果密码错误,返回“密码错误,您还有*次输入机会”
  • 如果连续三次输入密码错误,提示“三次密码错误,警报!”。此时,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

五、成果展示

5.1 输入密码判断

729788371e7a74d65b4895aa2fe78c30_af24ce9bde3b4f828b6c01d01c254a4c.png

c4ce1a7f1c6464ffa30ce124d5dea784_a3e65738ab29415fa782676e9baf16aa.png

5.2 进入管理员模式

230ee06a528c7230be93515a1d400b54_c3a70fbfec88452e8b2bc86afe7fa0c9.png

5.3 修改密码

342ca86daee52f68ab2a90115e62e7a5_fb372114644349e0b736b1c186fbdb7a.png

相关文章
|
4月前
STM32CubeMX FreeRTOS 互斥锁
STM32CubeMX FreeRTOS 互斥锁
162 12
|
6月前
|
传感器
基于STM32与FreeRTOS的四轴机械臂项目-3
基于STM32与FreeRTOS的四轴机械臂项目
基于STM32与FreeRTOS的四轴机械臂项目-3
|
6月前
|
传感器
基于STM32与FreeRTOS的四轴机械臂项目-2
基于STM32与FreeRTOS的四轴机械臂项目
基于STM32与FreeRTOS的四轴机械臂项目-2
|
5月前
|
传感器 数据采集 人工智能
【STM32+k210项目】基于AI技术智能语音台灯的设计(完整工程资料源码)
【STM32+k210项目】基于AI技术智能语音台灯的设计(完整工程资料源码)
233 1
|
4月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
156 0
|
4月前
|
数据安全/隐私保护
STM32F103C8T6实现简易密码锁(CubeMax配置)(一),Oled显示。
项目功能:实现设置密码,登陆密码,后期还可以通过E2PROM实现掉电不丢失数据。通过Oled的显示去判断我们是否设置或者登陆成功。
|
6月前
|
传感器 存储
基于STM32与FreeRTOS的四轴机械臂项目-1
基于STM32与FreeRTOS的四轴机械臂项目
基于STM32与FreeRTOS的四轴机械臂项目-1
|
5月前
|
存储 算法 测试技术
【STM32项目】基于Stm32c8t6-镭射激光打印机的设计(完整工程资料源码)(二)
【STM32项目】基于Stm32c8t6-镭射激光打印机的设计(完整工程资料源码)(二)
172 0
|
5月前
|
存储 搜索推荐 安全
【STM32项目】基于Stm32c8t6-镭射激光打印机的设计(完整工程资料源码)(一)
【STM32项目】基于Stm32c8t6-镭射激光打印机的设计(完整工程资料源码)(一)
118 0
|
运维 小程序 API
STM32实战项目—WIFI远程开关灯
本文介绍了如何利用正点原子ESP8266和STM32F103C8T6连接腾讯云,利用舵机实现远程开关灯。给出了详细的腾讯云配置和调试步骤,给出了部分程序设计。
306 0
STM32实战项目—WIFI远程开关灯