IT评测·应用市场-qidao123.com

标题: STM32G474的HRTIM用作时基定时器 [打印本页]

作者: 丝    时间: 2024-8-23 12:38
标题: STM32G474的HRTIM用作时基定时器
STM32G474的HRTIM由7个定时器组成,分别是主定时器,定时器A,定时器B,定时器C,定时器D,定时器E和定时器F,每个定时器均可单独配置,独立工作。每个定时器都有1个独立的计数器和4个独立的比较器。
STM32G474的HRTIM用作定时器,通过对输入时钟计数,验证每个定时器是不是独立工作。理论再好,不如使用程序说明。搜索网络,少有人用。
1、HRTIM计数器的输入时钟频率
当系统时钟为170MHz时,则HRTIM的计数器的输入时钟频率为170*32=5,440MHz
pTimeBaseCfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
//HRTIM主定时器配置:HRTIM_MCR寄存器bit2:0(CKPSC[2:0])
//HRTIM定时器A控制寄存器配置:HRTIM_TIMxCR寄存器bit2:0(CKPSC[2:0])
//CKPSC[2:0]=000b,则“主定时器和定时器A”的输入时钟的分频值为1
//“主定时器和定时器A”分频后的输入时钟频率为:fHRCK=170 x 32 MHz = 5.44 GHz
2、测试程序
1)、HRTIM.c如下:
  1. #include "HRTIM.h"
  2. #include "delay.h"
  3. #include "LED.h"
  4. /*
  5. STM32G474的HRTIM由7个定时器组成,分别是主定时器,定时器A,定时器B,定时器C,定时器D,定时器E和定时器F;
  6. 每个定时器都有1个独立的计数器和4个独立的比较器;
  7. PA8映射到HRTIM1_CHA1,PA9映射到HRTIM1_CHA2,由定时器A控制,可用作输入捕获引脚,或者用作比较器输出引脚;
  8. PA10映射到HRTIM1_CHB1,PA11映射到HRTIM1_CHB2,由定时器B控制,可用作输入捕获引脚,或者用作比较器输出引脚;
  9. PB12映射到HRTIM1_CHC1,PB13映射到HRTIM1_CHC2,由定时器C控制,可用作输入捕获引脚,或者用作比较器输出引脚;
  10. PB14映射到HRTIM1_CHD1,PB15映射到HRTIM1_CHD2,由定时器D控制,可用作输入捕获引脚,或者用作比较器输出引脚;
  11. PC8映射到HRTIM1_CHE1,PC9映射到HRTIM1_CHE2,由定时器E控制,可用作输入捕获引脚,或者用作比较器输出引脚;
  12. PC6映射到HRTIM1_CHF1,PC7映射到HRTIM1_CHF2,由定时器A控制,可用作输入捕获引脚,或者用作比较器输出引脚;
  13. 时基定时器中断
  14. */
  15. uint32_t HRTIM_MASTER_cnt;
  16. uint32_t HRTIM_A_cnt;
  17. uint32_t HRTIM_B_cnt;
  18. void HRTIM_Init(void);
  19. void HRTIM_Init(void)
  20. {
  21.         HRTIM_HandleTypeDef  HRTIM1_structure;
  22.         HRTIM_TimeBaseCfgTypeDef   pTimeBaseCfg  = {0};//HRTIM定时器基本参数描述结构体
  23.        
  24.         __HAL_RCC_HRTIM1_CLK_ENABLE();
  25.         //设置RCC->APB2ENR寄存器bit16(HRTIM1EN),令HRTIM1EN=1,HRTIM1时钟使能,开启HRTIM1时钟
  26. 主定时器,定时器A,定时器B,定时器C,定时器D,定时器E和定时器F初始化开始///       
  27.   HRTIM1_structure.Instance = HRTIM1;                            //调用HRTIM1
  28.   HRTIM1_structure.Init.HRTIMInterruptResquests = HRTIM_IT_NONE; //No interrupt enabled
  29.   HRTIM1_structure.Init.SyncOptions = HRTIM_SYNCOPTION_NONE;     //HRTIM是否和外部定时器同步
  30.   HAL_HRTIM_Init(&HRTIM1_structure);
  31.         //初始化HRTIM1
  32.         //HRTIM1_structure.TimerParam[0].CaptureTrigger1=HRTIM_CAPTURETRIGGER_NONE
  33.         //HRTIM1_structure.TimerParam[0].CaptureTrigger2=HRTIM_CAPTURETRIGGER_NONE
  34.         //HRTIM1_structure.TimerParam[0].InterruptRequests=HRTIM_IT_NONE
  35.         //HRTIM1_structure.TimerParam[0].DMARequests=HRTIM_IT_NONE
  36.         //HRTIM1_structure.TimerParam[0].DMASrcAddress=0
  37.         //HRTIM1_structure.TimerParam[0].DMADstAddress
  38.         //HRTIM1_structure.TimerParam[0].DMASize=0
  39.         //直到HRTIM1_structure.TimerParam[6]
  40.         //HRTIM1_structure.State=HAL_HRTIM_STATE_READY
  41. 主定时器,定时器A,定时器B,定时器C,定时器D,定时器E和定时器F初始化开始///
  42.         pTimeBaseCfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
  43.         //HRTIM主定时器配置:HRTIM_MCR寄存器bit2:0(CKPSC[2:0])
  44.         //HRTIM定时器A控制寄存器配置:HRTIM_TIMxCR寄存器bit2:0(CKPSC[2:0])
  45.         //CKPSC[2:0]=000b,则“主定时器和定时器A”的输入时钟的分频值为1
  46.         //“主定时器和定时器A”分频后的输入时钟频率为:fHRCK=170 x 32 MHz = 5.44 GHz
  47.   pTimeBaseCfg.Mode = HRTIM_MODE_CONTINUOUS;//连续计数,周而复始
  48.         //HRTIM主定时器配置:HRTIM_MCR寄存器bit4:3(RETRIG:CONT)
  49.         //HRTIM定时器A控制寄存器配置:HRTIM_TIMxCR寄存器bit2:0(CKPSC[2:0])
  50.         //RETRIG=0,计时器不能重复触发:只有当计数器停止(周期已过去)时,才能进行计数器重置
  51.         //CONT=1,计时器在连续(自由运行)模式下运行,当它达到MPER值时滚转为零
  52.   pTimeBaseCfg.Period = MASTER_PERIOD;
  53.         //主定时器溢出周期为5us
  54.         //HRTIM主定时器周期配置:HRTIM_MPER寄存器bit15:0(MPER[15:0])
  55.         //HRTIM定时器A周期寄存器配置;HRTIM_PERxR寄存器bit15:0(PERx[15:0])
  56.   pTimeBaseCfg.RepetitionCounter = 9;//重复(9+1)个周期,发生1次中断
  57.         //HRTIM主定时器重复周期值配置:HRTIM_MREP寄存器bit7:0(MREP[7:0]),MREP[7:0]=0x00
  58.         //HRTIM定时器A重复周期值配置:HRTIM_REPxR寄存器bit7:0(MREP[7:0]),MREP[7:0]=0x00
  59.   HAL_HRTIM_TimeBaseConfig(&HRTIM1_structure, HRTIM_TIMERINDEX_MASTER, &pTimeBaseCfg);
  60.         //初始化HRTIM主定时器
  61.         HAL_NVIC_SetPriority(HRTIM1_Master_IRQn,3,0);
  62.         //“主定时器”抢占优先级为3,响应优先级为0
  63.         //设置NVIC中断分组4:4位抢占优先级,0位响应优先级
  64.         //选择中断优先级组4,即抢占优先级为4位,取值为0~15,响应优先级组为0位,取值为0
  65.   HAL_NVIC_EnableIRQ(HRTIM1_Master_IRQn);      //使能“主定时器”中断
  66.         HAL_HRTIM_SimpleBaseStart_IT(&HRTIM1_structure,HRTIM_TIMERINDEX_MASTER);
  67.         //启动主定时器
  68.   HRTIM_MASTER_cnt=0;
  69. /定时器A初始化开始//
  70.         pTimeBaseCfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
  71.         //HRTIM定时器A配置:HRTIM_MCR寄存器bit2:0(CKPSC[2:0])
  72.         //HRTIM定时器A控制寄存器配置:HRTIM_TIMxCR寄存器bit2:0(CKPSC[2:0])
  73.         //CKPSC[2:0]=000b,则“定时器A”的输入时钟的分频值为1
  74.         //“定时器A”分频后的输入时钟频率为:fHRCK=170 x 32 MHz = 5.44 GHz
  75.   pTimeBaseCfg.Mode = HRTIM_MODE_CONTINUOUS;//连续计数,周而复始
  76.         //HRTIM定时器A配置:HRTIM_MCR寄存器bit4:3(RETRIG:CONT)
  77.         //HRTIM定时器A控制寄存器配置:HRTIM_TIMxCR寄存器bit2:0(CKPSC[2:0])
  78.         //RETRIG=0,计时器不能重复触发:只有当计数器停止(周期已过去)时,才能进行计数器重置
  79.         //CONT=1,计时器在连续(自由运行)模式下运行,当它达到MPER值时滚转为零
  80.   pTimeBaseCfg.Period = TIM_A_PERIOD;
  81.         //HRTIM定时器A溢出周期为10us
  82.         //HRTIM定时器A周期配置:HRTIM_MPER寄存器bit15:0(MPER[15:0])
  83.         //HRTIM定时器A周期寄存器配置;HRTIM_PERxR寄存器bit15:0(PERx[15:0])
  84.   pTimeBaseCfg.RepetitionCounter = 9;//重复(9+1)个周期,发生1次中断
  85.         //HRTIM定时器A重复周期值配置:HRTIM_MREP寄存器bit7:0(MREP[7:0]),MREP[7:0]=0x00
  86.         //HRTIM定时器A重复周期值配置:HRTIM_REPxR寄存器bit7:0(MREP[7:0]),MREP[7:0]=0x00
  87.   HAL_HRTIM_TimeBaseConfig(&HRTIM1_structure, HRTIM_TIMERINDEX_TIMER_A, &pTimeBaseCfg);
  88.         //初始化HRTIM定时器A
  89.         __HAL_HRTIM_TIMER_ENABLE_IT(&HRTIM1_structure,HRTIM_TIMERINDEX_TIMER_A,HRTIM_TIM_IT_REP);
  90.         //使能“定时器A”重复中断
  91.         HAL_NVIC_SetPriority(HRTIM1_TIMA_IRQn,3,0);
  92.         //“定时器A”抢占优先级为3,响应优先级为0
  93.         //设置NVIC中断分组4:4位抢占优先级,0位响应优先级
  94.         //选择中断优先级组4,即抢占优先级为4位,取值为0~15,响应优先级组为0位,取值为0
  95.   HAL_NVIC_EnableIRQ(HRTIM1_TIMA_IRQn);      //使能“定时器A”中断
  96.         HAL_HRTIM_SimpleBaseStart_IT(&HRTIM1_structure,HRTIM_TIMERINDEX_TIMER_A);
  97.         //启动主定时器
  98.         HRTIM_A_cnt=0;
  99. /定时器B初始化开始//
  100.         pTimeBaseCfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
  101.         //HRTIM定时器B配置:HRTIM_MCR寄存器bit2:0(CKPSC[2:0])
  102.         //HRTIM定时器B控制寄存器配置:HRTIM_TIMxCR寄存器bit2:0(CKPSC[2:0])
  103.         //CKPSC[2:0]=000b,则“定时器B”的输入时钟的分频值为1
  104.         //“定时器B”分频后的输入时钟频率为:fHRCK=170 x 32 MHz = 5.44 GHz
  105.   pTimeBaseCfg.Mode = HRTIM_MODE_CONTINUOUS;//连续计数,周而复始
  106.         //HRTIM定时器B配置:HRTIM_MCR寄存器bit4:3(RETRIG:CONT)
  107.         //HRTIM定时器B控制寄存器配置:HRTIM_TIMxCR寄存器bit2:0(CKPSC[2:0])
  108.         //RETRIG=0,计时器不能重复触发:只有当计数器停止(周期已过去)时,才能进行计数器重置
  109.         //CONT=1,计时器在连续(自由运行)模式下运行,当它达到MPER值时滚转为零
  110.   pTimeBaseCfg.Period = TIM_B_PERIOD;
  111.         //HRTIM定时器B溢出周期为2us
  112.         //HRTIM定时器B周期配置:HRTIM_MPER寄存器bit15:0(MPER[15:0])
  113.         //HRTIM定时器B周期寄存器配置;HRTIM_PERxR寄存器bit15:0(PERx[15:0])
  114.   pTimeBaseCfg.RepetitionCounter = 9;//重复(9+1)个周期,发生1次中断
  115.         //HRTIM定时器B重复周期值配置:HRTIM_MREP寄存器bit7:0(MREP[7:0]),MREP[7:0]=0x00
  116.         //HRTIM定时器B重复周期值配置:HRTIM_REPxR寄存器bit7:0(MREP[7:0]),MREP[7:0]=0x00
  117.   HAL_HRTIM_TimeBaseConfig(&HRTIM1_structure, HRTIM_TIMERINDEX_TIMER_B, &pTimeBaseCfg);
  118.         //初始化HRTIM定时器B
  119.         __HAL_HRTIM_TIMER_ENABLE_IT(&HRTIM1_structure,HRTIM_TIMERINDEX_TIMER_B,HRTIM_TIM_IT_REP);
  120.         //使能“定时器B”重复中断
  121.         HAL_NVIC_SetPriority(HRTIM1_TIMB_IRQn,2,0);
  122.         //“定时器B”抢占优先级为3,响应优先级为0
  123.         //设置NVIC中断分组4:4位抢占优先级,0位响应优先级
  124.         //选择中断优先级组4,即抢占优先级为4位,取值为0~15,响应优先级组为0位,取值为0
  125.   HAL_NVIC_EnableIRQ(HRTIM1_TIMB_IRQn);      //使能“定时器B”中断
  126.         HAL_HRTIM_SimpleBaseStart_IT(&HRTIM1_structure,HRTIM_TIMERINDEX_TIMER_B);
  127.         //启动主定时器
  128.         HRTIM_B_cnt=0;
  129. }
  130. //函数功能:HRTIM的主定时器50us中断一次
  131. void HRTIM1_Master_IRQHandler(void)
  132. {
  133.         if((HRTIM1->sMasterRegs.MDIER & HRTIM_MASTER_IT_MREP) == HRTIM_MASTER_IT_MREP)
  134.         {//Timer repetition interrupt enable
  135.                 HRTIM1->sMasterRegs.MICR = HRTIM_MASTER_IT_MREP;
  136.                 //HRTIM_TIMxICR为TIMx中断清除寄存器
  137.                 //这里是将“定时器A”的HRTIM_TIMAICR的bit4(REPC),令REPC=1,清除重复中断标志位
  138.                 HRTIM_MASTER_cnt++;
  139.                 if(HRTIM_MASTER_cnt>20)//t=20*50us=1ms
  140.                 {
  141.                         HRTIM_MASTER_cnt=0;
  142.                   LED1_Toggle(); //LED1引脚输出电平翻转
  143.                 }
  144.         }
  145. }
  146. //函数功能:HRTIM的定时器A为100us中断一次
  147. void HRTIM1_TIMA_IRQHandler(void)
  148. {
  149.         if((HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].TIMxDIER & HRTIM_TIM_IT_REP) == HRTIM_TIM_IT_REP)
  150.         {//Timer repetition interrupt enable
  151.                 HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].TIMxICR = HRTIM_TIM_IT_REP;
  152.                 //HRTIM_TIMxICR为TIMx中断清除寄存器
  153.                 //这里是将“定时器A”的HRTIM_TIMAICR的bit4(REPC),令REPC=1,清除重复中断标志位
  154.           HRTIM_A_cnt++;
  155.           if(HRTIM_A_cnt>20)//t=20*100us=2ms
  156.           {
  157.                   HRTIM_A_cnt=0;
  158.                   LED2_Toggle(); //LED2引脚输出电平翻转
  159.           }
  160.         }
  161. }
  162. //函数功能:HRTIM的定时器B为20us中断一次
  163. void HRTIM1_TIMB_IRQHandler(void)
  164. {
  165.         if((HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].TIMxDIER & HRTIM_TIM_IT_REP) == HRTIM_TIM_IT_REP)
  166.         {//Timer repetition interrupt enable
  167.                 HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].TIMxICR = HRTIM_TIM_IT_REP;
  168.                 //HRTIM_TIMxICR为TIMx中断清除寄存器
  169.                 //这里是将“定时器B”的HRTIM_TIMAICR的bit4(REPC),令REPC=1,清除重复中断标志位
  170.           HRTIM_B_cnt++;
  171.           if(HRTIM_B_cnt>20)//t=20*20us=0.4ms
  172.           {
  173.                   HRTIM_B_cnt=0;
  174.                   LED3_Toggle(); //LED3引脚输出电平翻转
  175.           }
  176.         }
  177. }
