stm32 pwm输出异常及解决过程

pwm输出是stm32最常用的外设之一,我比较习惯使用库函数配置,我通常移植做过的工程中的程序的配置代码,然后改一改相应的参数,配置方法也十分简单,即使很简单,但对于初学者有时候还是很容易出错。有时候会一点波形没有输出,在找不到其他原因的情况下,这个时候以自己以前的经验来说,配置代码里面有一句GPIO_PinAFConfig(GPIOB,GPIO_PinSource1, GPIO_AF_TIM3);   (以stm32f4 time3 ch4为例)比较容易出错同时被忽略,其中的GPIO_PinSource1很容易稍不注意会写成GPIO_Pin_1这样子会导致引脚复用没有成功,同时输入捕获的配置的时候也有可能导致配置没有成功的情况,然后其中一个比较可能的原因也是这个参数的宏写错,因为这两个宏有点像,以上是我之前遇到的配置pwm或输入捕获的时候由于自己的粗心出现的问题,当时也查了比较久的时间,所以记录下来。

       但前阵子在写一个程序是出现了一个更加奇怪的现象,出现了类似积分电路的波形。改工程程序的描述如下

该工程中需要配置一些外部中断和pwm输出于是写了这两个一下两个函数

	LimitSwitchInit();	
	PWM3_Configuration();//tim3ch4
两个函数的具体定义如下:

void LimitSwitchInit()
{
	NVIC_InitTypeDef   NVIC_InitStructure;
	EXTI_InitTypeDef   EXTI_InitStructure;
	
	OutGPIOInit(); //外部中断IO初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
	
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource2);//PA2 连接到中断线2
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource5);//PA5 连接到中断线5
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource6);//PA6 连接到中断线6
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource7);//PA7 连接到中断线7
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource15);//PB15 连接到中断线15
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource8);//PA8 连接到中断线8
	
	/* 配置EXTI_Line2 */
	EXTI_InitStructure.EXTI_Line = EXTI_Line2|EXTI_Line5|EXTI_Line6|EXTI_Line7|EXTI_Line8|EXTI_Line15;//LINE2,LINE5,LINE6,LINE7,LINE15,
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能
	EXTI_Init(&EXTI_InitStructure);//配置

	//中断配置
	NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断2
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);//配置
//	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;//外部中断7
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);//配置
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//外部中断7
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);//配置
}
void PWM3_Configuration(void)	//TIM3
{
	GPIO_InitTypeDef          gpio;
	TIM_TimeBaseInitTypeDef   tim;
	TIM_OCInitTypeDef         oc;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);		//TIM1--TIM8使用内部时钟时,由APB2提供

	gpio.GPIO_Pin = GPIO_Pin_1;
	
	gpio.GPIO_Mode = GPIO_Mode_AF;
	gpio.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOB,&gpio);

	GPIO_PinAFConfig(GPIOB,GPIO_PinSource1, GPIO_AF_TIM3);      
	
	tim.TIM_Prescaler = 12;
	tim.TIM_CounterMode = TIM_CounterMode_Up;		//向上计数
	tim.TIM_Period = 260;   //25khz	计数周期
	tim.TIM_ClockDivision = TIM_CKD_DIV1;		//设置时钟分割,不为1的话会乘2
	TIM_TimeBaseInit(TIM3,&tim);
	
	oc.TIM_OCMode = TIM_OCMode_PWM2;		//选择定时器模式
	oc.TIM_OutputState = TIM_OutputState_Enable;		//选择输出比较状态
	oc.TIM_OutputNState = TIM_OutputState_Disable;	//选择互补输出比较状态
	oc.TIM_Pulse = 150;		//设置待装入捕获比较器的脉冲值
	oc.TIM_OCPolarity = TIM_OCPolarity_Low;		//设置输出极性
	oc.TIM_OCNPolarity = TIM_OCPolarity_High;		//设置互补输出极性
	oc.TIM_OCIdleState = TIM_OCIdleState_Reset;		//选择空闲状态下的非工作状态
	oc.TIM_OCNIdleState = TIM_OCIdleState_Set;		//选择互补空闲状态下的非工作状态
	
	TIM_OC4Init(TIM3,&oc);		//通道4
	TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
	
	TIM_Cmd(TIM3,ENABLE);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;		//子优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
}

