OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3024|回复: 3

矩阵键盘翻转扫描时osdelay()函数卡顿导致程序无法正常运行

[复制链接]

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2021-1-22
在线时间
10 小时
发表于 2022-11-16 16:19:58 | 显示全部楼层 |阅读模式
10金钱

复制代码

键盘的扫描部分程序如下,使用的是翻转扫描的方法,高四位分别为GPIOC的C3,C4,C5,C6端口,低四位分别是GPIOD的D13,D13,D14,D15端口。

扫描过程是:
1、将高四位端口设置为输入模式,然后上拉,低四位的端口设置为输出模式,写为低电平输出,然后读高四位的值,用high_bit记录;
2、然后然后将低四位端口设置为输入模式,然后上拉,高四位的端口设置为输出模式,写为低电平输出,然后读低四位的值,用low_bit记录;
3、将高四位high_bit与低四位low_bit做或运算,得到8位的值,对应不同按键被按下的键值。

问题:
1、使用了freertos代码,在扫描程序中,使用osdelay()函数,程序会卡死osdelay()那一步中。但是使用stm32cubeide调试,单步运转程序正常,又不会出问题。
2、在KeyScanTask中使用printf函数,能够打印一次程序就停止了。
3、不适用osdelay()函数,使用hal_delay()做延时,程序又能正常执行。但是hal_delay()占用资源,在复杂系统中不便使用。
4、BoardScan()中的delay_us()函数是使用  __NOP();  实现的,这个仅做个延时。同样换用hal_delay(1);也没有问题。
5、修改osdelay()函数,在stat = osOK 之后加入一句 printf("osStatus  is %#4x .\r\n", stat); ,osdelay()又变正常,而且程序能够正常运行。

求问为什么会出现osdelay()函数卡死的问题,是什么原因导致的?(目前怀疑是直接对寄存器操作导致了系统紊乱,但是模拟spi通讯过程也是有这样的操作过程的。。。)

头文件
  1. // "matrixkeypad.h"
复制代码

扫描程序
  1. <blockquote>// "matrixkeypad.c"
复制代码

