硬汉嵌入式论坛

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

除数0 运算请教

[复制链接]

32

主题

298

回帖

394

积分

高级会员

积分
394
发表于 2020-1-11 16:00:21 | 显示全部楼层 |阅读模式
本帖最后由 weiyuliang 于 2020-1-11 16:29 编辑

请教一下,定时器部分代码,除法运算,如果除数为0,结果直接等于最大数值吗?
比如设置 _ulFreq0,计算得出来的 usPeriod等于0xFFFF,请教一下,这个地方除数为0是怎么运算的
  1. TIM_HandleTypeDef   TimHandle = {0};
  2.         uint16_t usPeriod;
  3.         uint16_t usPrescaler;
  4.         uint32_t uiTIMxCLK;

  5.         /* 使能TIM时钟 */
  6.         bsp_RCC_TIM_Enable(TIMx);
  7.         
  8.         /*-----------------------------------------------------------------------
  9.                 system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:

  10.                 HCLK = SYSCLK / 1     (AHB1Periph)
  11.                 PCLK2 = HCLK / 2      (APB2Periph)
  12.                 PCLK1 = HCLK / 4      (APB1Periph)

  13.                 因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
  14.                 因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;

  15.                 APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13,TIM14
  16.                 APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11

  17.         ----------------------------------------------------------------------- */
  18.         if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9) || (TIMx == TIM10) || (TIMx == TIM11))
  19.         {
  20.                 /* APB2 定时器时钟 = 168M */
  21.                 uiTIMxCLK = SystemCoreClock;
  22.         }
  23.         else        
  24.         {
  25.                 /* APB1 定时器 = 84M */
  26.                 uiTIMxCLK = SystemCoreClock / 2;
  27.         }

  28.         if (_ulFreq < 100)
  29.         {
  30.                 usPrescaler = 10000 - 1;                                                        /* 分频比 = 10000 */               
  31.                 usPeriod =  (uiTIMxCLK / 10000)/ _ulFreq  - 1;                /* 自动重装的值 */
  32.         }
  33.         else if (_ulFreq < 3000)
  34.         {
  35.                 usPrescaler = 100 - 1;                                        /* 分频比 = 100 */
  36.                 usPeriod =  (uiTIMxCLK / 100) / _ulFreq  - 1;                /* 自动重装的值 */
  37.         }
  38.         else        /* 大于4K的频率,无需分频 */
  39.         {
  40.                 usPrescaler = 0;                                        /* 分频比 = 1 */
  41.                 usPeriod = uiTIMxCLK / _ulFreq - 1;        /* 自动重装的值 */
  42.         }
复制代码


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2020-1-11 16:19:23 | 显示全部楼层
不能取值为0。


取值为0的话,可以看下权威指南,我记得对此有描述,另外可以先实际测试下。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2020-1-11 16:23:15 | 显示全部楼层
你这个标题导致帖子显示异常了,我重新修改了下,貌似还是不行
QQ截图20200111162224.png
回复

使用道具 举报

32

主题

298

回帖

394

积分

高级会员

积分
394
 楼主| 发表于 2020-1-11 16:29:05 | 显示全部楼层
eric2013 发表于 2020-1-11 16:23
你这个标题导致帖子显示异常了,我重新修改了下,貌似还是不行

硬汉收到,谢谢,我先把标题改好,
回复

使用道具 举报

32

主题

298

回帖

394

积分

高级会员

积分
394
 楼主| 发表于 2020-1-11 16:32:18 | 显示全部楼层

另外,如果需要严格要求程序的质量,还可以让CM3在遇到除数为零的时候,以及遇到未对齐访问的时候也产生用法fault。在NVIC中有两个控制位分别与它们对应。通过设置这两个控制位,就可以激活它们;看到权威指南有这个描述
回复

使用道具 举报

32

主题

298

回帖

394

积分

高级会员

积分
394
 楼主| 发表于 2020-1-11 16:35:06 | 显示全部楼层
实际测试,当_ulFreq = 0的时候,计算usPeriod =  (uiTIMxCLK / 10000)/ _ulFreq  - 1;                /* 自动重装的值 */

usPeriod自动重装的值是0xFFFF,  也就是 (uiTIMxCLK / 10000)/ 0 = 0;
0-1= 0xFFFF;

