• PY32F003F18之输入捕获


    输入捕获是定时器的功能之一,配合外部引脚,捕获脉宽时间或采集周期。

    CPU中的定时器最基本的功能就是计数功能,其次是输入捕获(IC),再次就是比较输出(OC),还有就是使用引脚对外部时钟进行计数,触发信号捕捉等。

    1、输入捕获功能图:

    2、测试程序

    1. #include "TIM1_EdgeAligned_InputCapture.h"
    2. #include "LED.h"
    3. /*
    4. 将PA3复用为TIM1_CH1,用作捕获信号输入引脚,
    5. PA4为TIM3中断时输出的信号,将这两个脚短接,使用示波器跟踪PA0的信号,就可以测试。
    6. */
    7. void TIM1_COUNTERMODE_UP_IC1_Init(uint16_t arr,uint16_t psc);
    8. void TIM3_COUNTERMODE_UP_Init(uint16_t arr,uint16_t psc);
    9. void HAL_TIM_IC_MspInit1(TIM_HandleTypeDef *htim)
    10. {
    11. GPIO_InitTypeDef GPIO_InitStructure;
    12. if(htim->Instance == TIM1)//初始化TIM1
    13. {
    14. __HAL_RCC_TIM1_CLK_ENABLE(); //使能TIM1时钟
    15. __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
    16. GPIO_InitStructure.Pin = GPIO_PIN_3; //选择第3脚,PA3是为TIM1_CH1
    17. GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    18. GPIO_InitStructure.Pull = GPIO_PULLUP; //引脚上拉被激活
    19. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    20. GPIO_InitStructure.Alternate = GPIO_AF13_TIM1;//选择AF13,将PA3引脚复用为TIM1_CH1
    21. HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
    22. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    23. //将PA3初始化为TIM1_CH1功能,用作IC11输入捕获引脚
    24. HAL_NVIC_SetPriority(TIM1_CC_IRQn,1, 0); //设置"捕获/比较"的中断优先级为1
    25. HAL_NVIC_EnableIRQ(TIM1_CC_IRQn); //开启"捕获/比较"总中断
    26. }
    27. if(htim->Instance == TIM3)//初始化TIM3
    28. {
    29. }
    30. }
    31. //函数功能:TIM1中基本计数功能,并使能了更新中断,每次重装ARR值时会产生一次更新中断
    32. //arr:自动重装值。
    33. //psc:时钟预分频数
    34. //TIM1_COUNTERMODE_UP_IC1_Init(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
    35. //TIM1_COUNTERMODE_UP_IC1_Init(20000,80);//若使用HSI,当arr=20000,psc=80时,则为200ms,误差为10us;
    36. void TIM1_COUNTERMODE_UP_IC1_Init(uint16_t arr,uint16_t psc)
    37. {
    38. GPIO_InitTypeDef GPIO_InitStructure;
    39. TIM_HandleTypeDef TIM1_HandleStructure;
    40. TIM_IC_InitTypeDef TIM1_IC_InitStructure;
    41. //HAL_TIM_IC_MspInit开始/
    42. __HAL_RCC_TIM1_CLK_ENABLE(); //使能TIM1时钟
    43. __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
    44. GPIO_InitStructure.Pin = GPIO_PIN_3; //选择第3脚,PA3是为TIM1_CH1
    45. GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    46. GPIO_InitStructure.Pull = GPIO_PULLUP; //引脚上拉被激活
    47. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    48. GPIO_InitStructure.Alternate = GPIO_AF13_TIM1;//选择AF13,将PA3引脚复用为TIM1_CH1
    49. HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
    50. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    51. //将PA3初始化为TIM1_CH1功能,用作IC11输入捕获引脚
    52. HAL_NVIC_SetPriority(TIM1_CC_IRQn,1, 0); //设置"捕获/比较"的中断优先级为1
    53. HAL_NVIC_EnableIRQ(TIM1_CC_IRQn); //开启"捕获/比较"总中断
    54. //HAL_TIM_IC_MspInit结束/
    55. TIM1_HandleStructure.Instance = TIM1; //选择TIM1
    56. TIM1_HandleStructure.Init.Period = arr-1;
    57. //设置在下一个更新事件产生时,装入"自动重载入寄存器TIMx_ARR"的值
    58. //将(arr-1)写入"自动重载入寄存器TIMx_ARR",设置自动重装载值
    59. TIM1_HandleStructure.Init.Prescaler = psc-1;
    60. //设置用来作为TIMx时钟频率除数的预分频值
    61. //将(psc-1)写入"预装载寄存器TIMx_PSC",的PSC[15:0],设置预分频值
    62. //计数器的时钟频率CK_CNT=fCK_PSC/(PSC[15:0]+1)
    63. TIM1_HandleStructure.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;//时钟不分频,则tDTS=tCK_INT
    64. //若使用HSE,计算公式:arr*psc/24000000/1,当arr=20000,psc=240时,则为200ms,误差为10us;
    65. //若使用HSI,计算公式:arr*psc/8000000/1,当arr=20000,psc=80时,则为200ms,误差为100us;
    66. TIM1_HandleStructure.Init.CounterMode = TIM_COUNTERMODE_UP;//向上计数
    67. TIM1_HandleStructure.Init.RepetitionCounter = 1 - 1;
    68. //不重复计数
    69. //将(1-1)写入"重复计数寄存器TIMx_RCR"中的REP[7:0],设置"重复计数器值"
    70. TIM1_HandleStructure.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    71. //"自动重装载寄存器"没有缓冲
    72. //不允许将"TIMx自动重新加载寄存器TIMx_ARR"的值被装入缓冲区;
    73. HAL_TIM_Base_Init(&TIM1_HandleStructure); //TIM1初始化
    74. //选择计数器模式:向上计数
    75. //设置时钟分频因子:时钟不分频,则tDTS=tCK_INT
    76. //设置自动重装载:"自动重装载寄存器"没有缓冲
    77. //设置自动重装载值:TIM_Base_InitStructure.Period
    78. //设置预分频值:TIM_Base_InitStructure.Prescaler
    79. //设置"重复计数器值":TIM_Base_InitStructure.RepetitionCounter
    80. //启动更新事件:将TIMx_EGR中的UG位置1,由软件产生更新事件
    81. TIM1_IC_InitStructure.ICPolarity = TIM_ICPOLARITY_RISING; //上升沿捕获
    82. TIM1_IC_InitStructure.ICSelection = TIM_ICSELECTION_DIRECTTI;//CC1通道配置为输入
    83. TIM1_IC_InitStructure.ICPrescaler = TIM_ICPSC_DIV1; //输入不分频
    84. TIM1_IC_InitStructure.ICFilter = 0; //输入无滤波
    85. HAL_TIM_IC_ConfigChannel(&TIM1_HandleStructure, &TIM1_IC_InitStructure, TIM_CHANNEL_1);
    86. //配置通道1输入捕获
    87. HAL_TIM_IC_Start_IT(&TIM1_HandleStructure, TIM_CHANNEL_1);
    88. //使能输入捕获1中断,使能输入捕获1通道
    89. }
    90. //函数功能:TIM3中基本计数功能,并使能了更新中断,每次重装ARR值时会产生一次更新中断
    91. //arr:自动重装值。
    92. //psc:时钟预分频数
    93. //TIM3_COUNTERMODE_UP_Init(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
    94. //TIM3_COUNTERMODE_UP_Init(20000,80);//若使用HSI,当arr=20000,psc=80时,则为200ms,误差为10us;
    95. void TIM3_COUNTERMODE_UP_Init(uint16_t arr,uint16_t psc)
    96. {
    97. TIM_HandleTypeDef TIM3_HandleStructure;
    98. //HAL_TIM_Base_MspInit开始/
    99. __HAL_RCC_TIM3_CLK_ENABLE(); //使能TIM3时钟
    100. HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0); //设置中断优先级
    101. HAL_NVIC_EnableIRQ(TIM3_IRQn); //使能TIM3中断
    102. //HAL_TIM_Base_MspInit开始/
    103. TIM3_HandleStructure.Instance = TIM3; //选择TIM3
    104. TIM3_HandleStructure.Init.Period = arr-1;
    105. //设置在下一个更新事件产生时,装入"自动重载入寄存器TIMx_ARR"的值
    106. //将(arr-1)写入"自动重载入寄存器TIMx_ARR",设置自动重装载值
    107. TIM3_HandleStructure.Init.Prescaler = psc-1;
    108. //设置用来作为TIMx时钟频率除数的预分频值
    109. //将(psc-1)写入"预装载寄存器TIMx_PSC",的PSC[15:0],设置预分频值
    110. //计数器的时钟频率CK_CNT=fCK_PSC/(PSC[15:0]+1)
    111. TIM3_HandleStructure.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;//时钟不分频,则tDTS=tCK_INT
    112. //若使用HSE,计算公式:arr*psc/24000000/1,当arr=20000,psc=240时,则为200ms,误差为10us;
    113. //若使用HSI,计算公式:arr*psc/8000000/1,当arr=20000,psc=80时,则为200ms,误差为100us;
    114. TIM3_HandleStructure.Init.CounterMode = TIM_COUNTERMODE_UP;//向上计数
    115. TIM3_HandleStructure.Init.RepetitionCounter = 1 - 1;
    116. //不重复计数
    117. //将(1-1)写入"重复计数寄存器TIMx_RCR"中的REP[7:0],设置"重复计数器值"
    118. TIM3_HandleStructure.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    119. //"自动重装载寄存器"没有缓冲
    120. //不允许将"TIMx自动重新加载寄存器TIMx_ARR"的值被装入缓冲区;
    121. HAL_TIM_Base_Init(&TIM3_HandleStructure); //TIM3初始化
    122. //选择计数器模式:向上计数
    123. //设置时钟分频因子:时钟不分频,则tDTS=tCK_INT
    124. //设置自动重装载:"自动重装载寄存器"没有缓冲
    125. //设置自动重装载值:TIM_Base_InitStructure.Period
    126. //设置预分频值:TIM_Base_InitStructure.Prescaler
    127. //设置"重复计数器值":TIM_Base_InitStructure.RepetitionCounter
    128. //启动更新事件:将TIMx_EGR中的UG位置1,由软件产生更新事件
    129. HAL_TIM_Base_Start_IT(&TIM3_HandleStructure);
    130. //允许计数器产生"更新中断";
    131. //如果计数器不是工作在触发模式中,则开始计数
    132. }
    133. //函数功能:TIM1输入捕获中断服务程序
    134. //IC1为上升沿捕获,所以捕获周期是TIM3周期的2
    135. void TIM1_CC_IRQHandler(void)
    136. {
    137. HAL_TIM_PeriodElapsedCallback开始/
    138. if (_HAL_TIM_GET_FLAG(TIM1,TIM_FLAG_CC1) != RESET)
    139. {//根据TIM_FLAG_CC1,读"TIMx状态寄存器(TIMx_SR)"中输入捕获中断标志位
    140. _HAL_TIM_CLEAR_IT(TIM1, TIM_IT_CC1);
    141. //TIM_IT_CC1,令CC1IF=0,清除输入捕获中断标志位
    142. TIM1_LED_Toggle();
    143. }
    144. HAL_TIM_PeriodElapsedCallback结束/
    145. }
    146. //函数功能:TIM3中断服务程序
    147. void TIM3_IRQHandler(void)
    148. {
    149. HAL_TIM_PeriodElapsedCallback开始/
    150. if (_HAL_TIM_GET_FLAG(TIM3,TIM_FLAG_UPDATE) != RESET)
    151. {//根据TIM_FLAG_UPDATE,读"TIMx状态寄存器(TIMx_SR)"中更新中断标志位
    152. _HAL_TIM_CLEAR_IT(TIM3, TIM_IT_UPDATE);
    153. //TIM_IT_UPDATE,令UIF=0,清除定时器更新中断标志位
    154. TIM3_LED_Toggle();
    155. }
    156. HAL_TIM_PeriodElapsedCallback结束/
    157. }

    1. #ifndef __TIM1_EdgeAligned_InputCapture_H
    2. #define __TIM1_EdgeAligned_InputCapture_H
    3. #include "py32f0xx_hal.h"
    4. #define _HAL_TIM_GET_FLAG(__INSTANCE__, __FLAG__) (((__INSTANCE__)->SR &(__FLAG__)) == (__FLAG__))
    5. //根据__FLAG__,读"TIMx状态寄存器(TIMx_SR)"中相应的中断标志位
    6. //TIM_FLAG_UPDATE,若UIF=1,建立"更新事件"
    7. //TIM_FLAG_CC1,若CC1IF=1,如果通道CC1配置为输出模式,则建立"CC1输出事件"
    8. //TIM_FLAG_CC1,若CC1IF=1,如果通道CC1配置为输入模式,则建立"CC1捕获事件"
    9. //TIM_FLAG_CC2,若CC2IF=1,如果通道CC2配置为输出模式,则建立"CC2输出事件"
    10. //TIM_FLAG_CC2,若CC2IF=1,如果通道CC2配置为输入模式,则建立"CC2捕获事件"
    11. //TIM_FLAG_CC3,若CC3IF=1,如果通道CC3配置为输出模式,则建立"CC3输出事件"
    12. //TIM_FLAG_CC3,若CC3IF=1,如果通道CC3配置为输入模式,则建立"CC3捕获事件"
    13. //TIM_FLAG_CC4,若CC4IF=1,如果通道CC4配置为输出模式,则建立"CC4输出事件"
    14. //TIM_FLAG_CC4,若CC4IF=1,如果通道CC4配置为输入模式,则建立"CC4捕获事件"
    15. //TIM_FLAG_COM,若COMIF=1,则建立"COM事件"
    16. //TIM_FLAG_TRIGGER,若TIF=1,则建立"触发事件"
    17. //TIM_FLAG_BREAK,若BIF=1,则建立"刹车事件"
    18. //TIM_FLAG_CC1OF,若CC1OF=1,则表示"计数器x的值被捕获到TIMx_CCR1寄存器"
    19. //TIM_FLAG_CC2OF,若CC2OF=1,则表示"计数器x的值被捕获到TIMx_CCR2寄存器"
    20. //TIM_FLAG_CC3OF,若CC3OF=1,则表示"计数器x的值被捕获到TIMx_CCR3寄存器"
    21. //TIM_FLAG_CC4OF,若CC4OF=1,则表示"计数器x的值被捕获到TIMx_CCR4寄存器"
    22. #define _HAL_TIM_CLEAR_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SR = ~(__INTERRUPT__))
    23. //根据__INTERRUPT__,将"TIMx状态寄存器(TIMx_SR)"中相应的中断标志位置0
    24. //TIM_IT_UPDATE,令UIF=0,清除定时器更新中断标志位
    25. //TIM_IT_CC1,令CC1IF=0,清除捕获/比较1中断标志位
    26. //TIM_IT_CC2,令CC2IF=0,清除捕获/比较2中断标志位
    27. //TIM_IT_CC3,令CC3IF=0,清除捕获/比较3中断标志位
    28. //TIM_IT_CC4,令CC4IF=0,清除捕获/比较4中断标志位
    29. //TIM_IT_COM,令COMIF=0,清除COM事件中断标志位
    30. //TIM_IT_TRIGGER,令TIF=0,清除触发中断标志位
    31. //TIM_IT_BREAK,令BIF=0,清除刹车中断标志位
    32. extern void TIM1_COUNTERMODE_UP_IC1_Init(uint16_t arr,uint16_t psc);
    33. extern void TIM3_COUNTERMODE_UP_Init(uint16_t arr,uint16_t psc);
    34. #endif /* __TIM1_EdgeAligned_InputCapture_H */
    1. #include "py32f0xx_hal.h"
    2. #include "SystemClock.h"
    3. #include "delay.h"
    4. #include "LED.h"
    5. #include "TIM1_EdgeAligned_InputCapture.h"
    6. int main(void)
    7. {
    8. HSE_Config();
    9. // HAL_Init();//systick初始化
    10. delay_init();
    11. HAL_Delay(1000);
    12. TIM1_LED_Init();
    13. TIM3_LED_Init();
    14. TIM1_COUNTERMODE_UP_IC1_Init(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
    15. TIM3_COUNTERMODE_UP_Init(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
    16. while (1)
    17. {
    18. delay_ms(100);
    19. // TIM1_LED_Toggle();
    20. // TIM3_LED_Toggle();
    21. }
    22. }
    1. #include "LED.h"
    2. void TIM1_LED_Init(void);
    3. void TIM3_LED_Init(void);
    4. //函数功能:TIM1_LED灯引脚初始化,并配置为关灯
    5. void TIM1_LED_Init(void)
    6. {
    7. GPIO_InitTypeDef GPIO_InitStructure;
    8. __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟
    9. //初始化PA0
    10. GPIO_InitStructure.Pin = GPIO_PIN_0; //选择第0
    11. GPIO_InitStructure.Pull = GPIO_PULLUP; //引脚上拉被激活
    12. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //配置GPIO速度为极高
    13. GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //设置引脚工作模式为推挽输出方式
    14. HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
    15. //根据GPIO_InitStructure结构变量指定的参数初始化GPIOA的外设寄存器
    16. TIM1_LED_Off();
    17. }
    18. //函数功能:TIM3_LED灯引脚初始化,并配置为关灯
    19. void TIM3_LED_Init(void)
    20. {
    21. GPIO_InitTypeDef GPIO_InitStructure;
    22. __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟
    23. //初始化PB5
    24. GPIO_InitStructure.Pin = GPIO_PIN_4; //选择第4
    25. GPIO_InitStructure.Pull = GPIO_PULLUP; //引脚上拉被激活
    26. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //配置GPIO速度为极高
    27. GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //设置引脚工作模式为推挽输出方式
    28. HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
    29. //根据GPIO_InitStructure结构变量指定的参数初始化GPIOA的外设寄存器
    30. TIM3_LED_Off();
    31. }

    将PA3复用为TIM1_CH1,用作捕获信号输入引脚,PA4为TIM3中断时输出的信号,将这两个脚短接,使用示波器跟踪PA0的信号,就可以测试。

  • 相关阅读:
    从 Hadoop 迁移,无需淘汰和替换
    LVS负载均衡集群
    vue 学习
    【论文笔记】LoRA LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS
    《对比Excel,轻松学习Python数据分析》读书笔记------数据分组与数据透视表
    JavaEE中的Lambda表达式与方法引用的使用
    使用Python实现多线程、多进程、异步IO的socket通信
    mac 打不开 idea 或者 pycharm 的方法
    一、K近邻算法K-NN(有监督学习)
    【SA8295P 源码分析 (三)】97 - QNX AIS Camera 框架介绍 及 Camera 工作流程分析
  • 原文地址:https://blog.csdn.net/weixin_42550185/article/details/132927553