You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
6.2 KiB
220 lines
6.2 KiB
## PWM
|
|
介绍了 STM32 的通用定时器 TIM3,用该定时器的中断来控制 DS1 的闪烁
|
|
|
|
TIM3_REMAP[1:0]重映射控制表, 查对应的引脚
|
|
|
|
TIM3_CH2 部分重映射可以对应 PB5, PB5 对应红色LED
|
|
|
|
### 配置
|
|
|
|
TIM_HandleTypeDef htim6;
|
|
三个结构体
|
|
TIM_ClockConfigTypeDef sClockSourceConfig = {0}; // 时钟源
|
|
TIM_MasterConfigTypeDef sMasterConfig = {0}; // 触发器模式
|
|
TIM_OC_InitTypeDef sConfigOC = {0}; //输出比较
|
|
|
|
|
|
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
|
sConfigOC.Pulse = 0;
|
|
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
|
|
sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
|
|
|
|
HAL_TIM_MspPostInit 可以候补配置使用的GPIO
|
|
#### 定义引脚 MspPostInit
|
|
|
|
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
|
|
|
|
```C
|
|
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
|
|
{
|
|
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
if(timHandle->Instance==TIM3)
|
|
{
|
|
/* USER CODE BEGIN TIM3_MspPostInit 0 */
|
|
|
|
/* USER CODE END TIM3_MspPostInit 0 */
|
|
|
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
|
/**TIM3 GPIO Configuration
|
|
PB5 ------> TIM3_CH2
|
|
*/
|
|
GPIO_InitStruct.Pin = PWM_TIM3_CH2_Pin;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
|
HAL_GPIO_Init(PWM_TIM3_CH2_GPIO_Port, &GPIO_InitStruct);
|
|
|
|
// __HAL_AFIO_REMAP_TIM3_PARTIAL(); // 部分重映射
|
|
// __HAL_AFIO_REMAP_TIM3_ENABLE(); // 完全映射
|
|
/* USER CODE BEGIN TIM3_MspPostInit 1 */
|
|
|
|
/* USER CODE END TIM3_MspPostInit 1 */
|
|
}
|
|
|
|
}
|
|
```
|
|
|
|
#### 时间计算
|
|
https://blog.csdn.net/weixin_44453694/article/details/122351580
|
|
设置分频系数为72,重装载值为500, 1us
|
|
自动重装载
|
|
|
|
PWM
|
|
mode: PWM1 : CNT << CCR 为有效电平
|
|
pulse: 0 占空比 这里设置为200,则占空比为200/500(重装载值为)
|
|
output compare preload: 输出比较装载使能
|
|
Fastmode : Enable
|
|
CH Polarity: Low 低电平有效
|
|
|
|
参数说明
|
|
Input capture direct mode 输入捕获直接模式
|
|
Input capture indirectmode 输入捕获间接模式
|
|
Input capture triggered by TRC 输入捕获触发器模式
|
|
Output compare no output 输出比较(冻结模式000 )
|
|
Output compare CH3 输出比较(001)
|
|
PWM Generation No output PWM产生无输出
|
|
PWM Generation CH3 PWM输出到CH3
|
|
CH3 Combined channels 联合通道
|
|
xor activation 定时器输入异或模式
|
|
|
|
启动通道 PostMSP
|
|
HAL_TIM_PWM_Start(timHandle,TIM_CHANNEL_3);//启动通道3
|
|
HAL_TIM_PWM_Start(timHandle,TIM_CHANNEL_4);//启动通道4
|
|
|
|
TIM1 TIM8 可以在cubemx 看到互补引脚
|
|
|
|
#### CCRx
|
|
在向上计数 PWM模式,
|
|
且当 CNT<CCRx 时,输出 0,当 CNT>=CCRx 时输出 1
|
|
|
|
所以:
|
|
当 CNT 值小于 CCRx 的时候, 输出低电平,
|
|
当 CNT 值大于等于 CCRx 的时候, 输出高电平,
|
|
当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数。
|
|
改变 CCRx 的值,就可以改变 PWM 输出的占空比
|
|
改变 ARR 的值,就可以改变 PWM 输出的频率
|
|
|
|
|
|
#### 输出模式
|
|
|
|
输出模式 : 不可以改变频率,改变 pulse
|
|
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,pwm_num); //设置pwm函数 Pulse 值
|
|
比较输出模式 : 可以改变频率, 改变 ARR 自动重装载值
|
|
|
|
|
|
### 捕获 CAP
|
|
输入捕获模式可以用来测量脉冲宽度或者测量频率。 捕获电平上升或下降沿中断
|
|
中间可能会有溢出, 需要配置溢出中断
|
|
|
|
HAL_TIM_Base_Start_IT(&htim5); // 开启中断
|
|
HAL_TIM_IC_Start_IT(&htim5, TIM_CHANNEL_1); // 开启捕获中断
|
|
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //溢出回调
|
|
|
|
捕获回调
|
|
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
|
|
{
|
|
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);//点灯
|
|
}
|
|
***通过分频,设置为1us***
|
|
|
|
|
|
```C
|
|
|
|
// 参考例程
|
|
//可以写在主函数,也可以在time.c
|
|
/*
|
|
sta当前的捕获状态:
|
|
[14]0x4000 =1表示捕获到了上升沿 现在待测量是高电平
|
|
[15]0x8000 =1表示捕获到了下降沿 现在待测量是低电平,此时第6位依然是1
|
|
[0~13] 用于记录计数器溢出次数
|
|
|
|
val记录计数器的值
|
|
*/
|
|
uint16_t tim5_ch1_cap_sta = 0;
|
|
uint32_t tim5_ch1_cap_val;
|
|
|
|
//定时器捕获中断回调函数
|
|
//第1次捕获的是上升沿
|
|
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
|
|
{
|
|
if(htim == &htim5)
|
|
{
|
|
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);//点亮或关闭DS1
|
|
|
|
if((tim5_ch1_cap_sta&0x8000) == 0)
|
|
{
|
|
if((tim5_ch1_cap_sta&0x4000))//捕获到了下降沿
|
|
{
|
|
tim5_ch1_cap_sta |= 0x8000;
|
|
//获取当前计数器的值
|
|
tim5_ch1_cap_val=HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);
|
|
//清除之前的沿触发捕获模式
|
|
TIM_RESET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1);
|
|
//设置为上升沿触发
|
|
TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);
|
|
}
|
|
else//捕获到了上升沿
|
|
{
|
|
/*重启定时器5*/
|
|
//关闭
|
|
__HAL_TIM_DISABLE(&htim5);
|
|
//计数器清0
|
|
__HAL_TIM_SET_COUNTER(&htim5,0);
|
|
//清除之前的沿触发捕获模式
|
|
TIM_RESET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1);
|
|
//定时器5通道1设置为下降沿捕获
|
|
TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);
|
|
//使能定时器5
|
|
__HAL_TIM_ENABLE(&htim5);
|
|
|
|
tim5_ch1_cap_sta = 0;
|
|
tim5_ch1_cap_val = 0;
|
|
tim5_ch1_cap_sta |= 0x4000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//计数器溢出中断回调函数(TIM5_CNT 只有16位)
|
|
//计数器记录的是自己的执行了多少个周期 如:1Mhz 1us计数器+1
|
|
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
|
|
{
|
|
if(htim == &htim5)
|
|
{
|
|
if((tim5_ch1_cap_sta&0x8000) == 0)
|
|
{
|
|
if((tim5_ch1_cap_sta&0x4000))
|
|
{
|
|
if((tim5_ch1_cap_sta&0x3fff) == 0x3fff)//记录溢出次数过多(高电平太长)
|
|
{
|
|
tim5_ch1_cap_sta |= 0x8000;//强行表示高电平结束
|
|
tim5_ch1_cap_val &= 0xffffffff;
|
|
}
|
|
else
|
|
{
|
|
tim5_ch1_cap_sta++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*主函数测试部分代码*/
|
|
long long temp;
|
|
while (1)
|
|
{
|
|
if((tim5_ch1_cap_sta&0x8000))//确认当前为低电平
|
|
{
|
|
u1_printf("Capture ok\r\n");
|
|
temp = tim5_ch1_cap_sta&0x3fff;
|
|
temp = temp*65535;
|
|
temp = temp + tim5_ch1_cap_val;
|
|
|
|
u1_printf("%.2lf s\r\n",(double)temp/(1000*1000));
|
|
HAL_Delay(1000);
|
|
break;
|
|
}
|
|
}
|
|
u1_printf("done\r\n");
|
|
|
|
``` |