你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32单片机裸机程序-高级实现实时性处理方法

[复制链接]
STMCU小助手 发布时间:2021-7-8 11:18
概述
这篇文章是对刚刚学习单片机的小伙伴们,提的一些处理技巧思维。(我在项目上经常使用这样的处理思路)

现在举个栗子,应用场景是这样的,比如:在while(1)中在处理一些裸机,然后碰巧又在延时时候,当你又有其他事件(这个事件是外部触发而来的)比较紧急要处理这个事件时,这时候,CUP肯定是处理不来,需要等待while(1)处理完延时之后,才能处理这个比较紧急的事件,这时候,可能有人会说,你干嘛不在外部中断去处理这个事件呢,但是如果这个事件刚好也要延时呢?怎么办,一般好的程序不会在中断函数里面使用过多的延时,还有很多逻辑的事件,这时候就要换一种处理思维了。哈哈,想必大家也会想到它,那就是定时器,如果这时候使用定时器的话,问题肯定能处理的比在while(1)的大循环干等待延时要强的多,完美的组合就是,要中断与定时器搭配来使用才行,这样的处理事件就不会因为延时逻辑过长导致其它事件处理不及时的问题。(废话有点多,请谅解)

1、打个比方:我的项目上有关机功能

2、首先配置一个单独的定时器(我这里配置的是 基本定时器6,注意:如果Tim不够用的话,可以使用SysTick_Handler/滴答定时器代替,使用方法同理。)
3.png

3、该定时专门处理这个关机逻辑的,这时根据自己的需求修改定时器的频率
4.png
tim.c 文件
  1. <font face="微软雅黑" size="3">/* USER CODE BEGIN 0 */
  2. #include "adc.h"

  3. extern void Power_OFF(void);
  4. /* USER CODE END 0 */
  5. .
  6. .
  7. .

  8. /* USER CODE BEGIN 1 */

  9. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  10. {
  11.         if(htim->Instance == TIM2)
  12.         {
  13.                 #ifdef TIMER_SAMPLING_MODE
  14.                         get_ADC_Channel_Val();
  15.                 #endif
  16.         }
  17.         else if(htim->Instance == TIM6)
  18.         {
  19.                 //编写回调逻辑,即定时器6定时1000us后的逻辑 1ms=1次
  20.                 Power_OFF();
  21.         }
  22. }

  23. /* USER CODE END 1 */
  24. </font>
复制代码
Power_OFF()函数:
  1. <font face="微软雅黑" size="3">
  2. void Power_ON(void)
  3. {
  4.         uint32_t tickstart = HAL_GetTick();
  5.         while(1)
  6.         {
  7.                 //读Power_on是否是高电平
  8.                 if(HAL_GPIO_ReadPin(POWER_OFF_GPIO_Port,POWER_OFF_Pin)==GPIO_PIN_SET)
  9.                 {
  10.                         if((HAL_GetTick() - tickstart) >= 3000)        //如果大于3s
  11.                         {
  12.                                 g_powerON_flag = 1;
  13.                                 HAL_GPIO_WritePin(POWER_ON_GPIO_Port,POWER_ON_Pin,GPIO_PIN_SET);        //开机
  14.                                 
  15.                                 HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_SET);                  //MOT_ON
  16.                                 HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);                                    //LED_ON
  17.                                 HAL_Delay(500);                                                   
  18.                                 HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_RESET);    //MOT_OFF
  19.                                 HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);                            //LED_OFF
  20.                                 HAL_Delay(500);                                                   
  21.                                 HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_SET);                  //MOT_ON
  22.                                 HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);                                          //LED_ON
  23.                                 HAL_Delay(500);
  24.                                 HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_RESET);                //MOT_OFF
  25.                                 HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);                                        //LED_OFF
  26.                                 break;
  27.                         }
  28.                 }
  29.                 else
  30.                 {
  31.                         HAL_GPIO_WritePin(POWER_ON_GPIO_Port,POWER_ON_Pin,GPIO_PIN_RESET);        //不开机
  32.                         HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_RESET);                  //MOT_OFF
  33.                         HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);                                                //LED_OFF
  34.                 }
  35.         }
  36. }
  37. </font>
复制代码
外部中断脚代码处理逻辑
  1. <font face="微软雅黑" size="3">
  2. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)               
  3. {
  4.     if(GPIO_Pin == POWER_OFF_Pin)
  5.         {
  6.                 /* Clear Wake Up Flag */
  7.                 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
  8.                 if(HAL_GPIO_ReadPin(POWER_OFF_GPIO_Port,POWER_OFF_Pin)==SET)
  9.                 {
  10.                         //printf("关机唤醒中断\r\n");
  11.                         g_powerOffWakeUp_flag=1;
  12.                         HAL_TIM_Base_Start_IT(&htim6);                                //开启定时器
  13.                 }
  14.         }
  15. }
  16. </font>
复制代码
main.c 文件
  1. <font face="微软雅黑" size="3">
  2. int main(void)
  3. {
  4.   /* USER CODE BEGIN 1 */

  5.   /* USER CODE END 1 */

  6.   /* MCU Configuration--------------------------------------------------------*/

  7.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  8.   HAL_Init();

  9.   /* USER CODE BEGIN Init */

  10.   /* USER CODE END Init */

  11.   /* Configure the system clock */
  12.   SystemClock_Config();

  13.   /* USER CODE BEGIN SysInit */

  14.   /* USER CODE END SysInit */

  15.   /* Initialize all configured peripherals */
  16.   MX_GPIO_Init();
  17.   MX_LPUART1_UART_Init();
  18.   MX_USART1_UART_Init();
  19.   /* USER CODE BEGIN 2 */

  20.   /* USER CODE END 2 */

  21.   /* Infinite loop */
  22.   /* USER CODE BEGIN WHILE */
  23.   while (1)
  24.   {
  25.           //事件1
  26.           HAL_Delay(1000);
  27.           //事件2
  28.           HAL_Delay(3000);
  29.     /* USER CODE END WHILE */

  30.     /* USER CODE BEGIN 3 */
  31.   }
  32.   /* USER CODE END 3 */

  33. </font>
复制代码
总结一下:其实这样处理思想,可以应用在很多地方,可达到实时性。不需要管while(1)中大循环的逻辑。有点像多线程处理一样。

这里的main.c代码,在实际开发中也不太允许这样处理,这样实时性太差了,也是很多小白刚学单片机犯最多的错误。这样写一看就知道是菜鸟。当然,我那样写不是很高大尚,其实想处理多线程的思路,还是引入RTOS好些。当然也不是说逻辑不好,各有利弊,看使用情况而定。

收藏 评论0 发布时间:2021-7-8 11:18

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版