【手拉手 带你准备电赛】PWM究竟是什么(附:PWM输出实验完整代码)

目录

PWM简介

PWM原理

PWM实验内容

PWM实验步骤

PWM实验代码

PWM解惑时刻

1、向上计数

2、刹车、死区

附录

初始化函数的完整代码

主函数的完整代码


        都知道BMW,那么你们知道PWM是什么吗?BMW异父异母的亲兄弟?nonono!下面就让小蛋糕带你走进PWM吧!GOGOGO!

PWM简介

        PWM是Pulse Width Modulation的缩写,中文为脉冲宽度调制,简称脉宽调制器,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的计数。简单一点,就是对脉冲宽度的控制。

PWM原理

        PWM对脉冲宽度控制的原理其实很好理解。下面我们根据

        在上图中,CCRx代表TIMx_CCPx即捕获/比较寄存器,ARR代表TIMx_ARR自动重装载寄存器。CCRx和ARR构成了整个系统的比较器。上图表达的工作原理便是:当信号小于CCRx时,输入捕获为低电平;当信号与CCRx进行比较,得出结果为大于CCRx时,输出高电平;并且在信号大于ARR时,发生更新,回到低电平,开始新一轮的信号捕获比较和高低电平变化。

PWM实验内容

                下面,通过PWM输出实验带大家进一步了解PWM。本实验的实验平台依旧时STM32F103系列的MINI开发板实验平台。在本次实验中,我们主要通过TIM1_CH1输出的PWM来控制LED0的亮度。

PWM实验步骤

        很惊喜,我们这个实验so easy,实验步骤可以只分成两部,惊不惊喜,意不意外!

  1. 第一步,编写定时器初始化函数
    1. 首先我们需要开启TIM1和PA8的时钟;
    2. 然后我们需要对GPIO进行初始化;
    3. 然后我们需要设置TIM1的一些参数进行初始化;
    4. 然后需要设置TIM1的比较参数;
    5. 由于我们使用了高级定时器,所以需要使能刹车和死区寄存器的MOE位;
    6. 然后开启寄存器的预装载功能;
    7. 然后使能TIM1在ARR上的预装载寄存器;
    8. 然后使能TIM1;
  2. 最后编写主函数即可;

PWM实验代码

        首先由于我们需要设置TIM1的自动重装值和时钟预分频数,所以我们的定时器初始化函数是有参数的,初始化函数的框架如下行代码所示

void TIM_PWM_Init(u16 arr,u16 psc)
{
    
}

        然后我们开启所使用的定时器和IO口的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//开启定时器的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启复用IO口的时钟

         接下来,我们进行GPIO的初始化

//定义初始化函数参数结构体
GPIO_InitTypeDef	GPIO_Initstruct;

//为结构体成员变量赋值
GPIO_Initstruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Initstruct.GPIO_Pin=GPIO_Pin_8;
GPIO_Initstruct.GPIO_Speed=GPIO_Speed_50MHz;

//调用初始化函数
GPIO_Init(GPIOA,&GPIO_Initstruct);

        然后我们根据指定的参数初始化所使用的定时器中的时间基数单位

//定义初始化参数结构体
TIM_TimeBaseInitTypeDef		TIM_Initstruct;

//为结构体中的参数赋值
TIM_Initstruct.TIM_Period=arr;
TIM_Initstruct.TIM_Prescaler=psc;
TIM_Initstruct.TIM_ClockDivision=0;
TIM_Initstruct.TIM_CounterMode=TIM_CounterMode_Up;

//调用初始化函数
TIM_TimeBaseInit(TIM1,&TIM_Initstruct);

         然后我们初始化比较参数

//定义初始化参数结构体
TIM_OCInitTypeDef		TIM_OCInitstruct;

//为比较参数赋值
TIM_OCInitstruct.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitstruct.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitstruct.TIM_OCNPolarity=TIM_OCPolarity_High;

//调用函数
TIM_OC1Init(TIM1,&TIM_OCInitstruct);

         然后我们编写初始化函数中的剩余内容

//使能刹车和死区寄存器的MOE位,以使能整个OCx输出
TIM_CtrlPWMOutputs(TIM1,ENABLE);

//开启寄存器的预装载功能	
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  
	
//使能定时器1在ARR上的预装载寄存器	
TIM_ARRPreloadConfig(TIM1, ENABLE); 