按键任务
  1. void StartKeyScanTask(void *argument) {
  2.     /* USER CODE BEGIN StartKeyScanTask */
  3.     uint8_t key_flag = 0x00;
  4.     osStatus_t stat;
  5.     /* Infinite loop */
  6.     for (;;) {
  7.         key_flag = BoardScan();
  8. //        printf("key_flag is %#04x. \r\n", key_flag);
  9.         switch (key_flag) {
  10.             case 0xff:HAL_GPIO_WritePin(GPIOG, 0x1fe, GPIO_PIN_SET);break;
  11.             case 0x88:HAL_GPIO_TogglePin(GPIOG, LED1_Pin);break;
  12.             case 0x48:HAL_GPIO_TogglePin(GPIOG, LED2_Pin);break;
  13.             case 0x28:HAL_GPIO_TogglePin(GPIOG, LED3_Pin);break;
  14.             case 0x18:HAL_GPIO_TogglePin(GPIOG, LED4_Pin);break;
复制代码





最佳答案

查看完整内容[请看2#楼]

代码中带了空格好像就漏掉了后面的,重新贴上 c文件 .h文件 task代码 重贴代码与之前代码相同,不过是新建了一个工程后测试的,hal_delay()函数和osdelay()函数做延时运行均变得正常了,hal_delay()的定时器由TIM1换成了TIM10,其他配置均相同。 放这里分享用吧, 具体原因还是不明,非常奇怪。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2021-1-22
在线时间
10 小时
 楼主| 发表于 2022-11-16 16:19:59 | 显示全部楼层


代码中带了空格好像就漏掉了后面的,重新贴上
c文件
  1. #include "matrixkeypad.h"
  2. volatile uint8_t bit_flag = 0x00;
  3. uint8_t BoardScan(void) {
  4.     uint8_t high_bit = 0xf0, low_bit = 0x0f;
  5. //    High_Bit_Scan_Init();
  6. LOW_PORT_OUT();
  7.     HIGH_PORT_IN();
  8.     HIGH_PORT_PULLUP();
  9.     HAL_GPIO_WritePin(LOW_PORT_C, LOW_PORT_PIN, GPIO_PIN_RESET);
  10. delay_times();
  11.     high_bit = ((uint8_t) (HIGH_PORT_R->IDR & HIGH_PORT_PIN) << 2) & 0xf0;
  12. //    high_bit = (uint8_t) ((HAL_GPIO_ReadPin(HIGH_PORT_R, H4_Pin) << 7) |
  13. //                          (HAL_GPIO_ReadPin(HIGH_PORT_R, H3_Pin) << 6) |
  14. //                          (HAL_GPIO_ReadPin(HIGH_PORT_R, H2_Pin) << 5) |
  15. //                          (HAL_GPIO_ReadPin(HIGH_PORT_R, H1_Pin) << 4)) & 0xf0;
  16. //    printf("high_bit is ok! high_bit is %#04x. \r\n", high_bit);
  17. if (high_bit != 0xf0) {
  18.         delay_times();
  19.         high_bit = ((uint8_t) (HIGH_PORT_R->IDR & HIGH_PORT_PIN) << 2) & 0xf0;
  20. //        high_bit = (uint8_t) ((HAL_GPIO_ReadPin(HIGH_PORT_R, H4_Pin) << 7) |
  21. //                              (HAL_GPIO_ReadPin(HIGH_PORT_R, H3_Pin) << 6) |
  22. //                              (HAL_GPIO_ReadPin(HIGH_PORT_R, H2_Pin) << 5) |
  23. //                              (HAL_GPIO_ReadPin(HIGH_PORT_R, H1_Pin) << 4)) & 0xf0;
  24. //        printf("high_bit is ok! high_bit is %#04x. \r\n", high_bit);
  25.         if (high_bit != 0xf0) {
  26. //            Low_Bit_Scan_Init();
  27.             HIGH_PORT_OUT();
  28.             LOW_PORT_IN();
  29.             LOW_PORT_PULLUP();
  30.             HAL_GPIO_WritePin(HIGH_PORT_R, HIGH_PORT_PIN, GPIO_PIN_RESET);
  31. delay_times();
  32.             low_bit = (uint8_t) ((LOW_PORT_C->IDR & LOW_PORT_PIN) >> 12) & 0x0f;
  33. //            low_bit = (uint8_t) ((HAL_GPIO_ReadPin(LOW_PORT_C, L4_Pin) << 3) |
  34. //                                 (HAL_GPIO_ReadPin(LOW_PORT_C, L3_Pin) << 2) |
  35. //                                 (HAL_GPIO_ReadPin(LOW_PORT_C, L2_Pin) << 1) |
  36. //                                 (HAL_GPIO_ReadPin(LOW_PORT_C, L1_Pin) << 0)) & 0x0f;
  37. //            printf("low_bit is ok! low_bit is %#04x. \r\n", low_bit);
  38.             bit_flag = high_bit | low_bit;
  39.         }
  40.     }
  41.     delay_times();
  42. //    __ASM volatile ("NOP");
  43. //    printf("bit_flag is ok! bit_flag is %#04x. \r\n", (uint8_t) ~bit_flag);
  44.     return (uint8_t) ~bit_flag;
  45. }
  46. void delay_times(void) {
  47.     osDelay(1);
  48. //    HAL_Delay(1);
  49. }
复制代码
.h文件
  1. #ifndef __MATRIXKEYPAD_H__
  2. #define __MATRIXKEYPAD_H__
  3. #include "main.h"
  4. #include "gpio.h"
  5. #include "retarget.h"
  6. #include "cmsis_os2.h"
  7. #define HIGH_PORT_R GPIOC
  8. #define LOW_PORT_C  GPIOD
复制代码

task代码
  1. void StartKeyScanTask(void *argument) {
  2.     /* USER CODE BEGIN StartKeyScanTask */
  3.     uint8_t last_key_flag = 0x00;
  4.     /* Infinite loop */
  5.     for (;;) {
  6.         uint8_t temp_key_flag = BoardScan();
  7. #if (TSAK_NOTIFICATION == 1)
  8.         // 任务通知版本,可以使用 任务通知功能 直接进行任务间传输,不需要全局变量。
  9.         if (temp_key_flag != last_key_flag) {
  10.             printf("key_flag is %#04x. \r\n", temp_key_flag);
  11.             xTaskGenericNotify(LedTaskHandle, temp_key_flag, eSetValueWithOverwrite, NULL);
  12.             last_key_flag = temp_key_flag;
  13.         }
  14. #else
  15.         // 使用全局变量key_flag版本,非任务通知
  16.         if (temp_key_flag != key_flag) {
  17.             printf("key_flag is %#04x. \r\n", temp_key_flag);
  18.             key_flag = temp_key_flag;
  19.         }
  20. #endif
  21.         osDelay(100);
  22.     }
  23.     /* USER CODE END StartKeyScanTask */
  24. }
复制代码


重贴代码与之前代码相同,不过是新建了一个工程后测试的,hal_delay()函数和osdelay()函数做延时运行均变得正常了,hal_delay()的定时器由TIM1换成了TIM10,其他配置均相同。
放这里分享用吧, 具体原因还是不明,非常奇怪。



回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
发表于 2022-11-16 19:45:57 | 显示全部楼层
osdelay()函数 是什么的干活,是操作系统自身提供的延时API函数吗?
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2021-1-22
在线时间
10 小时
 楼主| 发表于 2022-11-16 22:42:48 | 显示全部楼层
霸王猫 发表于 2022-11-16 19:45
osdelay()函数 是什么的干活,是操作系统自身提供的延时API函数吗?

是的,使用stm32cube生成的freertos项目时,自带的延时函数,和vtaskdelay()是一样的,多了层st的封装。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 13:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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