STM32F407单一定时器输出4路不同频率及占空比的PWM波

这篇具有很好参考价值的文章主要介绍了STM32F407单一定时器输出4路不同频率及占空比的PWM波。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:写上一篇单一定时器输出四路PWM时就想过能否输出四路不同频率及占空比的PWM波形,最近有空就花时间研究了一下,首先定时器的频率在ARR和PSC设置好之后就已经锁定了,要输出不同频率的波形需要使用TIM_OCMode_Toggle电平翻转模式,在中断中动态修改CRR比较寄存器的值来控制电平不断翻转实现不同频率波形

程序效果演示

STM32单一定时器输出四路不同频率及占空比的PWM波

四路pwm输出,STM32单片机,stm32,单片机,嵌入式硬件
一、程序思路
因为定时器只有一个CNT计数器所以只能有一个输出频率,若要实现多路不同频率波形,只能通过在当前CNT计数器的基础上不断累加自身CCR寄存器的值来触发中断在中断中翻转波形的方式,此时中断触发的频率即为波形的频率(CLOCK/PSC/ARR*(ARR/CRR每次加的数字大小));PS:CNT计数器与CCR寄存器都不存在数据溢出的风险,当数据值大于65535后会自动将多出的不分从0开始计数,所以不需要单独处理这部分数据。
二、程序实现
1、创建所需变量数组

//定义通道1的CCR比较值
uint16_t CCR_Value[4] = {5000,10000,15000,20000};

//设置各通道的占空比大小
float Duty_Ratio[4] = {0.5,0.6,0.7,0.8};

//定义一个标志位用于存放是高电平中断还是低电平中断,初始为高电平
uint8_t flag[4] = {0,0,0,0};

//用于存放各个通道中断时的CNT计数器值
uint32_t CNT[4] = {0,0,0,0};

2、配置GPIO

//开启相关GPIO外设时钟
	RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE); 
	RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOB, ENABLE); 
	// 定时器3引脚复用 注:引脚复用函数参数只能有一个引脚不能同一个方法填写多个
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3); 
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM3); 
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource0,GPIO_AF_TIM3);
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource1,GPIO_AF_TIM3);
	
	//定义结构体用于初始化GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	//初始化GPIOA														   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;    
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 
	//初始化结构体A
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//初始化GPIOB
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;	
	//初始化结构体B,相同参数可复用
	GPIO_Init(GPIOB, &GPIO_InitStructure);

3、配置定时器
PS:此时定时器需要不断翻转,所以配置为电平翻转模式,且需要失能定时器通道自动重装器,手动装载CCR的值来达到控制翻转的目的

	 // 开启TIMx时钟 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	 //定义时基单元初始化结构体
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	 //定义PWM输出参数结构体
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	 //PWM结构体预初始化,防止数据未初始化对数据产生影响
	TIM_OCStructInit(&TIM_OCInitStructure);
	 //当定时器从0计数到65535,即为65535次为一个定时周期,定时周期到了之后会产生一个更新或中断,可通过更新中断TIM_IT_Update来捕获
	TIM_TimeBaseStructure.TIM_Period = 65535-1;       
	// 通用控制定时器时钟源TIMxCLK = HCLK/2=84MHz 
	// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=400KHz  此时定时器输出的频率为84000000/65535/21=61hz
    TIM_TimeBaseStructure.TIM_Prescaler = 21-1;	
	// 采样时钟分频,分频含义为几个周期采集一次数据,此处不分频
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	// 计数方式,向上计数
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
	
	// 初始化定时器TIM3
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
	
	//PWM模式配置
	//配置为电平翻转模式
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	
	//此处设置比较值为5000
	TIM_OCInitStructure.TIM_Pulse = CCR_Value[0];
	//当定时器计数值小于CCR寄存器值时时为高电平
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  
	//使能定时器3通道,相同参数可复用,
	//使能通道1
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);	
//此处设置比较值为10000	
	TIM_OCInitStructure.TIM_Pulse = CCR_Value[1];
	//使能通道2
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);	
//此处设置比较值为15000	
	TIM_OCInitStructure.TIM_Pulse = CCR_Value[2];
	//使能通道3
	TIM_OC3Init(TIM3, &TIM_OCInitStructure);	 
	//此处设置比较值为20000
	TIM_OCInitStructure.TIM_Pulse = CCR_Value[3];
	//使能通道4
	TIM_OC4Init(TIM3, &TIM_OCInitStructure);	 
	 
	//重载的目的是在定时器的预加载寄存器中存入要修改的TIM_SetCompareX值,防止修改值立即对当前周期生效影响电平,使得参数可以在上一个周期执行完之后使能
	//此处不需要重载功能,若要实时输出不同频率及占空比的波形就需要修改数据后实时生效
	//失能定时器3所有通道重载
	//失能通道1重载
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
	//失能通道2重载
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
	//失能通道3重载
	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);
	//失能通道4重载
	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Disable);