硬汉请教一下这样处理是否可行?先判断_ulFreq是否等于0,如果等于0,直接关闭定时器;
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2020-1-11 16:41:43 | 显示全部楼层
weiyuliang 发表于 2020-1-11 16:35
实际测试,当_ulFreq = 0的时候,计算usPeriod =  (uiTIMxCLK / 10000)/ _ulFreq  - 1;                /* 自动重装的值 * ...

可以的。
回复

使用道具 举报

32

主题

298

回帖

394

积分

高级会员

积分
394
 楼主| 发表于 2020-1-11 17:01:38 | 显示全部楼层

收到,谢谢;已加入_ulFreq 为零判断;测试定时器关闭可以执行;

  1. void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority)
  2. {
  3.         TIM_HandleTypeDef   TimHandle = {0};
  4.         uint16_t usPeriod;
  5.         uint16_t usPrescaler;
  6.         uint32_t uiTIMxCLK;

  7.         if(_ulFreq == 0)
  8.         {
  9.                 /* 关闭定时器 Update interrupt   */
  10.                 TIMx->DIER &= ~TIM_IT_UPDATE;
  11.                
  12.                 return;
  13.         }
  14.         /* 使能TIM时钟 */
  15.         bsp_RCC_TIM_Enable(TIMx);
  16.        
  17.         /*-----------------------------------------------------------------------
  18.                 system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:

  19.                 HCLK = SYSCLK / 1     (AHB1Periph)
  20.                 PCLK2 = HCLK / 2      (APB2Periph)
  21.                 PCLK1 = HCLK / 4      (APB1Periph)

  22.                 因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
  23.                 因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;

  24.                 APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13,TIM14
  25.                 APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11

  26.         ----------------------------------------------------------------------- */
  27.         if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9) || (TIMx == TIM10) || (TIMx == TIM11))
  28.         {
  29.                 /* APB2 定时器时钟 = 168M */
  30.                 uiTIMxCLK = SystemCoreClock;
  31.         }
  32.         else       
  33.         {
  34.                 /* APB1 定时器 = 84M */
  35.                 uiTIMxCLK = SystemCoreClock / 2;
  36.         }

  37.         if (_ulFreq < 100)
  38.         {
  39.                 usPrescaler = 10000 - 1;                                                        /* 分频比 = 10000 */               
  40.                 usPeriod =  (uiTIMxCLK / 10000)/ _ulFreq  - 1;                /* 自动重装的值 */

  41.                 printf(" usPeriod %d \r\n",usPeriod);
  42.         }
  43.         else if (_ulFreq < 3000)
  44.         {
  45.                 usPrescaler = 100 - 1;                                        /* 分频比 = 100 */
  46.                 usPeriod =  (uiTIMxCLK / 100) / _ulFreq  - 1;                /* 自动重装的值 */
  47.         }
  48.         else        /* 大于4K的频率,无需分频 */
  49.         {
  50.                 usPrescaler = 0;                                        /* 分频比 = 1 */
  51.                 usPeriod = uiTIMxCLK / _ulFreq - 1;        /* 自动重装的值 */
  52.         }

  53.         /*
  54.        定时器中断更新周期 = TIMxCLK / usPrescaler + 1)/usPeriod + 1)
  55.         */
  56.         TimHandle.Instance = TIMx;
  57.         TimHandle.Init.Prescaler         = usPrescaler;                        /* 分频值         */
  58.         TimHandle.Init.Period            = usPeriod;                        /* 周期变量 */
  59.         TimHandle.Init.ClockDivision     = 0;
  60.         TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
  61.         TimHandle.Init.RepetitionCounter = 0;
  62.         TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  63.         if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
  64.         {
  65.                 Error_Handler(__FILE__, __LINE__);
  66.         }

  67.         /* 使能定时器中断  */
  68.         __HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE);
  69.        

  70.         /* 配置TIM定时更新中断 (Update) */
  71.         {
  72.         uint8_t irq = 0;        /* 中断号, 定义在 stm32h7xx.h */

  73.         if (TIMx == TIM1) irq = TIM1_UP_TIM10_IRQn;
  74.         else if (TIMx == TIM2) irq = TIM2_IRQn;
  75.         else if (TIMx == TIM3) irq = TIM3_IRQn;
  76.         else if (TIMx == TIM4) irq = TIM4_IRQn;
  77.         else if (TIMx == TIM5) irq = TIM5_IRQn;
  78.         else if (TIMx == TIM6) irq = TIM6_DAC_IRQn;
  79.         else if (TIMx == TIM7) irq = TIM7_IRQn;
  80.         else if (TIMx == TIM8) irq = TIM8_UP_TIM13_IRQn;
  81.                 else if (TIMx == TIM9) irq = TIM1_BRK_TIM9_IRQn;
  82.         else if (TIMx == TIM10) irq = TIM1_UP_TIM10_IRQn;
  83.         else if (TIMx == TIM11) irq =  TIM1_TRG_COM_TIM11_IRQn;
  84.         else if (TIMx == TIM12) irq = TIM8_BRK_TIM12_IRQn;
  85.         else if (TIMx == TIM13) irq = TIM8_UP_TIM13_IRQn;
  86.         else if (TIMx == TIM14) irq = TIM8_TRG_COM_TIM14_IRQn;
  87.         else
  88.         {
  89.             Error_Handler(__FILE__, __LINE__);
  90.         }       
  91.         HAL_NVIC_SetPriority((IRQn_Type)irq, _PreemptionPriority, _SubPriority);
  92.         HAL_NVIC_EnableIRQ((IRQn_Type)irq);               
  93.         }
  94.        
  95.         HAL_TIM_Base_Start(&TimHandle);
  96. }
复制代码
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-14 03:04 , Processed in 0.046184 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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