首先选择外部晶振:
配置时钟频率:
选择使用的定时器:
根据内部原理图:
这里以TIM_CH1为例,当从CH1输入一个PWM波,通过输入滤波后将会产生两路信号:tim_ti1fp1 & tim_ti1fp2,分别送至tim_ic1 & tim_ic2,也就是说一个TI信号将会被映射成两路的IC信号,所以可以通过进行边沿检测来测量PWM的频率以及占空比。
具体步骤如下:
1、设置定时器Slave Mode为Reset Mode,也就是当检测到上升沿时,定时器复位;
2、PWM由CH1进入,触发源设置为TI1FP1,并设置IC1为上升沿捕获;
3、当第一次捕获到上升沿时,定时器复位,计数寄存器CNT清零;
4、当IC2捕获到下降沿时,计数器CNT的值将会被存到捕获寄存器CCR2中;
5、当IC1再次捕获到上升沿时,计数器CNT的值将会被存到捕获寄存器CCR1中,同时将定时器复位;
因此,CCR1的值就是周期,CCR2的值就是占空比。
配置如下:
通道1设置为直接模式,通道2设置为间接模式。
而最终计算得到的频率值 = 分频后得到的时钟频率 / 上升沿个数
= ( 定时器时钟频率 / 预分频系数 )/ 上升沿个数 ;
最终计算的到的占空比 = 下降沿个数 / 上升沿个数;
值得注意的是:要明确输入PWM波的大致范围,因为需要根据PWM波范围来确定预分频系数;比如说输入一个频率大概为50Hz,占空比为10%的PWM波,需要将预分频系数稍微设置大一些;(这是因为:定时器所能测量到的最小频率 = 定时器频率 / ( 预分频系数 * 自动重载值 ),而因为ARR(Auto-Reload-Register)是一个十六位寄存器,其最大值为65536,所以当需要测量的频率值较小时,必须要将预分频系数设为较大值)
以本次使用定时器TIM3为例,其时钟频率已配置为84MHz,再配置PSC(Prescaler)为(8400-1),因此,最终频率 = ( 84000000 / 8400 )/ PWM_RisingCount;
参数配置:
再打开定时器中断:
配置NVIC(Nested Vector Interrupt Controller):
代码:
1、全局变量以及主函数
/* USER CODE BEGIN 0 */
uint16_t PWM_RisingCount;
uint16_t PWM_FallingCount;
float duty;
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//每1秒输出一次
HAL_Delay(1000);
//这里的10000就是由定时器频率84000000/预分频系数8400 得到
printf("PWM_Frequency = %d \r\n",(uint16_t)10000/PWM_RisingCount);
printf("PWM_Duty = %.2f %% \r\n",duty * 100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
2、输入捕获中断回调函数
/* USER CODE BEGIN 4 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
//注意这里为HAL_TIM_ACTIVE_CHANNEL_1而不是TIM_CHANNEL_1
{
PWM_RisingCount = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
duty = (float)PWM_FallingCount / PWM_RisingCount;
}
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
PWM_FallingCount = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
}
}
/* USER CODE END 4 */
最终结果如下:
(输入为另一块STM32产生的PWM波,频率为50Hz,占空比为5%,可以看到有些许误差,这是因为没有进行滤波的缘故)