复制代码
2)、HRTIM.h如下:
  1. #ifndef __HRTIM_H__
  2. #define __HRTIM_H__
  3. #include "stm32g4xx_hal.h"
  4. //#include "main.h"
  5. #define HRTIM_INPUT_CLOCK   170000000  //HRTIM的输入时钟频率为170MHz
  6. #define TIM_MASTER_FREQ     200000     //HRTIM主定时器中断频率为200KHz,周期为5us
  7. #define MASTER_PERIOD ((uint16_t)(((uint64_t)HRTIM_INPUT_CLOCK * 32) / TIM_MASTER_FREQ))
  8. //HRTIM主定时器周期:170000000*32/200000=27200,配置HRTIM主定时器中断频率为200KHz
  9. //HRTIM主定时器计数器输入时钟频率:170000000*32=5440000000Hz=5.440GHz
  10. //HRTIM主定时器计数器输入时钟周期:1/(170000000*32)=0.1838235294117647纳秒=183.8235294117647皮秒
  11. #define TIM_A_FREQ     100000     //HRTIM定时器A中断频率为100KHz,周期为10us
  12. #define TIM_A_PERIOD ((uint16_t)(((uint64_t)HRTIM_INPUT_CLOCK * 32) / TIM_A_FREQ))
  13. //HRTIM主定时器周期:170000000*32/200000=54400,配置HRTIM主定时器中断频率为100KHz
  14. #define TIM_B_FREQ     500000     //HRTIM定时器B中断频率为500KHz,周期为2us
  15. #define TIM_B_PERIOD ((uint16_t)(((uint64_t)HRTIM_INPUT_CLOCK * 32) / TIM_B_FREQ))
  16. //HRTIM主定时器周期:170000000*32/500000=1088,配置HRTIM主定时器中断频率为100KHz
  17. extern void HRTIM_Init(void);
  18. #endif /* __HRTIM_H */
