硬汉嵌入式论坛

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

[RTOS] 为FreeRTOS和RTX5使用HAL库整理的两种HAL库时间基准方案

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
发表于 2019-4-4 02:25:14 | 显示全部楼层 |阅读模式
专门为此教程准备的:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=93149


HAL库默认是用的滴答定时器,而OS里面要使用,所以整理了两种方案。

一种是使用TIM7提供,另外一种是借用RTOS的API获取

  1. /*
  2. *********************************************************************************************************
  3. *
  4. *        模块名称 : HAL库时基
  5. *        文件名称 : stm32h7xx_hal_timbase_tim.c
  6. *        版    本 : V1.0
  7. *        说    明 : 用于为HAL库提供时间基准
  8. *        修改记录 :
  9. *                版本号  日期         作者       说明
  10. *                V1.0    2018-07-29  Eric2013   正式发布
  11. *
  12. *        Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
  13. *
  14. *********************************************************************************************************
  15. */
  16. #include "includes.h"


  17. /* 采用TIM7方案或者RTX5内核时钟方案 */
  18. #if 0

  19. TIM_HandleTypeDef   TimHandle = {0};
  20.         
  21. /*
  22. *********************************************************************************************************
  23. *        函 数 名: System_Init
  24. *        功能说明: 为HAL库配置1ms的时间基准,此函数会被HAL_Init和HAL_RCC_ClockConfig调用
  25. *        形    参:TickPriority  定时器优先级
  26. *        返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)
  30. {

  31.         RCC_ClkInitTypeDef    clkconfig;
  32.         uint32_t              uwTimclock, uwAPB1Prescaler = 0U;
  33.         uint32_t              uwPrescalerValue = 0U;
  34.         uint32_t              pFLatency;

  35.         
  36.         /* 复位定时器7 */
  37.         TimHandle.Instance = TIM7;
  38.         if(HAL_TIM_Base_DeInit(&TimHandle) != HAL_OK)
  39.         {
  40.                 Error_Handler(__FILE__, __LINE__);
  41.         }
  42.         
  43.         /* 设置TIM7的中断优先级并使能 */
  44.         HAL_NVIC_SetPriority(TIM7_IRQn, TickPriority ,0U);
  45.         HAL_NVIC_EnableIRQ(TIM7_IRQn);

  46.         /* 使能TIM7时钟 */
  47.         __HAL_RCC_TIM7_CLK_ENABLE();

  48.         /*-----------------------------------------------------------------------
  49.         System Clock source       = PLL (HSE)
  50.         SYSCLK(Hz)                = 400000000 (CPU Clock)
  51.         HCLK(Hz)                  = 200000000 (AXI and AHBs Clock)
  52.         AHB Prescaler             = 2
  53.         D1 APB3 Prescaler         = 2 (APB3 Clock  100MHz)
  54.         D2 APB1 Prescaler         = 2 (APB1 Clock  100MHz)
  55.         D2 APB2 Prescaler         = 2 (APB2 Clock  100MHz)
  56.         D3 APB4 Prescaler         = 2 (APB4 Clock  100MHz)

  57.         因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = APB1 x 2 = 200MHz;
  58.         因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = APB2 x 2 = 200MHz;
  59.         APB4上面的TIMxCLK没有分频,所以就是100MHz;

  60.         APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14,LPTIM1
  61.         APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17

  62.         APB4 定时器有 LPTIM2,LPTIM3,LPTIM4,LPTIM5
  63.         ----------------------------------------------------------------------- */
  64.         /* 获取时钟配置 */
  65.         HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);

  66.         /* 获取APB1时钟 */
  67.         uwAPB1Prescaler = clkconfig.APB1CLKDivider;

  68.         /* 获得TIM7时钟 */
  69.         if (uwAPB1Prescaler == RCC_HCLK_DIV1)
  70.         {
  71.                 uwTimclock = HAL_RCC_GetPCLK1Freq();
  72.         }
  73.         else
  74.         {
  75.                 uwTimclock = 2*HAL_RCC_GetPCLK1Freq();
  76.         }

  77.         /* TIM7分频到1MHz */
  78.         uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);

  79.         /* TIM7CLK = uwTimclock / (Period + 1) / (Prescaler + 1) = 1KHz */
  80.         TimHandle.Init.Period = (1000000U / 1000U) - 1U;
  81.         TimHandle.Init.Prescaler = uwPrescalerValue;
  82.         TimHandle.Init.ClockDivision = 0;
  83.         TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
  84.         if(HAL_TIM_Base_Init(&TimHandle) == HAL_OK)
  85.         {
  86.                 /* 启动TIM7 */
  87.                 return HAL_TIM_Base_Start_IT(&TimHandle);
  88.         }

  89.         /* 返回错误 */
  90.         return HAL_ERROR;
  91. }

  92. /*
  93. *********************************************************************************************************
  94. *        函 数 名: HAL_SuspendTick
  95. *        功能说明: 关闭TIM7
  96. *        形    参: 无
  97. *        返 回 值: 无
  98. *********************************************************************************************************
  99. */
  100. void HAL_SuspendTick(void)
  101. {
  102.         __HAL_TIM_DISABLE_IT(&TimHandle, TIM_IT_UPDATE);
  103. }

  104. /*
  105. *********************************************************************************************************
  106. *        函 数 名: HAL_ResumeTick
  107. *        功能说明: 使能TIM7
  108. *        形    参: 无
  109. *        返 回 值: 无
  110. *********************************************************************************************************
  111. */
  112. void HAL_ResumeTick(void)
  113. {
  114.         __HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE);
  115. }

  116. /*
  117. *********************************************************************************************************
  118. *        函 数 名: TIM7_IRQHandler
  119. *        功能说明: TIM7定时器中断服务程序
  120. *        形    参: 无
  121. *        返 回 值: 无
  122. *********************************************************************************************************
  123. */
  124. void TIM7_IRQHandler(void)
  125. {
  126.         if((TIM7->SR & TIM_FLAG_UPDATE) != RESET)
  127.         {
  128.                  TIM7->SR = ~ TIM_FLAG_UPDATE;
  129.                  HAL_IncTick();
  130.         }
  131. }

  132. #else
  133. /*
  134. *********************************************************************************************************
  135. *        函 数 名: HAL_Delay
  136. *        功能说明: 重定向毫秒延迟函数。替换HAL中的函数。因为HAL中的缺省函数依赖于Systick中断,如果在USB、SD卡
  137. *             中断中有延迟函数,则会锁死。也可以通过函数HAL_NVIC_SetPriority提升Systick中断
  138. *        形    参: 无
  139. *        返 回 值: 无
  140. *********************************************************************************************************
  141. */
  142. void HAL_Delay(uint32_t Delay)
  143. {
  144.         bsp_DelayMS(Delay);
  145. }

  146. HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)
  147. {
  148.         return HAL_OK;
  149. }

  150. uint32_t HAL_GetTick (void)
  151. {
  152.         static uint32_t ticks = 0U;
  153.         uint32_t i;

  154.         if (osKernelGetState () == osKernelRunning)
  155.         {
  156.                 return ((uint32_t)osKernelGetTickCount ());
  157.         }

  158.         /* 如果RTX5还没有运行,采用下面方式 */
  159.         for (i = (SystemCoreClock >> 14U); i > 0U; i--)
  160.         {
  161.                 __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
  162.                 __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
  163.         }
  164.         
  165.         return ++ticks;
  166. }
  167. #endif

  168. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码



