STM32F7同一定时器多路输出PWM波通道之间相互影响问题

--------------------------2020/8/12更新--------------------------------
这次用Cube直接生成PWM控制代码,然后再RT-Thread Studio上编写程序,发现可实现TIM1和TIM8的8路PWM波调控,因此上面论述的问题可能是自己在写底层时有某些因素忽略了,以下仅供参考。

--------------------------原文--------------------------------
用这篇博客记录一下我折腾了三天换来的惨痛踩坑经历,事先声明,以下内容仅供参考,如果有大佬知道是什么原因欢迎在评论区指正。

先说结论:本次踩坑经历发现F7开发板(至少是我买的这块)在配置同一定时器多路PWM波输出的时候,各个通道之间存在相互影响,具体表现为TIM3和TIM4两个定时器的CH1和CH2,CH3和CH4之间并不相互独立。具体描述见后续。

初始情况

为了节省STM32的资源,博主原本打算用同一个定时器的四个通道来输出多路PWM波实现对多个电调的控制。用的正点原子的F7的开发板,原本打算的是选用TIM3和TIM4,总共八个通道实现八路PWM波输出,然后通过串口发送指令修改PWM波的占空比。

参考资料为官方手册
串口通信控制参考这篇博文:STM32407串口控制PWM占空比和频率
电调控制参考我上一篇博文:STM32通过PWM控制ESC30C电调

初始化配置TIM3和TIM4八通道共同输出PWM,周期20ms,初始脉宽1.5ms。

问题出现

首先是在程序下载之后再实物上进行测试,开始电调解锁之后用串口发送1.7ms脉宽进行调速,完成控制,但是在给定1.1ms之后却停转了,本以为是遇到死区了,然后重新发送1.3ms指令,仍然没动静。然后接上示波器观察引脚输出波形,惊讶的发现当串口发送指令的时候在1.5ms以上范围内是可以进行脉宽自由调节的,但是在小于1.5ms脉宽时却不会发生改变,最小变化至1.5ms(我在程序中PWM初始化时是随机给定脉宽,而后再用TIM->CCRx配置寄存器修改初始化脉宽为1.5ms,上一篇博文说过这是为了解锁电调)。

为了让文章内容更充实,示意性给上自己脉宽修改的程序

//设置TIM3通道的占空比
//compare:比较值
void TIM3_SetChannelCompare(u8 channel, u32 compare)
{
    
    
	switch(channel)		//配置各个通道的CCRx寄存器值
	{
    
    
		case 1:
			TIM3->CCR1 = compare;
			break;
		case 2:
			TIM3->CCR2 = compare;
			break;
		case 3:
			TIM3->CCR3 = compare;
			break;
		case 4:
			TIM3->CCR4 = compare;
			break;
	}
}

这边是串口控制程序,注意一下这边仅配置了TIM3各通道的串口控制

/*****
串口指令控制PWM波输出函数
初始高电平占空比已设置为中位信号1.5ms,对应于15
通过修改占空比来实现电调调速功能,范围11~19
后续配置指令如下(目前仅配置TIM3通道):
输入指令CHx XX E,其中x表示通道,XX表示占空比时间,E表示结束
*****/
void USART1_PWM(void)
{
    
    
	u16 len;
	u8 ch, time;
	u8 flag = 0;
	
	if(USART_RX_STA & 0x8000)
	{
    
    
		len = USART_RX_STA & 0x3fff;
		
		if(USART_RX_BUF[len-1]=='E')
		{
    
    
			if(USART_RX_BUF[0]=='C' & USART_RX_BUF[1]=='H' & USART_RX_BUF[3]==' ' & len==8)
			{
    
    
				ch = (USART_RX_BUF[2]-48);
				time = 10*(USART_RX_BUF[4]-48) + (USART_RX_BUF[5]-48);		//字符'0'对应的ASC码是48,因此为了得到正确的数字需减去48
				printf("ch = %d, time = %d\r\n", ch, time);
				if(ch<5 & ch>0)
				{
    
    
					//TIM4_SetChannelCompare(ch, time);
					TIM3_SetChannelCompare(ch, time);
					printf("pwm占空比已修改为%d\r\n", time);
					flag = 0;
				}
				else flag = 1;
			}
			else flag = 1;
		}
		else flag = 1;
		
		if(flag==1)
		{
    
    
			flag=0;
			printf("指令无效,请重新输入\r\n");
		}
		
		USART_RX_STA = 0;
	}
}