复制代码
3)、LED.c如下
  1. #include "LED.h"
  2. void LED_Init(void);
  3. //函数功能:配置PC13为输出,无上拉或下拉,输出速度为5MHz
  4. void LED_Init(void)
  5. {
  6.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  7.   __HAL_RCC_GPIOC_CLK_ENABLE();                   //GPIOC时钟使能
  8.   GPIO_InitStruct.Pin = GPIO_PIN_13;              //选择引脚号码
  9.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;     //推挽输出模式
  10.         GPIO_InitStruct.Pull = GPIO_NOPULL;             //引脚上拉和下拉都没有被激活
  11. //        GPIO_InitStruct.Pull = GPIO_PULLUP;           //设置上拉
  12.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    //引脚的输出速度为5MHz
  13.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  14.         //根据GPIO_InitStruct结构变量指定的参数初始化GPIOC的外设寄存器
  15.         LED1_Off();
  16.   __HAL_RCC_GPIOB_CLK_ENABLE(); //使能PB端口的时钟
  17.   GPIO_InitStruct.Pin = GPIO_PIN_15;              //选择引脚号码
  18.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;     //推挽输出模式
  19.   GPIO_InitStruct.Pull = GPIO_PULLUP;             //设置上拉
  20.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    //引脚的输出速度为5MHz
  21.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  22.         LED2_Off();
  23.   __HAL_RCC_GPIOA_CLK_ENABLE(); //使能PA端口的时钟
  24.   GPIO_InitStruct.Pin = GPIO_PIN_0;              //选择引脚号码
  25.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;     //推挽输出模式
  26.   GPIO_InitStruct.Pull = GPIO_PULLUP;             //设置上拉
  27.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    //引脚的输出速度为5MHz
  28.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  29.         LED3_Off();
  30. }
复制代码
4)、LED.h如下
  1. #ifndef __LED_H__
  2. #define __LED_H__
  3. #include "stm32g4xx_hal.h"
  4. #define LED1_On()      HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET)  //输出低电平开灯
  5. #define LED1_Off()     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET)    //输出高电平关灯
  6. #define LED1_Toggle()  HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13)                //LED1引脚输出电平翻转
  7. #define LED2_On()      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET)  //输出低电平开灯
  8. #define LED2_Off()     HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET)    //输出高电平关灯
  9. #define LED2_Toggle()  HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_15)                //LED2引脚输出电平翻转
  10. #define LED3_On()      HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET)  //输出低电平开灯
  11. #define LED3_Off()     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET)    //输出高电平关灯
  12. #define LED3_Toggle()  HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_0)                //LED3引脚输出电平翻转
  13. extern void LED_Init(void);
  14. #endif /*__ GPIO_H__ */
复制代码
3、测试结果



颠末测试, 发现主定时器,定时器A和定时器B,在用作时基定时器时,它们是独立工作的,由此可知,定时器C,定时器D,定时器E和定时器F也是可以独立工作的。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4