硬汉嵌入式论坛

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

[NUCLEO-H743ZI] 【STM32H743实验例程】实验5:STM32H743使用滴答定时器实现多组软件定时器

[复制链接]

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
发表于 2018-4-4 01:44:37 | 显示全部楼层 |阅读模式
实验介绍
开发平台:官方STM32H743 NUCLEO板子
开发环境:MDK5.25正式版
软件版本:
(1)CMSIS软件包 V5.3.0
(2)H7的HAL库版本 V1.2.0
例程下载:
实验5:STM32H743使用滴答定时器实现多组软件定时器.7z (1.08 MB, 下载次数: 182)


  1. #include "bsp.h"



  2. /* 这2个全局变量转用于 bsp_DelayMS() 函数 */
  3. static volatile uint32_t s_uiDelayCount = 0;
  4. static volatile uint8_t s_ucTimeOutFlag = 0;

  5. /* 定于软件定时器结构体变量 */
  6. static SOFT_TMR s_tTmr[TMR_COUNT];

  7. /*
  8.         全局运行时间,单位1ms
  9.         最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题
  10. */
  11. __IO int32_t g_iRunTime = 0;

  12. static void bsp_SoftTimerDec(SOFT_TMR *_tmr);


  13. /*
  14. *********************************************************************************************************
  15. *        函 数 名: bsp_InitTimer
  16. *        功能说明: 配置systick中断,并初始化软件定时器变量
  17. *        形    参:  无
  18. *        返 回 值: 无
  19. *********************************************************************************************************
  20. */
  21. void bsp_InitTimer(void)
  22. {
  23.         uint8_t i;

  24.         /* 清零所有的软件定时器 */
  25.         for (i = 0; i < TMR_COUNT; i++)
  26.         {
  27.                 s_tTmr[i].Count = 0;
  28.                 s_tTmr[i].PreLoad = 0;
  29.                 s_tTmr[i].Flag = 0;
  30.                 s_tTmr[i].Mode = TMR_ONCE_MODE;        /* 缺省是1次性工作模式 */
  31.         }

  32.         /*
  33.                 配置systic中断周期为1ms,并启动systick中断。

  34.             SystemCoreClock 是固件中定义的系统内核时钟,对于STM32F4XX,一般为 168MHz

  35.             SysTick_Config() 函数的形参表示内核时钟多少个周期后触发一次Systick定时中断.
  36.                     -- SystemCoreClock / 1000  表示定时频率为 1000Hz, 也就是定时周期为  1ms
  37.                     -- SystemCoreClock / 500   表示定时频率为 500Hz,  也就是定时周期为  2ms
  38.                     -- SystemCoreClock / 2000  表示定时频率为 2000Hz, 也就是定时周期为  500us

  39.             对于常规的应用,我们一般取定时周期1ms。对于低速CPU或者低功耗应用,可以设置定时周期为 10ms
  40.     */
  41.         SysTick_Config(SystemCoreClock / 1000);
  42. }

  43. /*
  44. *********************************************************************************************************
  45. *        函 数 名: SysTick_ISR
  46. *        功能说明: SysTick中断服务程序,每隔1ms进入1次
  47. *        形    参:  无
  48. *        返 回 值: 无
  49. *********************************************************************************************************
  50. */
  51. extern void bsp_RunPer1ms(void);
  52. extern void bsp_RunPer10ms(void);
  53. void SysTick_ISR(void)
  54. {
  55.         static uint8_t s_count = 0;
  56.         uint8_t i;

  57.         /* 每隔1ms进来1次 (仅用于 bsp_DelayMS) */
  58.         if (s_uiDelayCount > 0)
  59.         {
  60.                 if (--s_uiDelayCount == 0)
  61.                 {
  62.                         s_ucTimeOutFlag = 1;
  63.                 }
  64.         }

  65.         /* 每隔1ms,对软件定时器的计数器进行减一操作 */
  66.         for (i = 0; i < TMR_COUNT; i++)
  67.         {
  68.                 bsp_SoftTimerDec(&s_tTmr[i]);
  69.         }

  70.         /* 全局运行时间每1ms增1 */
  71.         g_iRunTime++;
  72.         if (g_iRunTime == 0x7FFFFFFF)        /* 这个变量是 int32_t 类型,最大数为 0x7FFFFFFF */
  73.         {
  74.                 g_iRunTime = 0;
  75.         }

  76.         bsp_RunPer1ms();                /* 每隔1ms调用一次此函数,此函数在 bsp.c */

  77.         if (++s_count >= 10)
  78.         {
  79.                 s_count = 0;

  80.                 bsp_RunPer10ms();        /* 每隔10ms调用一次此函数,此函数在 bsp.c */
  81.         }
  82. }

  83. /*
  84. *********************************************************************************************************
  85. *        函 数 名: bsp_SoftTimerDec
  86. *        功能说明: 每隔1ms对所有定时器变量减1。必须被SysTick_ISR周期性调用。
  87. *        形    参:  _tmr : 定时器变量指针
  88. *        返 回 值: 无
  89. *********************************************************************************************************
  90. */
  91. static void bsp_SoftTimerDec(SOFT_TMR *_tmr)
  92. {
  93.         if (_tmr->Count > 0)
  94.         {
  95.                 /* 如果定时器变量减到1则设置定时器到达标志 */
  96.                 if (--_tmr->Count == 0)
  97.                 {
  98.                         _tmr->Flag = 1;

  99.                         /* 如果是自动模式,则自动重装计数器 */
  100.                         if(_tmr->Mode == TMR_AUTO_MODE)
  101.                         {
  102.                                 _tmr->Count = _tmr->PreLoad;
  103.                         }
  104.                 }
  105.         }
  106. }

  107. /*
  108. *********************************************************************************************************
  109. *        函 数 名: bsp_DelayMS
  110. *        功能说明: ms级延迟,延迟精度为正负1ms
  111. *        形    参:  n : 延迟长度,单位1 ms。 n 应大于2
  112. *        返 回 值: 无
  113. *********************************************************************************************************
  114. */
  115. void bsp_DelayMS(uint32_t n)
  116. {
  117.         if (n == 0)
  118.         {
  119.                 return;
  120.         }
  121.         else if (n == 1)
  122.         {
  123.                 n = 2;
  124.         }

  125.         DISABLE_INT();                          /* 关中断 */

  126.         s_uiDelayCount = n;
  127.         s_ucTimeOutFlag = 0;

  128.         ENABLE_INT();                                  /* 开中断 */

  129.         while (1)
  130.         {
  131.                 bsp_Idle();                                /* CPU空闲执行的操作, 见 bsp.c 和 bsp.h 文件 */

  132.                 /*
  133.                         等待延迟时间到
  134.                         注意:编译器认为 s_ucTimeOutFlag = 0,所以可能优化错误,因此 s_ucTimeOutFlag 变量必须申明为 volatile
  135.                 */
  136.                 if (s_ucTimeOutFlag == 1)
  137.                 {
  138.                         break;
  139.                 }
  140.         }
  141. }

  142. /*
  143. *********************************************************************************************************
  144. *    函 数 名: bsp_DelayUS
  145. *    功能说明: us级延迟。 必须在systick定时器启动后才能调用此函数。
  146. *    形    参:  n : 延迟长度,单位1 us
  147. *    返 回 值: 无
  148. *********************************************************************************************************
  149. */
  150. void bsp_DelayUS(uint32_t n)
  151. {
  152.     uint32_t ticks;
  153.     uint32_t told;
  154.     uint32_t tnow;
  155.     uint32_t tcnt = 0;
  156.     uint32_t reload;
  157.       
  158.         reload = SysTick->LOAD;               
  159.     ticks = n * (SystemCoreClock / 1000000);         /* 需要的节拍数 */  
  160.    
  161.     tcnt = 0;
  162.     told = SysTick->VAL;             /* 刚进入时的计数器值 */

  163.     while (1)
  164.     {
  165.         tnow = SysTick->VAL;   
  166.         if (tnow != told)
  167.         {   
  168.             /* SYSTICK是一个递减的计数器 */   
  169.             if (tnow < told)
  170.             {
  171.                 tcnt += told - tnow;   
  172.             }
  173.             /* 重新装载递减 */
  174.             else
  175.             {
  176.                 tcnt += reload - tnow + told;   
  177.             }        
  178.             told = tnow;

  179.             /* 时间超过/等于要延迟的时间,则退出 */
  180.             if (tcnt >= ticks)
  181.             {
  182.                     break;
  183.             }
  184.         }  
  185.     }
  186. }


  187. /*
  188. *********************************************************************************************************
  189. *        函 数 名: bsp_StartTimer
  190. *        功能说明: 启动一个定时器,并设置定时周期。
  191. *        形    参:          _id     : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
  192. *                                _period : 定时周期,单位1ms
  193. *        返 回 值: 无
  194. *********************************************************************************************************
  195. */
  196. void bsp_StartTimer(uint8_t _id, uint32_t _period)
  197. {
  198.         if (_id >= TMR_COUNT)
  199.         {
  200.                 /* 打印出错的源代码文件名、函数名称 */
  201.                 BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
  202.                 while(1); /* 参数异常,死机等待看门狗复位 */
  203.         }

  204.         DISABLE_INT();                          /* 关中断 */

  205.         s_tTmr[_id].Count = _period;                /* 实时计数器初值 */
  206.         s_tTmr[_id].PreLoad = _period;                /* 计数器自动重装值,仅自动模式起作用 */
  207.         s_tTmr[_id].Flag = 0;                                /* 定时时间到标志 */
  208.         s_tTmr[_id].Mode = TMR_ONCE_MODE;        /* 1次性工作模式 */

  209.         ENABLE_INT();                                  /* 开中断 */
  210. }

  211. /*
  212. *********************************************************************************************************
  213. *        函 数 名: bsp_StartAutoTimer
  214. *        功能说明: 启动一个自动定时器,并设置定时周期。
  215. *        形    参:          _id     : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
  216. *                                _period : 定时周期,单位10ms
  217. *        返 回 值: 无
  218. *********************************************************************************************************
  219. */
  220. void bsp_StartAutoTimer(uint8_t _id, uint32_t _period)
  221. {
  222.         if (_id >= TMR_COUNT)
  223.         {
  224.                 /* 打印出错的源代码文件名、函数名称 */
  225.                 BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
  226.                 while(1); /* 参数异常,死机等待看门狗复位 */
  227.         }

  228.         DISABLE_INT();                  /* 关中断 */

  229.         s_tTmr[_id].Count = _period;                        /* 实时计数器初值 */
  230.         s_tTmr[_id].PreLoad = _period;                /* 计数器自动重装值,仅自动模式起作用 */
  231.         s_tTmr[_id].Flag = 0;                                /* 定时时间到标志 */
  232.         s_tTmr[_id].Mode = TMR_AUTO_MODE;        /* 自动工作模式 */

  233.         ENABLE_INT();                          /* 开中断 */
  234. }

  235. /*
  236. *********************************************************************************************************
  237. *        函 数 名: bsp_StopTimer
  238. *        功能说明: 停止一个定时器
  239. *        形    参:          _id     : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
  240. *        返 回 值: 无
  241. *********************************************************************************************************
  242. */
  243. void bsp_StopTimer(uint8_t _id)
  244. {
  245.         if (_id >= TMR_COUNT)
  246.         {
  247.                 /* 打印出错的源代码文件名、函数名称 */
  248.                 BSP_Printf("Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__);
  249.                 while(1); /* 参数异常,死机等待看门狗复位 */
  250.         }

  251.         DISABLE_INT();          /* 关中断 */

  252.         s_tTmr[_id].Count = 0;                                /* 实时计数器初值 */
  253.         s_tTmr[_id].Flag = 0;                                /* 定时时间到标志 */
  254.         s_tTmr[_id].Mode = TMR_ONCE_MODE;        /* 自动工作模式 */

  255.         ENABLE_INT();                  /* 开中断 */
  256. }

  257. /*
  258. *********************************************************************************************************
  259. *        函 数 名: bsp_CheckTimer
  260. *        功能说明: 检测定时器是否超时
  261. *        形    参:          _id     : 定时器ID,值域【0,TMR_COUNT-1】。用户必须自行维护定时器ID,以避免定时器ID冲突。
  262. *                                _period : 定时周期,单位1ms
  263. *        返 回 值: 返回 0 表示定时未到, 1表示定时到
  264. *********************************************************************************************************
  265. */
  266. uint8_t bsp_CheckTimer(uint8_t _id)
  267. {
  268.         if (_id >= TMR_COUNT)
  269.         {
  270.                 return 0;
  271.         }

  272.         if (s_tTmr[_id].Flag == 1)
  273.         {
  274.                 s_tTmr[_id].Flag = 0;
  275.                 return 1;
  276.         }
  277.         else
  278.         {
  279.                 return 0;
  280.         }
  281. }

  282. /*
  283. *********************************************************************************************************
  284. *        函 数 名: bsp_GetRunTime
  285. *        功能说明: 获取CPU运行时间,单位1ms。最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题
  286. *        形    参:  无
  287. *        返 回 值: CPU运行时间,单位1ms
  288. *********************************************************************************************************
  289. */
  290. int32_t bsp_GetRunTime(void)
  291. {
  292.         int32_t runtime;

  293.         DISABLE_INT();          /* 关中断 */

  294.         runtime = g_iRunTime;        /* 这个变量在Systick中断中被改写,因此需要关中断进行保护 */

  295.         ENABLE_INT();                  /* 开中断 */

  296.         return runtime;
  297. }

  298. /*
  299. *********************************************************************************************************
  300. *        函 数 名: bsp_CheckRunTime
  301. *        功能说明: 计算当前运行时间和给定时刻之间的差值。处理了计数器循环。
  302. *        形    参:  _LastTime 上个时刻
  303. *        返 回 值: 当前时间和过去时间的差值,单位1ms
  304. *********************************************************************************************************
  305. */
  306. int32_t bsp_CheckRunTime(int32_t _LastTime)
  307. {
  308.         int32_t now_time;
  309.         int32_t time_diff;

  310.         DISABLE_INT();          /* 关中断 */

  311.         now_time = g_iRunTime;        /* 这个变量在Systick中断中被改写,因此需要关中断进行保护 */

  312.         ENABLE_INT();                  /* 开中断 */
  313.        
  314.         if (now_time >= _LastTime)
  315.         {
  316.                 time_diff = now_time - _LastTime;
  317.         }
  318.         else
  319.         {
  320.                 time_diff = 0x7FFFFFFF - _LastTime + now_time;
  321.         }

  322.         return time_diff;
  323. }

  324. /*
  325. *********************************************************************************************************
  326. *        函 数 名: SysTick_Handler
  327. *        功能说明: 系统嘀嗒定时器中断服务程序。启动文件中引用了该函数。
  328. *        形    参:  无
  329. *        返 回 值: 无
  330. *********************************************************************************************************
  331. */
  332. void SysTick_Handler(void)
  333. {
  334.         SysTick_ISR();
  335. }

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



回复

使用道具 举报

52

主题

623

回帖

784

积分

金牌会员

积分
784
发表于 2018-4-4 08:17:09 | 显示全部楼层
连发几个H7实验,敢情是放弃了RT系列了,转抱H7了啊
回复

使用道具 举报

2

主题

109

回帖

115

积分

初级会员

积分
115
发表于 2018-4-4 09:11:22 | 显示全部楼层
你的代码里面写到:建议低速CPU一般设置滴答定时器周期为10ms,那么一般情况下,建议多少M主频以下的采取10ms定时器呢?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
 楼主| 发表于 2018-4-4 09:43:50 | 显示全部楼层
浮云流水zjf 发表于 2018-4-4 09:11
你的代码里面写到:建议低速CPU一般设置滴答定时器周期为10ms,那么一般情况下,建议多少M主频以下的采取10 ...

STM32就用1ms就行。之前STM8的时候是搞的10ms。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
 楼主| 发表于 2018-4-4 09:44:28 | 显示全部楼层
ou513 发表于 2018-4-4 08:17
连发几个H7实验,敢情是放弃了RT系列了,转抱H7了啊

http://www.armbbs.cn/forum.php?m ... &extra=page%3D1
回复

使用道具 举报

2

主题

109

回帖

115

积分

初级会员

积分
115
发表于 2018-4-4 11:20:54 | 显示全部楼层
eric2013 发表于 2018-4-4 09:43
STM32就用1ms就行。之前STM8的时候是搞的10ms。

STM32的大于等于72M的都可以1ms,STM32低功耗的有32M的建议用10ms吗?
回复

使用道具 举报

2

主题

109

回帖

115

积分

初级会员

积分
115
发表于 2018-4-4 11:21:42 | 显示全部楼层
eric2013 发表于 2018-4-4 09:44
http://www.armbbs.cn/forum.php?mod=viewthread&tid=86017&extra=page%3D1

什么时候出H7呢
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
 楼主| 发表于 2018-4-4 11:22:04 | 显示全部楼层
浮云流水zjf 发表于 2018-4-4 11:20
STM32的大于等于72M的都可以1ms,STM32低功耗的有32M的建议用10ms吗?

如果程序中应用有1ms的需求,推荐用1ms。
回复

使用道具 举报

57

主题

908

回帖

1079

积分

至尊会员

积分
1079
发表于 2018-4-5 21:08:37 | 显示全部楼层
eric2013 发表于 2018-4-4 11:22
如果程序中应用有1ms的需求,推荐用1ms。

如果是ucos,  这个滴答是哪个参数啊?
比如F7   200M的主频,下面的是不是太大了?

                                                            /* ------------------------ TICKS ----------------------- */
#define  OS_CFG_TICK_RATE_HZ            1000u               /* Tick rate in Hertz (10 to 1000 Hz)                     */
               */
#define  OS_CFG_TMR_TASK_RATE_HZ         100u               /* Rate for timers (100 Hz Typ.)                           */


另外,任务里面
OSTimeDlyHMSM(0, 0, 0, 10 ,OS_OPT_TIME_PERIODIC,&os_err);
10ms 切换一次是不是太慢了? 老的stm32f103之类一直用这个, 换F7 200M了是不是要升级一下
变成1ms?? 那么对应的OS_CFG_TICK_RATE_HZ          OS_CFG_TMR_TASK_RATE_HZ         设置多少呢??

期望版主有空帮忙看看这个问题。。感觉一直没有吃透。   
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
 楼主| 发表于 2018-4-6 15:36:00 | 显示全部楼层
roguebear 发表于 2018-4-5 21:08
如果是ucos,  这个滴答是哪个参数啊?
比如F7   200M的主频,下面的是不是太大了?

一般情况下,系统时钟节拍推荐设置1ms,使用F1,F4,F7,H7都推荐这个数值。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-1 07:20 , Processed in 0.395103 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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