4、配置中断源并开启定时器中断

NVIC_InitTypeDef NVIC_InitStructure; 
	//设置中断组为0
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);		
	//设置中断来源
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; 	
	//设置抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 
	//设置响应优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;	
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	//定时器四个通道中断使能,先配置中断源再打开中断保证中断设置可以使能上
	TIM_ITConfig(TIM3,TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
	
	//使能定时器
	TIM_Cmd(TIM3,ENABLE);

5、在中断中捕获电平翻转中断并修改CCR值

void TIM3_IRQHandler(void)
{
	//处理通道1中断
	if(TIM_GetITStatus(TIM3,TIM_IT_CC1) == SET){
		//存储通道1中断时的计数器值
		CNT[0] = TIM_GetCapture1(TIM3);
		TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
		if(flag[0] == 0){
			flag[0] = 1;
			//将下一段高电平持续时间存入CCR
			TIM_SetCompare1(TIM3,CNT[0]+CCR_Value[0]*Duty_Ratio[0]);
		}else{
			flag[0] = 0;
			//将下一段低电平持续时间存入CCR
			TIM_SetCompare1(TIM3,CNT[0]+CCR_Value[0]*(1-Duty_Ratio[0]));
		}	
	}
	//处理通道2中断
	if(TIM_GetITStatus(TIM3,TIM_IT_CC2) == SET){
		//存储通道2中断时的计数器值
		CNT[1] = TIM_GetCapture2(TIM3);
		TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
		if(flag[1] == 0){
			flag[1] = 1;
			//将下一段高电平持续时间存入CCR
			TIM_SetCompare2(TIM3,CNT[1]+CCR_Value[1]*Duty_Ratio[1]);
		}else{
			flag[1] = 0;
			//将下一段低电平持续时间存入CCR
			TIM_SetCompare2(TIM3,CNT[1]+CCR_Value[1]*(1-Duty_Ratio[1]));
		}	
	}
	//处理通道3中断
	if(TIM_GetITStatus(TIM3,TIM_IT_CC3) == SET){
		//存储通道3中断时的计数器值
		CNT[2] = TIM_GetCapture3(TIM3);
		TIM_ClearITPendingBit(TIM3,TIM_IT_CC3);
		if(flag[2] == 0){
			flag[2] = 1;
			//将下一段高电平持续时间存入CCR
			TIM_SetCompare3(TIM3,CNT[2]+CCR_Value[2]*Duty_Ratio[2]);
		}else{
			flag[2] = 0;
			//将下一段低电平持续时间存入CCR
			TIM_SetCompare3(TIM3,CNT[2]+CCR_Value[2]*(1-Duty_Ratio[2]));
		}	
	}
	//处理通道4中断
	if(TIM_GetITStatus(TIM3,TIM_IT_CC4) == SET){
		//存储通道4中断时的计数器值
		CNT[3] = TIM_GetCapture4(TIM3);
		TIM_ClearITPendingBit(TIM3,TIM_IT_CC4);
		if(flag[3] == 0){
			flag[3] = 1;
			//将下一段高电平持续时间存入CCR
			TIM_SetCompare4(TIM3,CNT[3]+CCR_Value[3]*Duty_Ratio[3]);
		}else{
			flag[3] = 0;
			//将下一段低电平持续时间存入CCR
			TIM_SetCompare4(TIM3,CNT[3]+CCR_Value[3]*(1-Duty_Ratio[3]));
		}	
	}
}

三、小结
使用此方式输出四路不同频率PWM波需要对定时器有相当的理解,且在定时器初始化时其持续输出高电平无频率,需后续改进或丢弃此段数据文章来源地址https://www.toymoban.com/news/detail-744815.html

到了这里,关于STM32F407单一定时器输出4路不同频率及占空比的PWM波的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32F407高级定时器-死区时间研究-STM32CubeMX

    距离上次写笔记,已经过去好长时间了 中间也折腾过不少东西,但是都没咋整理,主要是这中间都是在干活儿,不是自己想要研究的,也没想着要写。 从去年10月份开始想要学习FOC,10月份研究了一个月,到11月初,实现了SVPWM驱动BLDC电机,使用串口实现开环下转速和力矩调

    2023年04月23日
    浏览(54)
  • stm32f407关于通用定时器各种函数——PWM(二)

            定时器产生PWM:在计数器频率固定时,PWM 频率由 自动重载寄存器(TIMx_ARR) 的值决定,其占空比由 捕获/比较寄存器(TIMx_CCRx) 的值决定         定时器工作在递增计数模式,纵轴是计数器的计数值 CNT,横轴表示时。当 CNT=CCRx 时,IO 输出高电平(逻辑 1);

    2024年02月08日
    浏览(85)
  • stm32f407探索者开发板(二十二)——通用定时器基本原理讲解

    STM32F40x系列总共最多有14个定时器 三种(4)STM32定时器区别 STM3 F4 的通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定时器功能特点包括: 16 /32 位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT)。 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系

    2024年02月12日
    浏览(43)
  • 基于STM32CubeMX和keil采用STM32F407的基本定时器中断实现LED闪烁

    定时器有三种,基本定时器,通用定时器,以及高级定时器。 这篇博客以最简单的基本定时器为例,实现LED的闪烁。 后面两种定时器的用法后面再写。 实现功能: TIM6控制LED每隔0.5s变一次状态。 TIM7控制LED1常量2s后熄灭。 因为都是用到LED,所以和上一篇基于STM32CubeMX与keil采

    2024年02月04日
    浏览(64)
  • STM32F1定时器-PWM输出

    STM32 PWM工作过程 ARR寄存器决定PWM周期,CCR寄存器决定占空比 通道1为例 的PWM输出电路图 CCR1:捕获比较(值)寄存器(x =1,2,3,4):设置比较值。 CCMR1:OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1【110】 或者PWM模式2【111】 CCER:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平

    2024年02月09日
    浏览(81)
  • STM32F105RBT6 使用定时器TIM3输出PWM波

    2.1 相关函数 RCC_APB1PeriphClockCmd、GPIO_Init、TIM_TimeBaseInit、TIM_OC4Init、TIM_OC4PreloadConfig、NVIC_Init、TIM_ITConfig、TIM_Cmd、 3.1 在启动文件里面找到TIM3 对应的中断入口函数,也就是中断服务函数 TIM3_IRQHandler 4.1 中断服务函数需要快速地执行完毕。中断服务函数应该避免执行太多的计算复

    2024年02月08日
    浏览(51)
  • STM32F4使用高级定时器(TIM1和TIM8)输出PWM问题

    STM32F4使用高级定时器(TIM1和TIM8)输出PWM时要使用TIM_CtrlPWMOutputs使能PWM输出,否则不会输出PWM波形,这一点是和通用定时器输出PWM不一样的地方,通用定时器是不用配置TIM_CtrlPWMOutputs函数的。、

    2024年02月15日
    浏览(43)
  • 基于STM32F103C8T6的端口重映射及定时器输出PWM控制

    #一、端口重映射原理及部分/完全重映射 #二、端口重映射的配置 #三、PWM控制 ##1、通用定时器输出PWM ##2、PWM的工作原理 ##3、PWM的内部运作机制 ##4、PWM的模式 ##5、自动加载的预载寄存器 #四、定时器输出PWM结构体及库函数的配置 #五、项目硬件 #六、项目代码 一、端口重映射

    2024年02月13日
    浏览(52)
  • STM32F407 GPIO口输出配置配置步骤

    STM32F407ZGT6 是意法半导体(STMicroelectronics)公司推出的一款高性能ARM Cortex-M4核心的32位微控制器(MCU)。它是 STM32F4 系列的一员,具备强大的处理能力和丰富的外设功能,适用于各种应用领域。 说明:STM32F4 的主频最高是 168Mhz,所以我们一般设置 PLLCLK 为 168Mhz(M=8,N=336,P=2),通

    2024年02月12日
    浏览(52)
  • STM32F407ZGT6 LQFP144 uart 打印输出

    STM32F407ZGT6 +AX58100 ETHERCAT芯片软件,需要查看SSC 协议栈运行情况,UART输出状态信息。 STM32F407ZGT6 驱动库使用标准库,虽然老,但是够用。 STM32F407ZGT6 作为AX58100 的主控 STM32F407ZGT6 +AX58100 ETHERCAT 从站开发板 2.0 硬件连接图 AX58100 核心板的UART 采用UART1 PB6 PB7 PIN 2.1 UART1配置

    2024年02月09日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包