//使能定时器	
TIM_Cmd(TIM1,ENABLE);

        最后,我们来编写主函数:

         在主函数中,我们在while循环(死循环)中控制LED0_PWM_VAL的值从0到300,然后从300到0,如此循环,因此LED的亮度也会从暗变亮,然后又从亮变暗。

int main(void)
 {	
	u16 led0pwmval=0;    
	u8 dir=1;	
	delay_init();	    	 
	TIM_PWM_Init(899,0);
   	while(1)
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;	 
 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;	   					 
		TIM_SetCompare1(TIM1,led0pwmval);	   
	} 
}

        至此,我们的函数就写完了。

PWM解惑时刻

        可能我们编写完函数之后,对于某些地方还是存有疑惑,下面我针对几个地方向大家说明:

1、向上计数

         STM32的通用定时器和高级定时器支持的计数模式包括:向上计数、向下计数和中心对齐计数模式。其中向上计数是最简单的一种技术过程:从0开始递增计数,直到ARR,发生溢出,计数器重装为0,开始下一轮计数。

2、刹车、死区

        stm32的刹车功能:stm32有PWM输出,可以用来驱动电机,刹车就是关掉PWM紧急停止的意思。

        STM32的高级定时器可以输出两路互补信号,并管理输出与接通瞬间,输出与接通之间的延迟时间便成为死区。

附录

初始化函数的完整代码

void TIM_PWM_Init(u16 arr,u16 psc)
{
	GPIO_InitTypeDef	GPIO_Initstruct;
	TIM_TimeBaseInitTypeDef		TIM_Initstruct;
	TIM_OCInitTypeDef		TIM_OCInitstruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	
	GPIO_Initstruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_Initstruct.GPIO_Pin=GPIO_Pin_8;
	GPIO_Initstruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Initstruct);
	

	TIM_Initstruct.TIM_Period=arr;
	TIM_Initstruct.TIM_Prescaler=psc;
	TIM_Initstruct.TIM_ClockDivision=0;
	TIM_Initstruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM1,&TIM_Initstruct);
	

	TIM_OCInitstruct.TIM_OCMode=TIM_OCMode_PWM2;
	TIM_OCInitstruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitstruct.TIM_OCNPolarity=TIM_OCPolarity_High;
	TIM_OC1Init(TIM1,&TIM_OCInitstruct);
	

	TIM_CtrlPWMOutputs(TIM1,ENABLE);	


	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);   
	
	
	TIM_ARRPreloadConfig(TIM1, ENABLE); 
	
	TIM_Cmd(TIM1,ENABLE);
}

主函数的完整代码

 int main(void)
 {	
	u16 led0pwmval=0;    
	u8 dir=1;	
	delay_init();	    	
	TIM_PWM_Init(899,0);
   	while(1)
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;	 
 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;	   					 
		TIM_SetCompare1(TIM1,led0pwmval);	   
	} 
}

        好了,关于PWM小蛋糕就介绍到这里,你学废了没有?我们下篇文章见!

  • 6
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
电赛中使用openmv准备的过程中,可以先了解openmv的硬件平台和功能。openmv是一个搭载了STM32系列芯片的摄像头,它提供了许多可供用户直接调用的函数,可以满足大部分图像处理需求。在openmv的操作中,我们使用python进行编程。\[1\] 对于快速上手openmv的人来说,思路是最重要的。可以通过学习一些基础使用的语法和算法,然后根据具体的任务将算法结合起来,完成任务。在网上可以找到一些教程和视频,可以借鉴他人的思路和经验。\[2\] 在电赛中,可以利用openmv进行色块识别。可以通过调用相关函数,设置条件来识别特定的色块。例如,当框0、1、2、5全为True,同时3和4为False时,可以识别为直角,并统计直角的数量。当达到一定数量时,可以发送倒车指令给MSP432进行倒车入库。在出库和侧方停车的过程中,可能会遇到直角的干扰,可以通过将直角数量置零或在下一次统计直角数量变为5时开始侧方停车来解决。\[3\] #### 引用[.reference_title] - *1* [【手拉手 准备电赛】单色块识别(基于openmv)](https://blog.csdn.net/weixin_54354252/article/details/124226631)[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^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [电赛OpenMV巡线巡迹](https://blog.csdn.net/weixin_53434575/article/details/130542864)[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^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值