搜索
ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU

[STM32F0] 分享“半软半硬”两个16位定时器 级联成32位 CubeMX示例

[复制链接]
251|18
 楼主 | 2020-9-26 09:02 | 显示全部楼层 |阅读模式
摸索了 2天 总算是 【“半软半硬”】将 两个16位定时器 级联成 32位 了。
先请ST专家看看——是否能够配置成为完全的【硬级联】” ?
——意思是后级定时器 也采用 “Reset 捕获模式” ——我没配置成功——


CubeMX工程内容:——将 STM32 F030 Tim1 级联到 Tim3 的后面,
Tim3 出现 “溢出 更新事件” 的时候,Tim1 就自动计数一次 软读出
半软半硬.jpg
NVIC 配置优先级:明显 Tim3 优先级 必须高于 后级的Tim1 。
半软半硬2.jpg
主程序需要自己写的 测试代码:
Tim16 是用来 产生 PWM测试脉冲的,不在本例讨论。
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start (&htim16,TIM_CHANNEL_1);
  HAL_TIM_Base_Start_IT(&htim1);
  HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
  
  /* USER CODE END 2 */


  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    Overtime = __HAL_TIM_GET_COUNTER(&htim1);
      HAL_Delay(950);
    Overtime = __HAL_TIM_GET_COUNTER(&htim1);
      HAL_Delay(950);
    Overtime = __HAL_TIM_GET_COUNTER(&htim1);   
      HAL_Delay(950);
    Overtime = __HAL_TIM_GET_COUNTER(&htim1);   
      HAL_Delay(950);   
  HAL_Delay(1);
  /* USER CODE END WHILE */


  /* USER CODE BEGIN 3 */


  }
  /* USER CODE END 3 */

半软半硬1.jpg
需要自己写的 回调函数 :
  uint16_t GenPeriod,CountOver,Overtime;


void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM3)
  {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
      {                 // 由于内部 HSI 频率偏高 初值 39952 代表4ms,引用计算时【按照 四万】。
        GenPeriod = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
        CountOver = __HAL_TIM_GET_COUNTER(&htim1) - 1;
        __HAL_TIM_SET_COUNTER(&htim1,0);        // 借助该引脚的中断 提取溢出次数后 给它清零 。
      }
  }
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM1)
  {
    HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4); // 1023 = 四秒 Tim1 超时进中断 翻转 LED 。
  }
}

使用特权

评论回复
| 2020-9-26 10:07 | 显示全部楼层
感觉实际上还是软件功能实现的。虽然中断属于硬件触发事件,但是中间的响应过程还是软件。

使用特权

评论回复
 楼主 | 2020-9-26 10:07 | 显示全部楼层
想把它 搞成 【全硬件】方式依葫芦画瓢 居然【死机】了。
代码也都是 仔细 添加了,NVIC 也 添加了 Tim1 Capture 中断,
可是 —— 总是 死机 —— 按理说:“至少 不应该 死机 吧 !”
回调函数中:添加了 判断 Tim1 Capture 中断:也没错 啊。
if (htim->Instance == TIM1)
  {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
      {
        GenPerT1_2 = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_2);
      }
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
      {
        GenPerT1_1 = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);
      }
  }

全硬件.jpg

使用特权

评论回复
 楼主 | 2020-9-26 10:24 | 显示全部楼层
gaoyang9992006 发表于 2020-9-26 10:07
感觉实际上还是软件功能实现的。虽然中断属于硬件触发事件,但是中间的响应过程还是软件。 ...

难道 ST 公司 没有仔细考虑 定时器 级联捕获 ??

其实 俺只需要设置:后级定时器 工作在 计数器模式
计数器的时钟:来自前级定时器的 【溢出更新信号】
捕获引信:最好能 直接来自 前级定时器(节约引脚啊)
实在不行——我把 PA7 PA9 两个输入并联也并无不妥



可是——为何 居然 总是 死机 呢 ——!?——不解啊。

使用特权

评论回复
| 2020-9-26 10:47 | 显示全部楼层
caosix 发表于 2020-9-26 10:24
难道 ST 公司 没有仔细考虑 定时器 级联捕获 ??

其实 俺只需要设置:后级 ...

不知道你这么级联的作用是什么,因为定时这东西,可以分频吧,难道你要定很长很长很长?

使用特权

评论回复
 楼主 | 2020-9-26 11:23 | 显示全部楼层
