[STM32F1] 单定时器多路输入捕获测量PWM的频率和占空比

[复制链接]
1968|15
 楼主| abotomson 发表于 2024-4-14 20:00 | 显示全部楼层 |阅读模式
对于定时器的单路捕获PWM的频率和脉冲,用cubemx配置:一个通道捕获上升沿,另一个通道捕获下降沿,Slave Mode 为Reset Mode .触发源为 TL1FP1 这可以很好地测量输入信号的周期和高电平时间,是使用定时器输入捕获的常用模式。(但仅限于定时器捕获单路PWM波)
在这种模式下:
1.上升沿到来时,触发中断,保存计数值到CCR1(假设通道1捕获上升沿的计数值),然后定时器的计数值清0(TIMx->CNT = 0)(这一点是关键)
2.下降沿到来时,保存计数值到CCR2(假设通道2捕获下降沿的计数值),定时器的计数值不会清0.
PWM一个周期下映射到定时器的计数值 = 上升沿的计数值.(CCRx)
PWM的频率 = 定时器的频率(1M) / (捕获上升沿的计数值 -0)
PWM的占空比 = (下降沿的计数值 / 上升沿的计数值)
配置(以通道1上升沿直接捕获,通道2下降沿间接捕获)
给出以上的实例代码
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){    static u16 t = 0;    static u16 d = 0;    if(htim->Instance == TIM2)    {        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)        {            LEDDT[0]=1;            t = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1)+1;            freq = 1000000 / t;            duty = (float)d/t*100;        }        else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)        {              LEDDT[1]=2;            d =  HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;        }    }}多路捕获PWM的频率和占空比(状态机实现)
我的思路:
配置定时器的两个通道都为上升沿捕获,开启定时器对于通道的输入捕获中断。
状态图
需要注意定时器的计数值有可能会溢出,所以要记录下溢出次数(在定时器的溢出更新中断中记录)
PWM频率= 定时器频率/ 两个上升沿之间的计数值
定时器频率 = 系统时钟 /预分频系数 = 1M
两个上升沿之间的计数值 = 第一次上升沿的计数值 +( 溢出次数 x 重装载值)- 第二次上升沿的计数值
PWM占空比 = 有效计数值 / 两个上升沿的计数值
有效计数值(假设以高电平为有效电平) = 下降沿的计数值 + ( 溢出次数 x 重装载值)-上升沿的计数值
配置
设置定时器的两个通道(多通道)为上升沿捕获计数值,这意味着每次PWM波在上升沿都会进入中断,保留计数值到CCRx.
用cubemx配置的话,就是很简单的配置方式,系统时钟80m,预分配系数80-1, 定时器频率为1M,预装载为0xffff(65535)
给出示例代码
TIM3的通道1和通道2
数据类型:
typedef struct mypwm{    u32 firstrisingcnt;    u32 secondrisingcnt;    u32 fallingcnt;    u32 validcnt; //有效计数值对应于脉宽    float freq;    float duty;    u16 updatetimes;    u8 state;} pwms;
在溢出更新中断的回调函数中:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){  if(htim->Instance == TIM3)    {       mpwms[0].updatetimes++;       mpwms[1].updatetimes++;         //两路的更新计数值自加1,这里实际上可以用一个代替    }}
输入捕获的中断回调函数
void Inputcapturehandle(pwms * cpwm,u32 cnt,TIM_HandleTypeDef *htim,u32 ch){     u32 temp = 0;     switch(cpwm->state)    {           case 0:     //测量上升沿        {                  //开启下次为下降沿采样                __HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_FALLING);                 //溢出计数值置为0                cpwm->updatetimes = 0;               //捕获第一次计数值                cpwm->firstrisingcnt =cnt;                //更新状态                cpwm->state = 1;                break;        }        case 1:    //测量下降沿        {            //开启下一次为上升沿采样         __HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_RISING);           //捕获下降沿的计数值        cpwm->fallingcnt = cnt;         //计算有效计数值(考虑溢出)        cpwm->validcnt =  (cpwm->updatetimes * htim->Instance->ARR)+ cpwm->fallingcnt-cpwm->firstrisingcnt;           //溢出计数置为0        cpwm->updatetimes  =0;           //更新下一状态        cpwm->state = 2;                   break;            }        case 2:  //再次测量上升沿            {                //捕获第二次上升沿的计数值                cpwm->secondrisingcnt = cnt;                //计算两个上升沿之间的计数值(考虑溢出)                temp =  cpwm->secondrisingcnt + (cpwm->updatetimes * htim->Instance->ARR) - cpwm->firstrisingcnt;                //溢出计数值置为0                cpwm->updatetimes = 0;                //计算频率 = 定时器频率/一个PWM波的两个上升沿的计数值                cpwm->freq = 1e6/temp;                //计算占空比                cpwm->duty = cpwm->validcnt*1.0f / temp *100;                //更新状态                cpwm->state = 0;            }               break;      }}void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){     if(htim->Instance ==  TIM3)    {        if(htim->Channel ==  HAL_TIM_ACTIVE_CHANNEL_1)        {            //进入到自己的中断回调函数中执行            Inputcapturehandle(&mpwms[0],TIM3->CCR1,htim,TIM_CHANNEL_1);        }        else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)        {                 //进入到自己的中断回调函数中执行           Inputcapturehandle(&mpwms[1],TIM3->CCR2,htim,TIM_CHANNEL_2);        }    }}测试效果
通过电位器控制输出PWM波的频率和占空比:输出格式为 频率 -占空比


wakayi 发表于 2024-6-5 09:13 | 显示全部楼层
这种捕获模式需要多路定时器工作吧
tpgf 发表于 2024-6-5 09:52 | 显示全部楼层
一个定时器多路输入捕获会互相产生干扰吗
guanjiaer 发表于 2024-6-5 10:26 | 显示全部楼层
如果测量占空比的话 就需要上升沿和下降沿都能捕获
木木guainv 发表于 2024-6-5 12:32 | 显示全部楼层
可以同时捕获不同占空比的pwm波吗
xiaoqizi 发表于 2024-6-5 22:50 | 显示全部楼层
捕获使用的是中断模式是吗 会不会产生阻塞
wowu 发表于 2024-6-5 23:23 | 显示全部楼层
使用状态机来实现多路的话  如果分支太多感觉代码不简洁
EmmaTT 发表于 2024-6-18 22:47 | 显示全部楼层
可以捕获不同的频率的pwm的
是你的乱码 发表于 2024-8-31 13:53 | 显示全部楼层
在使用STM32定时器进行PWM信号捕获时,正确配置和处理捕获中断是关键。
是你的乱码 发表于 2024-8-31 13:53 | 显示全部楼层
wakayi 发表于 2024-6-5 09:13
这种捕获模式需要多路定时器工作吧

假设使用的是TIM2,并且你的两个通道分别配置为CH1和CH2,下面是如何实现捕获和计算PWM信号频率和占空比
是你的乱码 发表于 2024-8-31 13:53 | 显示全部楼层
tpgf 发表于 2024-6-5 09:52
一个定时器多路输入捕获会互相产生干扰吗

你的思路是使用两个通道分别捕获PWM信号的上升沿和下降沿,这样可以准确测量PWM的周期和占空比。
t60yz 发表于 2024-8-31 22:14 | 显示全部楼层
你的思路是使用两个通道分别捕获PWM信号的上升沿和下降沿,这样可以准确测量PWM的周期和占空比。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

65

主题

1992

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部