硬汉嵌入式论坛

 找回密码
 立即注册
查看: 822|回复: 10
收起左侧

[技术讨论] 按键扫描驱动文件 bsp_key 的一处BUG

[复制链接]

82

主题

401

回帖

667

积分

金牌会员

积分
667
QQ
发表于 2022-6-21 19:34:48 | 显示全部楼层 |阅读模式
今天调试一个手持式产品,要检测电源键长按开机,一直移植的是bsp_key 文件,今天碰到了第一次按开机键不启动,要按第二次才能启动,最后排查发现驱动文件有问题

头文件 中结构体变量的定义是这样的
/*
        每个按键对应1个全局的结构体变量。
*/
typedef struct
{
        /* 下面是一个函数指针,指向判断按键手否按下的函数 */
        uint8_t (*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */

        uint8_t  Count;                        /* 滤波器计数器 */
        uint16_t LongCount;                /* 长按计数器 */
        uint16_t LongTime;                /* 按键按下持续时间, 0表示不检测长按 */
        uint8_t  State;                        /* 按键当前状态(按下还是弹起) */
        uint8_t  RepeatSpeed;        /* 连续按键周期 */
        uint8_t  RepeatCount;        /* 连续按键计数器 */
}KEY_T;


但是在初始化的时候 却没有将  LongCount 清零


/*
*********************************************************************************************************
*        函 数 名: bsp_InitKeyVar
*        功能说明: 初始化按键变量
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
static void bsp_InitKeyVar(void)
{
        uint8_t i;

        /* 对按键FIFO读写指针清零 */
        s_tKey.Read = 0;
        s_tKey.Write = 0;
        s_tKey.Read2 = 0;

        /* 给每个按键结构体成员变量赋一组缺省值 */
        for (i = 0; i < KEY_COUNT; i++)
        {
                s_tBtn.LongTime = KEY_LONG_TIME;                        /* 长按时间 0 表示不检测长按键事件 */
                s_tBtn.Count = KEY_FILTER_TIME / 2;                /* 计数器设置为滤波时间的一半 */
                s_tBtn.State = 0;                                                        /* 按键缺省状态,0为未按下 */
                //s_tBtn.KeyCodeDown = 3 * i + 1;                                /* 按键按下的键值代码 */
                //s_tBtn.KeyCodeUp   = 3 * i + 2;                                /* 按键弹起的键值代码 */
                //s_tBtn.KeyCodeLong = 3 * i + 3;                                /* 按键被持续按下的键值代码 */
                s_tBtn.RepeatSpeed = 0;                                                /* 按键连发的速度,0表示不支持连发 */
                s_tBtn.RepeatCount = 0;                                                /* 连发计数器 */
        }

        /* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
        /* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */
        s_tBtn[KID_JOY_U].LongTime = 100;
        s_tBtn[KID_JOY_U].RepeatSpeed = 5;        /* 每隔50ms自动发送键值 */

        s_tBtn[KID_JOY_D].LongTime = 100;
        s_tBtn[KID_JOY_D].RepeatSpeed = 5;        /* 每隔50ms自动发送键值 */

        s_tBtn[KID_JOY_L].LongTime = 100;
        s_tBtn[KID_JOY_L].RepeatSpeed = 5;        /* 每隔50ms自动发送键值 */

        s_tBtn[KID_JOY_R].LongTime = 100;
        s_tBtn[KID_JOY_R].RepeatSpeed = 5;        /* 每隔50ms自动发送键值 */

        /* 判断按键按下的函数 */
        s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
        s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
        s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
        s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
        s_tBtn[4].IsKeyDownFunc = IsKeyDown5;
        s_tBtn[5].IsKeyDownFunc = IsKeyDown6;
        s_tBtn[6].IsKeyDownFunc = IsKeyDown7;
        s_tBtn[7].IsKeyDownFunc = IsKeyDown8;

        /* 组合键 */
        s_tBtn[8].IsKeyDownFunc = IsKeyDown9;
        s_tBtn[9].IsKeyDownFunc = IsKeyDown10;
}




