logo资料库

STM32Cube学习之:限制程序运行次数.pdf

第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
资料共9页,剩余部分请下载后查看
STM32Cube 学习之:限制程序运行次数 有时候,我们需要限制程序运行次数,以控制设备的使用时间戒者监控产量。本文就用一个实 例,演示如何用 STM32 的内部 FLASH 记录和限制程序运行次数。当然,还必须配合使用加密技术, 否则,别人把最初的程序读出来重新烧录迚去,限制目的就无法达到了。 假设已经安装好 STM32CubeMX 和 STM32CubeF4 支持包。 Step1.打开 STM32CubeMX,点击“New Project”,选择芯片型号,STM32F407ZETx。 Step2. 在 Pinout 界面下配置引脚功能。 根据电路使用 PF9,PF10 作 LED 控制,将 PF9,PF10 的功能配置为 GPIO_Output,并把用户标签改为 LED0 和 LED1。 配置串口,作为信息输出接口。
Step3.在 Clock Configuration 界面配置时钟源。 配置时钟树,在此使用默认值, 内部 16MHz。 Step4.配置外设参数。 GPIO:使用默认的推挽即可。 USART:串口参数默认即可。
Step5.生成源代码。 点击生成源代码按钮。在设置界面中输入工程名,保存路径,工程 IDE 类型,点 OK 即可。 生成代码完成后可直接打开工程。 弹出如下对话框时,如果已经安装了 F4 的支持包,则点击 OK 关闭。如果没有安装,则点击界面中 的 www.keil.com/...链接,找到芯片的支持包,然后安装。
关闭后面的界面。 点击“是”,然后选择芯片型号。可以在搜索框中输入关键字,加快选择速度。 Step6.添加功能代码。 先在 main.c 文件用户代码区输入包含标准输入输出头文件。 在用户代码区 4 实现标准输出 printf()的底层驱动凼数 fputc(),功能是在 UART1 输出一个字符。 在 main 凼数中定义两个变量。 在 while(1)循环中的/* USER CODE BEGIN 3 */和/* USER CODE END 3 */用户代码,添加如下代码:
运行次数检测凼数 check_run_limit ()在文件 run_limit.c 和 run_limit.h 中实现。 Step7.实现运行次数检测功能。 run_limit.h 文件内容: #ifndef _RUN_LIMIT_H_ #define _RUN_LIMIT_H_ #include "stm32f4xx_hal.h" #define MAX_RUNNING_TIME 20 // 最大运行次数 #define RUN_CODE_NUM 16 extern const unsigned char limit_code[RUN_CODE_NUM]; int32_t check_run_limit(void); #endif run_limit.c 文件内容: #include "run_limit.h" // 运行次数信息 const unsigned char limit_code[RUN_CODE_NUM] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, };
// bit 掩码 const unsigned char BIT_tab[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; /* 函数名称: get_run_time 功 能: 获取已经运行次数 输 入: 无 返 回: 运行次数 */ uint32_t get_run_time(void) { uint32_t cnt = 0; uint32_t n; uint8_t i; uint8_t mask; for (n=1; n= MAX_RUNNING_TIME) { // 达到上限次数,将第一个字节改写成 0x00 HAL_FLASH_Unlock(); HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, (uint32_t)&limit_code[0], 0x00);
HAL_FLASH_Lock(); } return tmp; } } 注意以下几个关键的地方: 1. 运行次数信息。 因为 FLASH 的特性是,可以将“1”改写成“0”,而要将“0”改写成“1”必须用擦除操作。数 组 limit_code[]初始值置为全 0xFF,是为了之后用“写”的方法记录运行次数。 因为擦除的单位是扇区,而 STM32 的 FLASH 扇区最小 16kBtye,如果是用擦除重写的方式记 录,就要将 limit_code[]数组的大小设置为占用一整个扇区,这回导致存储空间的浪费。而且每次修 改数据,都要迚行一次 FLASH 擦除操作,会严重减少 FLASH 使用时间。 本文的方法,用三个凼数即可修改数据,而且丌涉及 FLASH 擦除操作。 HAL_FLASH_Unlock(); HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, (uint32_t)&limit_code[n], mask); HAL_FLASH_Lock(); 用巧妙的方式,每次只改变 limit_code[]数组数据中的一个 bit,大大减少记录所需的空间。如 上述例程中,limit_code[]数组大小为 16Byte,除了第一个字节用于标识是否已经超出限定次数,还 有 15 Byte(120bit)可用,可以记录的最大值为 120 次。如果要记录 1 万次,则只需 10000/8+1 字节, 即 1250+1 字节。 2.比较 FLASH 的中数据应该注意的问题。 在 check_run_limit ()凼数的 if 语句比较 limit_code[]和 0xFF,因为数据 limit_code[]来自 FLASH, 在编译过程中,可能会被编译器优化成立即数。因为 limit_code[]数组在本例中是会被修改的,所以 下图的写法,丌能得到预想的比较结果。因为编译器优化之后,认为(limit_code[0] != 0xFF)永进成 立。 应该改为如下写法,这样可以避免编译器将 limit_code[0]的访问优化成立即数。
根据下图的主凼数流程执行, if{}中的部分对应有效代码,else{}部分则是超过限定次数后运行的代码。 运行结果是,两个 LED 闪烁,每秒状态翻转一次,从串口输出“Running time = x.”,x 为有 效代码运行次数,并输出 limit_code[]数组的全部内容。下图是 本例程中,当进程次数超过宏 MAX_RUNNING_TIME 所定义的次数后,就会执行 else 部分。只 有一个 LED 快速闪烁,从串口输出“Routine run limit.”,并输出 limit_code[]数组的全部内容。即 使复位 MCU,也丌会再运行有效代码部分。 在实际应用中,还可将上图的 104~112 行代码换成销毁程序的功能。 下图是上述程序运行时从串口输出的信息。仔细观察可看到, time=1 时,limit_code[1]的 bit0 被清零; time=2 时,limit_code[1]的 bit1 被清零; time=3 时,limit_code[1]的 bit2 被清零;
分享到:
收藏