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

TIM在base模式时的任意定时的实现,NEC红外编码

[复制链接]
kylongmu 发布时间:2018-8-23 11:35
ST给的TIM例子都是实现一个固定频率的当时输出,如果想在每次定时中断后改变定时器值,那么需要动态的修改定时器周期配置。
实测中发现一有坑,给大家共享。
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  2. {
  3.   /* USER CODE BEGIN Callback 0 */

  4.   /* USER CODE END Callback 0 */
  5.   if (htim->Instance == TIM22) {
  6.     HAL_IncTick();
  7.   }
  8.   /* USER CODE BEGIN Callback 1 */
  9.   if (htim->Instance == TIM2) {
  10.     IrdaTransfer(pDataNEC);
  11.         }
  12.   /* USER CODE END Callback 1 */
  13. }
复制代码
首先在HAL_TIM_PeriodElapsedCallback中添加TIM的Update事件中断回调函数,自己写IrdaTransfer(pDataNEC)实现NEC编码的红外遥控。
  1. uint16_t IrdaTransfer(uint8_t* pDataNEC)
  2. {
  3.         PulseVal=TimeSerial(pDataNEC,PulseSteps);
  4.         PulseSteps++;
  5.         if(PulseVal>0)
  6.         {
  7.                 htim2.Init.Period = PulseVal&0x7fff;
  8.                 HAL_TIM_Base_Init(&htim2);
  9.                 __HAL_TIM_CLEAR_FLAG(&htim2, TIM_SR_UIF);
  10.                 HAL_TIM_Base_Start_IT(&htim2);
  11.         }
  12.         else
  13.         {
  14.                 __HAL_TIM_CLEAR_FLAG(&htim2, TIM_SR_UIF);
  15.                 HAL_TIM_Base_Stop_IT(&htim2);
  16.         }
  17.         if(PulseVal&0x8000)
  18.                 HAL_GPIO_WritePin(IrDA_Output_GPIO_Port, IrDA_Output_Pin, GPIO_PIN_SET);
  19.         else
  20.                 HAL_GPIO_WritePin(IrDA_Output_GPIO_Port, IrDA_Output_Pin, GPIO_PIN_RESET);
  21.         return PulseVal;
  22. }
复制代码
注意这里的坑是:
htim2.Init.Period = PulseVal&0x7fff;
                HAL_TIM_Base_Init(&htim2);
                __HAL_TIM_CLEAR_FLAG(&htim2, TIM_SR_UIF);//这是坑,必须在此处加。
HAL_TIM_Base_Start_IT(&htim2);
在初始化定时时长后,必须先清除中断标志,再启动定时器中断,否则会直接进中断而没有在定时结束时进,这个坑调了我一天,不明白为啥初始化定时器就会触发一次UPDATE中断。
以上代码即可实现每次定时后立即更新定时值,实现任意的序列控制。具体的NEC红外序列实现功能我就不放了,留点自己动脑子的地方,填的坑与大家共享。



收藏 评论4 发布时间:2018-8-23 11:35

举报

4个回答
kylongmu 回答时间:2018-8-23 11:46:26
以定时器方式实现任意序列的输出,最大的好处是MCU可以完全处于低功耗状态,不用写跑死MCU的Delay函数。
kylongmu 回答时间:2018-8-23 13:26:46
感觉是提供的库函数HAL_TIM_Base_Init(&htim2)带来的问题,触发了UPDATE中断,为了验证此想法,直接操作TIM的ARR寄存器,把__HAL_TIM_CLEAR_FLAG提前,代码如下:
  1. uint16_t IrdaTransfer(uint8_t* pDataNEC)
  2. {
  3.         __HAL_TIM_CLEAR_FLAG(&htim2, TIM_SR_UIF);
  4.         PulseVal=TimeSerial(pDataNEC,PulseSteps);
  5.         PulseSteps++;
  6.         if(PulseVal>0)
  7.         {
  8.                 htim2.Instance->ARR = (uint32_t)PulseVal&0x7fff ;
  9.                 HAL_TIM_Base_Start_IT(&htim2);
  10.         }
  11.         else
  12.         {
  13.                 HAL_TIM_Base_Stop_IT(&htim2);
  14.         }
  15.         if(PulseVal&0x8000)
  16.                 HAL_GPIO_WritePin(IrDA_Output_GPIO_Port, IrDA_Output_Pin, GPIO_PIN_SET);
  17.         else
  18.                 HAL_GPIO_WritePin(IrDA_Output_GPIO_Port, IrDA_Output_Pin, GPIO_PIN_RESET);
  19.         return PulseVal;
  20. }
复制代码
发现工作正常,看来这个坑真的是
HAL库里的。



butterflyspring 回答时间:2018-8-23 14:32:41
不错不错,如果可以共享整个工程就好了,但是我了解这种遥控器,最关键的还是解码库.特别是那个万能遥控器的.
xmshao 回答时间:2018-11-1 17:41:37
          __HAL_TIM_CLEAR_FLAG(&htim2, TIM_SR_UIF);//这是坑,必须在此处加。
HAL_TIM_Base_Start_IT(&htim2);
在初始化定时时长后,必须先清除中断标志,再启动定时器中断,否则会直接进中断而没有在定时结束时进,这个坑调了我一天,不明白为啥初始化定时器就会触发一次UPDATE中断。
==>不能算是个坑,应该是手册没看清楚。
因为有些寄存器比方PSC/RCR寄存器必须通过更新事件才能更新,我们初始化时只能操作预转载寄存器,所以让我们用户数据生效,就手动产生个更新事件,让预装载寄存器的数据拷贝到影子寄存器【实际寄存器】发挥作用。但这个操作会置位更新中断标志,所以我们在使能更新中断前有必要清除下该标志UIF,否则可能一使能更新中断就跳进更新中断服务程序。

所属标签

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