评分

参与人数 1金币 +20 收起 理由
missfox + 20

查看全部评分

回复

使用道具 举报

608

主题

3043

回帖

4887

积分

至尊会员

积分
4887
发表于 2019-4-4 08:38:07 | 显示全部楼层
回复

使用道具 举报

27

主题

272

回帖

353

积分

高级会员

积分
353
发表于 2019-4-4 09:08:14 | 显示全部楼层
回复

使用道具 举报

23

主题

1403

回帖

1472

积分

至尊会员

积分
1472
发表于 2019-4-4 11:04:12 | 显示全部楼层
特来支持,希望可以早点发一个模板出来尝尝鲜
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106590
QQ
 楼主| 发表于 2019-4-4 12:00:49 | 显示全部楼层
missfox 发表于 2019-4-4 11:04
特来支持,希望可以早点发一个模板出来尝尝鲜

好,后面先整出模板出来供大家使用。
回复

使用道具 举报

36

主题

2039

回帖

2147

积分

至尊会员

积分
2147
发表于 2019-4-4 15:58:47 | 显示全部楼层
我现在用的第1种方案。
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.
回复

使用道具 举报

3

主题

1222

回帖

1231

积分

至尊会员

积分
1231
发表于 2021-11-11 16:49:16 | 显示全部楼层
第二种方案,STM32CubeMX里面直接支持, 你可以自由选择定时器硬件。
  1. /* Private typedef -----------------------------------------------------------*/
  2. /* Private define ------------------------------------------------------------*/
  3. /* Private macro -------------------------------------------------------------*/
  4. /* Private variables ---------------------------------------------------------*/
  5. TIM_HandleTypeDef        htim6;
  6. /* Private function prototypes -----------------------------------------------*/
  7. /* Private functions ---------------------------------------------------------*/

  8. /**
  9.   * @brief  This function configures the TIM6 as a time base source.
  10.   *         The time source is configured  to have 1ms time base with a dedicated
  11.   *         Tick interrupt priority.
  12.   * @note   This function is called  automatically at the beginning of program after
  13.   *         reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
  14.   * @param  TickPriority: Tick interrupt priority.
  15.   * @retval HAL status
  16.   */
  17. HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
  18. {
  19.     RCC_ClkInitTypeDef    clkconfig;
  20.     uint32_t              uwTimclock, uwAPB1Prescaler;

  21.     uint32_t              uwPrescalerValue;
  22.     uint32_t              pFLatency;
  23.     /*Configure the TIM6 IRQ priority */
  24.     if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  25.     {
  26.         HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority, 0U);

  27.         /* Enable the TIM6 global Interrupt */
  28.         HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
  29.         uwTickPrio = TickPriority;
  30.     }
  31.     else
  32.     {
  33.         return HAL_ERROR;
  34.     }

  35.     /* Enable TIM6 clock */
  36.     __HAL_RCC_TIM6_CLK_ENABLE();

  37.     /* Get clock configuration */
  38.     HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);

  39.     /* Get APB1 prescaler */
  40.     uwAPB1Prescaler = clkconfig.APB1CLKDivider;
  41.     /* Compute TIM6 clock */
  42.     if (uwAPB1Prescaler == RCC_HCLK_DIV1)
  43.     {
  44.         uwTimclock = HAL_RCC_GetPCLK1Freq();
  45.     }
  46.     else
  47.     {
  48.         uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
  49.     }

  50.     /* Compute the prescaler value to have TIM6 counter clock equal to 1MHz */
  51.     uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);

  52.     /* Initialize TIM6 */
  53.     htim6.Instance = TIM6;

  54.     /* Initialize TIMx peripheral as follow:
  55.     + Period = [(TIM6CLK/1000) - 1]. to have a (1/1000) s time base.
  56.     + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
  57.     + ClockDivision = 0
  58.     + Counter direction = Up
  59.     */
  60.     htim6.Init.Period = (1000000U / 1000U) - 1U;
  61.     htim6.Init.Prescaler = uwPrescalerValue;
  62.     htim6.Init.ClockDivision = 0;
  63.     htim6.Init.CounterMode = TIM_COUNTERMODE_UP;

  64.     if(HAL_TIM_Base_Init(&htim6) == HAL_OK)
  65.     {
  66.         /* Start the TIM time Base generation in interrupt mode */
  67.         return HAL_TIM_Base_Start_IT(&htim6);
  68.     }

  69.     /* Return function status */
  70.     return HAL_ERROR;
  71. }
复制代码
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-26 00:48 , Processed in 0.170286 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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