运行程序之后的波形:


发现波形输出不是标准的方波,有点像是积分的波形,于是开始找原因,然后无意之间调换了LimitSwitchInit(); PWM3_Configuration();//tim3ch4这两个配置函数的位置即:

	PWM3_Configuration();//tim3ch4
	LimitSwitchInit();	

结果输出波形就变得很正常:



于是很自然变想到了是第一个配置的外部中断影响到了正常的pwm输出,于是在这个方向上找了好久的原因,但是始终找不到外部中断有什么问题,同时外部中断的功能也很正常,而且还有一个很奇怪的问题,就是如果外部中断的配置影响了pwm的外设,那么应该是外部中断放在pwm后面才会出现问题,因为放在后面的pwm配置应该会覆盖原来的配置,但是实际情况刚好相反,pwm放在后面的时候便会出错,放在前面反而正常。

最后把void PWM3_Configuration(void)//TIM3这个函数的定义里面,配置gpio的gpio这个结构体放到了函数外面,变成一个全局变量,然后再次运行程序然后发现无论两个函数的配置位置是如何的都pwm输出都非常正常,到这里时问题就变得比较清晰了,我们应该知道局部变量和全局变量的区别,首先这两种类型的变量的作用域和生存期不同,局部变量作用域是该函数,生存期时这个函数的运行的时间,即函数返回,内存被回收利用,而全局变量的作用域是整个文件,生存期就是整个程序的运行时间内长期存在,内存不会被回收,其次他们还有另外一个问题就是,当定义一个全局变量的时候,分配的内存会全部清零,即所有的变量的初始值会是0,而当定义一个局部变量时,内存将不会清零。分配到的内存里面是什么数据,便是什么数据,也就说,局部变量不初始化的话,变量的值是很随机的。

回到之前的程序,由于我定义了一个局部变量GPIO_InitTypeDef  gpio;这个结构体,然后这个结构体的数据便是原先内存的数据,里面成员的值是比较随机的,通过打断点观察成员的数据得到

LimitSwitchInit(); PWM3_Configuration();//tim3ch4这个顺序时GPIO_InitTypeDef  gpio里面的成员数据如左图,调换顺序之后变成右图:


可以发现后面的两个成员的数据改变了,查看原来void PWM3_Configuration(void)//TIM3函数的定义可以知道里面对这个结构体的赋值只有前三个成员而少了后两个成员,然后导致调换程序效果不同的原因是当前一个函数改变了某些内存,然后定义后面函数的局部变量的时候导致回收的内存里面的数据残留,造成了效果不同,至于是哪个变量不同呢,测试得到当补充配置gpio.GPIO_OType = GPIO_OType_PP;(推挽输出)时程序就没问题,当当配置为gpio.GPIO_OType = GPIO_OType_OD;(开漏输出)时便会出现那种异常波形。

以上得到的教训就是在定义了局部变量时,一定要把所有成员初始化一遍,不然会导致很多奇怪而又难以发现的问题,如以上遇到的问题。


  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
回答: 当STM32无法输出PWM波时,可能有几个原因。首先,检查配置代码中的参数是否正确。有时候在配置GPIO引脚时,可能会写错GPIO_PinSource参数,比如将GPIO_PinSource1写成了GPIO_Pin_1,这会导致引脚复用没有成功。另外,在输入捕获的配置中,也有可能出现配置不成功的情况,这时候也要检查参数的宏是否写错。\[1\] 其次,如果使用了未进行重映射的引脚,可能无法输出PWM波。例如,使用PA7引脚输出定时器3通道2的波形时,需要进行重映射才能成功输出PWM波。可以尝试修改引脚,使用PC7引脚来输出PWM波,并进行完全重映射和配置。\[2\] 最后,如果以上方法都没有解决问题,有可能是硬件上的连接问题。有时候,IO引脚连接了其他片内外设可能会导致无法输出PWM波。在这种情况下,建议尝试更换通道或者定时器,或者进行一些映射操作来解决问题。\[3\] #### 引用[.reference_title] - *1* [stm32 pwm输出异常解决过程](https://blog.csdn.net/l_w_zeng/article/details/73431846)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [解决stm32PWM输出失败](https://blog.csdn.net/weixin_52308622/article/details/131211290)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值