问题解决过程

以下是我解决的思路以及过程,如果大家遇到问题了,可以尝试照着这个思路先自己试着解决一下。

① 怀疑过是自己修改CCRx值的方式的问题,于是参照正点原子给的方式,单独对通道进行配置。

//设置TIM通道1的占空比
//compare:比较值
void TIM_SetTIM3Compare1(u32 compare)
{
    
    
	TIM3->CCR1 = compare;
}

但是很明显确实不是函数的问题,就算是直接在main中修改寄存器CCRx的值也没有任何变化。

② 然后考虑是串口通信影响了,就是先关闭在main中使用 USART1_PWM() 函数,不使用串口修改占空比,而是直接在程序中修改占空比。在测试之后发现问题仍然存在。

③ 最后是单独调试一个定时器,我首先把其他3路的PWM波都给关闭了,仅剩下一条通道输出,此时关键来了!发现在这种情况下是可以通过串口进行控制的,也可以在程序内部直接进行修改,也就是说可以在1.5ms以下进行调节。

④ 但是在多次测试之后我始终搞不懂为什么会这样子。于是开始进行求助(毕竟要自己先尝试过,知道自己的具体问题,不然求助也抓不到重点)。首先是问了周围用过STM32的同志,但是均没有尝试过配置多路PWM输出,然后只能是在网上进行求助,包括但不限于论坛以及各种专业群(这时候就要多叫几声大佬了),但是结果都不甚理想。

⑤ 关键时候还是朋友靠得住,在好友的远程视频协助下,发现这是一个玄学问题, 在调试模式下测试在串口发送指令时,观察到尽管测试的CH1通道脉宽始终不能降低至1.5ms以下,但是观察到内部的CCR1寄存器的值确实是改变了的,于是多番讨论之后,确定这是一个玄学问题, 又观察到当通道1的脉宽改变了之后,也会影响到通道2的脉宽,讨论至深夜依然无果。

问题解决

早上起来突发奇想,如果CH1和CH2之间是会相互影响的话,那么CH3和CH4呢?然后一顿操作之后惊奇地发现:CH1和CH2之间是相互影响的,CH3和CH4之间也是相互影响。

具体表现为,当你在使用SetCompare这种方式初始化配置完同一个定时器的四个通道的时候(假定均为1.5ms),那么CH1的脉宽变化会受到另一条通道CH2的影响,哪条通道的脉宽较大,那么另一条通道脉宽就不能小于这条通道的脉宽,假定CH2脉宽被配置到了2ms,那么CH1也会跟着变化到2ms,并且只能在≥2ms范围内进行调节。CH3和CH4之间也是如此。然而看了手册,上面明明说是各个通道之间相互独立,不清楚是什么原因,如果有懂的大佬麻烦解答一下。
在这里插入图片描述

结论

以下仅是个人测试所得结论(可能有误),发现同一个定时器下进行多通道PWM波输出时,CH1和CH2之间会相互影响(称为组1),同理CH3和CH4(称为组2)。但是组1和组2之间是互不影响的,也就是说可以使用CH1和CH3/CH4的方式,或CH2和CH3/CH4的方式进行PWM波各自的控制。

当然,也有可能是我自身缘故导致的问题,因此以上内容仅供参考,主要目的是记录一下本次踩坑经历方便给自己后续回顾,也欢迎大佬批评指正。

--------------------------2020/8/12更新--------------------------------
这次用Cube直接生成PWM控制代码,然后再RT-Thread Studio上编写程序,发现可实现TIM1和TIM8的8路PWM波调控,因此上面论述的问题可能是自己在写底层时有某些因素忽略了,仅供参考。

猜你喜欢

转载自blog.csdn.net/moumde/article/details/107687596