通用定时器-同时测量PWM周期和占空比-寄存器&HAL库实现
使用到的相关寄存器
CC1S



TS



相关寄存器设置代码
配置通道为输入并映射正确通道
/* 4. CH1通道配置为输入,并IC1映射到TI1上:CCMR1_CC1S=01 */
TIM4->CCMR1 &= ~TIM_CCMR1_CC1S_1;
TIM4->CCMR1 |= TIM_CCMR1_CC1S_0;
/* 4.1 把IC2映射到TI1上: CCMR1_CC2S=10*/
TIM4->CCMR1 |= TIM_CCMR1_CC2S_1;
TIM4->CCMR1 &= ~TIM_CCMR1_CC2S_0;配置从模式控制器
/* 11. 必须配置从模式控制器为复位模式 SMS=100, 触发输入信号为:TI1FP1 TS=101*/
TIM4->SMCR |= TIM_SMCR_TS_2;
TIM4->SMCR &= ~TIM_SMCR_TS_1;
TIM4->SMCR |= TIM_SMCR_TS_0;
TIM4->SMCR |= TIM_SMCR_SMS_2;
TIM4->SMCR &= ~(TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0);寄存器代码实现
TIM4.h
#ifndef __TIM4_H
#define __TIM4_H
#include "stm32f10x.h"
void TIM4_Init(void);
// 将定时器的开关包装成函数
void TIM4_Start(void);
void TIM4_Stop(void);
// 获取输入信号周期的函数
double TIM4_GetPWMCycle(void);
double TIM4_GetPWMFreq(void);
double TIM4_GetPWMDutyCycle(void);
#endifTIM4.c
#include "tim4.h"
void TIM4_Init(void)
{
// 1. 开启时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
// 2. GPIO工作模式,PB6:浮空输入 CNF-01,MODE-00
GPIOB->CRL &= ~GPIO_CRL_MODE6;
GPIOB->CRL &= ~GPIO_CRL_CNF6_1;
GPIOB->CRL |= GPIO_CRL_CNF6_0;
// 定时器配置
// 3. 时基部分
// 3.1 预分频值 71,得到1MHz
TIM4->PSC = 71;
// 3.2 重装载值,65535,尽量在信号一个周期内不要产生溢出
TIM4->ARR = 65535;
// 3.3 计数方向
TIM4->CR1 &= ~TIM_CR1_DIR;
// 4. 输入通道部分
// 4.1 TI1的输入选择
TIM4->CR2 &= ~TIM_CR2_TI1S;
// 4.2 输入滤波器
TIM4->CCMR1 &= ~TIM_CCMR1_IC1F;
// 4.3 配置极性:上升沿触发
TIM4->CCER &= ~TIM_CCER_CC1P;
// 通道2:下降沿触发
TIM4->CCER |= TIM_CCER_CC2P;
// 4.4 选择通道1的输入映射为 TI1:CC1S - 01
TIM4->CCMR1 &= ~TIM_CCMR1_CC1S_1;
TIM4->CCMR1 |= TIM_CCMR1_CC1S_0;
// 选择通道2的输入映射为 TI1:CC2S - 10
TIM4->CCMR1 |= TIM_CCMR1_CC2S_1;
TIM4->CCMR1 &= ~TIM_CCMR1_CC2S_0;
// 4.5 预分频器
TIM4->CCMR1 &= ~TIM_CCMR1_IC1PSC;
TIM4->CCMR1 &= ~TIM_CCMR1_IC2PSC;
// 4.6 配置触发输入信号TRGI TS - 101
TIM4->SMCR |= TIM_SMCR_TS_2;
TIM4->SMCR &= ~TIM_SMCR_TS_1;
TIM4->SMCR |= TIM_SMCR_TS_0;
// 4.7 配置从模式为复位模式 SMS - 100
TIM4->SMCR |= TIM_SMCR_SMS_2;
TIM4->SMCR &= ~TIM_SMCR_SMS_1;
TIM4->SMCR &= ~TIM_SMCR_SMS_0;
// 4.6 通道1输入捕获使能
TIM4->CCER |= TIM_CCER_CC1E;
// 通道2输入捕获使能
TIM4->CCER |= TIM_CCER_CC2E;
}
// 将定时器的开关包装成函数
void TIM4_Start(void)
{
TIM4->CR1 |= TIM_CR1_CEN;
}
void TIM4_Stop(void)
{
TIM4->CR1 &= ~TIM_CR1_CEN;
}
// cycle单位为us,返回周期单位为ms
double TIM4_GetPWMCycle(void)
{
return TIM4->CCR1 / 1000.0;
}
double TIM4_GetPWMFreq(void)
{
return 1000000.0 / TIM4->CCR1;
}
double TIM4_GetPWMDutyCycle(void)
{
return TIM4->CCR2 * 1.0 / TIM4->CCR1;
}main.c
#include "usart.h"
#include "tim5.h"
#include "tim4.h"
#include "delay.h"
int main(void)
{
// 初始化
USART_Init();
TIM4_Init();
TIM5_Init();
printf("Hello, world!\n");
// 开启定时器
TIM5_Start();
TIM4_Start();
TIM5_SetDutyCycle(78);
while (1)
{
printf("T = %.2f ms, f = %.2f Hz, duty = %.2f %%\n",
TIM4_GetPWMCycle(), TIM4_GetPWMFreq(), TIM4_GetPWMDutyCycle() * 100);
Delay_ms(1000);
}
}HAL库代码实现
软件设置

tim.c 添加代码
/* USER CODE BEGIN 1 */
/* 返回PWM的周期 ms*/
double Driver_TIM4_GetPWMCycle(void)
{
// return TIM4->CCR1 / 1000.0;;
return (__HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_1) + 1) / 1000.0;
}
/* 返回PWM的频率 */
double Driver_TIM4_GetPWMFreq(void)
{
// return 1000000.0 / TIM4->CCR1;
return 1000000.0 / (__HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_1) + 1);
}
// 返回占空比
double Driver_TIM4_GetDutyCycle(void)
{
// return TIM4->CCR2 * 1.0 / TIM4->CCR1;
return (1 + __HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_2)) * 1.0 / (1 + __HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_1));
}
/* USER CODE END 1 */main函数代码
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM4_Init();
MX_TIM5_Init();
MX_USART1_UART_Init();
HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_2);
HAL_TIM_IC_Start(&htim4, TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim4, TIM_CHANNEL_2);
double t, f, dutyCycle;
while (1)
{
t = Driver_TIM4_GetPWMCycle();
f = Driver_TIM4_GetPWMFreq();
dutyCycle = Driver_TIM4_GetDutyCycle();
printf("t=%.4fms, f=%.4fHz, dutyCycle=%.2f%%\r\n", t, f, dutyCycle * 100); // 40%
HAL_Delay(1000);
}
}