红色循环部分没有将   LongCount 清零,希望大家在移植过程中要小心 ,在循环中清零


        /* 给每个按键结构体成员变量赋一组缺省值 */
        for (i = 0; i < KEY_COUNT; i++)
        {
                s_tBtn.LongTime = KEY_LONG_TIME;                        /* 长按时间 0 表示不检测长按键事件 */
                s_tBtn.LongCount= 0;                 /*长按计数器清零*/
                s_tBtn.Count = KEY_FILTER_TIME / 2;                /* 计数器设置为滤波时间的一半 */
                s_tBtn.State = 0;                                                        /* 按键缺省状态,0为未按下 */
                //s_tBtn.KeyCodeDown = 3 * i + 1;                                /* 按键按下的键值代码 */
                //s_tBtn.KeyCodeUp   = 3 * i + 2;                                /* 按键弹起的键值代码 */
                //s_tBtn.KeyCodeLong = 3 * i + 3;                                /* 按键被持续按下的键值代码 */
                s_tBtn.RepeatSpeed = 0;                                                /* 按键连发的速度,0表示不支持连发 */
                s_tBtn.RepeatCount = 0;                                                /* 连发计数器 */
        }




武汉天纵鹏元科技有限公司。承接嵌入式项目开发,相关技术交流。STM32,物联网,工业控制方向。QQ  408137104
回复

使用道具 举报

29

主题

231

回帖

318

积分

高级会员

积分
318
发表于 2022-6-22 07:49:48 | 显示全部楼层
厉害了
回复

使用道具 举报

28

主题

178

回帖

262

积分

高级会员

积分
262
发表于 2022-6-22 09:47:49 | 显示全部楼层
够细节
回复

使用道具 举报

1

主题

369

回帖

372

积分

高级会员

积分
372
发表于 2022-6-22 10:27:35 | 显示全部楼层
感谢分享,我在前面加个memset清零算了,不用操心
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2022-6-22 11:12:12 | 显示全部楼层
楼主的是早期标准库版的,现在HAL库版的,这个地方修改了,定义的时候直接做了结构体清零。
H7:

image.png

F4

image.png


回复

使用道具 举报

82

主题

401

回帖

667

积分

金牌会员

积分
667
QQ
 楼主| 发表于 2022-6-22 17:38:04 | 显示全部楼层
定义的时候 清零  学习了
武汉天纵鹏元科技有限公司。承接嵌入式项目开发,相关技术交流。STM32,物联网,工业控制方向。QQ  408137104
回复

使用道具 举报

19

主题

233

回帖

290

积分

高级会员

积分
290
发表于 2022-6-22 18:55:45 | 显示全部楼层
静态变量不都是零吗
回复

使用道具 举报

82

主题

401

回帖

667

积分

金牌会员

积分
667
QQ
 楼主| 发表于 2022-6-23 08:32:59 | 显示全部楼层
tovinz 发表于 2022-6-22 18:55
静态变量不都是零吗

不一定,单片机在初始化的时候内存内容是不确定的,还有其他的程序也会占用内存,会随机改写那个地址内容,如果没有初始化的话,那个值就是随机值,在程序应用过程中容易出隐患BUG

还有在函数内部定义变量的时候也要初始化0或者定义的值  不然也会出幺蛾子
可以看我这个帖子
谨记,函数内部变量一定要初始化!!!
https://www.armbbs.cn/forum.php? ... 4&fromuid=18397
(出处: 硬汉嵌入式论坛)

武汉天纵鹏元科技有限公司。承接嵌入式项目开发,相关技术交流。STM32,物联网,工业控制方向。QQ  408137104
回复

使用道具 举报

19

主题

233

回帖

290

积分

高级会员

积分
290
发表于 2022-6-23 09:05:53 | 显示全部楼层
雷鹏 发表于 2022-6-23 08:32
不一定,单片机在初始化的时候内存内容是不确定的,还有其他的程序也会占用内存,会随机改写那个地址内容 ...

按理来说。未初始化的静态变量放在.bss段中,cm的单片机系统启动会调用通过调用__main对这个段里的内容进行清零操作啊。莫非将这个变量所在的空间指定了NoInit?
局部变量的值是未定义的这是规定了的
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2022-6-23 09:44:23 | 显示全部楼层
tovinz 发表于 2022-6-22 18:55
静态变量不都是零吗

你的理解没问题,MDK,IAR定义全局变量,大部分情况下都可以正常清零的。

回复

使用道具 举报

82

主题

401

回帖

667

积分

金牌会员

积分
667
QQ
 楼主| 发表于 2022-6-23 11:30:46 | 显示全部楼层
tovinz 发表于 2022-6-23 09:05
按理来说。未初始化的静态变量放在.bss段中,cm的单片机系统启动会调用通过调用__main对这个段里的内容进 ...

为了避免幺蛾子发生  养成好习惯  不管在在哪里  什么变量 定义之后直接初始化零
武汉天纵鹏元科技有限公司。承接嵌入式项目开发,相关技术交流。STM32,物联网,工业控制方向。QQ  408137104
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-26 08:47 , Processed in 0.268926 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表