gaoyang9992006 发表于 2020-9-26 10:47
不知道你这么级联的作用是什么,因为定时这东西,可以分频吧,难道你要定很长很长很长? ...

这是 应用层面的事情,例如 雷达捕获目标,
无线电信号脉冲 需要 非常高的 “时间分辨率”


你如果采用了“预分频器”,那么你测量到的目标
距离的分辨率就会很差,你还指望导弹能命中目标吗 ?

使用特权

评论回复
 楼主 | 2020-9-26 12:03 | 显示全部楼层
本帖最后由 caosix 于 2020-9-26 12:08 编辑
gaoyang9992006 发表于 2020-9-26 10:07
感觉实际上还是软件功能实现的。虽然中断属于硬件触发事件,但是中间的响应过程还是软件。 ...

现在 11:58 全解决了,调试器死机是低级失误
串口被动移位、占用了SWD调试口。咳 低级失误 。
结论:纯硬件级联 需要多占用一个引脚PA9-PA7需连接。
87878.jpg

最后一个 疑问:同样是 Capture 中断函数,Tim3 不需要去“人工 清零”
Tim1 就需要 __HAL_TIM_SET_COUNTER(&htim1,0);  去人工清零 。

使用特权

评论回复
| 2020-9-26 13:57 | 显示全部楼层
caosix 发表于 2020-9-26 11:23
这是 应用层面的事情,例如 雷达捕获目标,
无线电信号脉冲 需要 非常高的 “时间分辨率”,

你这个理由就太扯了,导弹那种是实时校准的,类似PID调节那种系统控制。没你说的时间分辨率。那种也就用16BIT也足够。

使用特权

评论回复
| 2020-9-26 14:11 | 显示全部楼层
caosix 发表于 2020-9-26 12:03
现在 11:58 全解决了,调试器死机是低级失误:
串口被动移位、占用了SWD调试口。咳 低级失 ...


很多单片机的几个定时器设计不同,这很正常。

使用特权

评论回复
| 2020-9-26 19:27 | 显示全部楼层
如果想将两个16位定时器级联成32位是可以的,前级定时器的更新事件作为触发输出,并作为后级定时器的触发输入,后级定时器工作外部时钟模式1.

使用特权

评论回复
 楼主 | 2020-9-29 09:19 | 显示全部楼层
香水城 发表于 2020-9-26 19:27
如果想将两个16位定时器级联成32位是可以的,前级定时器的更新事件作为触发输出,并作为后级定时器的触发输 ...

谢谢 大师的 总结。。最后一个 疑问 :
同样是 Capture 中断回调函数,Tim3 不需要去“人工 清零”


Tim1 就需要 __HAL_TIM_SET_COUNTER(&htim1,0);  去人工清零
这是怎么个道理呢 ?? 懒得去仔细看 手册,所以 在这里提问 。。

使用特权

评论回复
| 2020-9-29 13:42 | 显示全部楼层
caosix 发表于 2020-9-29 09:19
谢谢 大师的 总结。。最后一个 疑问 :
同样是 Capture 中断回调函数,Tim3 不需要去“人 ...

我对你说的代码并不是很了解,为什么这样不确定。

关于这个清零操作,我估计跟你定时器的工作模式有关。对于处于复位模式的定时器,相应的触发信号过来时,
计数器就可以被硬件清零,无须手动了。

使用特权

评论回复
| 2020-9-29 13:55 | 显示全部楼层
软件功能

使用特权

评论回复
| 2020-10-10 13:00 | 显示全部楼层
图文并茂呀

使用特权

评论回复
| 2020-10-10 13:00 | 显示全部楼层
这是用的iar吗

使用特权

评论回复
| 2020-10-10 13:03 | 显示全部楼层
为什么是半硬半软呢

使用特权

评论回复
| 2020-10-10 13:04 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
| 2020-10-10 13:05 | 显示全部楼层
我来学习学习

使用特权

评论回复
 楼主 | 2020-10-14 10:50 | 显示全部楼层
木木guainv 发表于 2020-10-10 13:03
为什么是半硬半软呢

为了 节约 一个 输入 引脚,
后级 定时器 没采用 【直接 捕获 模式】
而是 采用 “软处理” 。我事后验证了:
后级 定时器也可以采用 “全硬件 捕获”
那样 就需要将 前级 和 后级 各自的
输入 捕获引脚 并联起来
捕获输入脉冲。

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表