首页 > 编程知识 正文

单片机输出pwm波,三相pwm整流电路

时间:2023-05-06 06:22:08 阅读:168303 作者:956

说起PWM波,做过智能小车的人一定很熟悉,其实他是脉宽调制。 智能小车一般采用PWM波控制小车的速度,通过控制方波中高低电平的比例达到控制小车转速的目的。 32个芯片由他提供了专用的PWM波输出通道,我们只需进行适当的配置就可以调用32个PWM波的输出,今天我们通过定时器3的通道2产生PWM波来控制LED灯的亮度,实现呼吸灯的效果。

首先,说明32个PWM波输出的结构。 首先需要使用计时器。 (实际上我在用计数器。 因为计时器的本质是计数器) )假设让计数器从0数到100,然后在0到100之间再设定一个数。 假设设定为30,则计数器计数值低于30时,PWM输出的引脚输出1电平) )具体可以设定为高电平还是低电平)。 并且,当计数器的值大于30时,PWM波的输出端子输出与刚才相反的电平。 然后,计数到100后,再次回到0,重新开始下一个计数。 然后,通过控制中间的值(刚才例子中的30 ),可以控制PWM波的占空比。 并且,通过控制计数的最大值(刚才例子中的100 ),可以控制PWM波的输出周期,这是32时PWM波输出的基本原理。

今天也使用了LED和计时器。 按照往常的做法,还是做两个空白文件,分别命名为time.c和time.h,按照前两个博客的步骤添加到工程中。 具体步骤在此省略。 这次把所有的初始化函数放入了time.c文件。 这意味着您不需要重新创建led.c和led.h文件。

首先基本构成计时器3。 代码如下所示

fkd Qt _ timebaseinittypedeffkdqt _ time base structure; //结构声明必须在函数的开头中包含RCC _ AP B1 periphclockcmd (RCC _ AP B1 per iph _ fkd Qt 3,ENABLE ); fkd Qt _ time base structure.fkd Qt _ clock division=fkd Qt _ CKD _ div 1; fkd Qt _ time base structure.fkd Qt _ counter mode=fkd Qt _ counter mode _ up; fkd Qt _ time base structure.fkd Qt _ period=arr; fkd Qt _ time base structure.fkd Qt _ prescaler=PSC; FKDQt_timebaseinit(FKDQt3,fkdqt_TimeBaseStructure ); 这些代码和以前的博客一样。 我不再多说了。 不明白的地方请看前面的博客(通过计时器中断控制LED )。

接着,设定计时器3通道2的PWM输出的动作方法。 代码如下所示

//fk dq T3通道2 pwmfkdqt _ ocinittypedeffkdqt _ ocinitstructure的配置; fkd Qt _ ocinitstructure.fkd Qt _ oc mode=fkd Qt _ oc mode _ PWM 2; fkd Qt _ ocinitstructure.fkd Qt _ oc polarity=fkd Qt _ oc polarity _ high; fkd Qt _ ocinitstructure.fkd Qt _ output state=fkd Qt _ output state _ enable; FKDQt_oC2init(FKDQt3,fkdqt_OCInitStructure ); //请注意此处的函数名称和函数的条目参数。 这还是一个结构,32中基本上使用了所有配置的结构。 首先,让我们看一下此结构的第一个成员变量fkdqt_OCMode。 该变量用于设定PWM的动作模式,关于PWM的动作模式有以下几种

# definefkdqt _ oc mode _ timing ((uint16_t )0x0000 ) definefkdQt_ocmode_active ) (uint 16 _ t )0x0010 ) dedefinefk t )0x0030 ) definefkdQt_ocmode_PWM1) uint16_t )0x0060 ) define

关于PWM输出PWM模式1:上账户: fkdqtx _ cntfkdqtx _ cc R1 active; fkdqtx_CNT=fkdqtx_CCR1 inactive向下计数: fkdqtx _ cntfkdqtx _ cc R1 inactive; fkdqtx _ CNT=fkdqtx _ cc R1 activepwmmode 2:向上计数: fkdqtx _ cntfkdqtx _ cc R1 inactive

;fkdqtx_CNT>=fkdqtx_CCR1 active向下计数:fkdqtx_CNT>fkdqtx_CCR1 active ;fkdqtx_CNT<=fkdqtx_CCR1 inactive

这里我们选择模式2,那么代码就是

fkdqt_OCInitStructure.fkdqt_OCMode=fkdqt_OCMode_PWM2;

然后这个结构体的第二个成员就是设置输出极性,也就是有效电平。假如说我们设置输出极性(有效电平)是高电平,对于模式2来说,当计数器的值小于你设定的阈值(上面那个例子中的30)的时候,PWM波对应的输出引脚就会输出无效电平,也就是低电平,当计数器的值大于你设定的阈值的时候,PWM波就会输出有效电平,也就是高电平;而对于模式1来说,则正好相反,当计数器的值小于你设定的阈值(上面那个例子中的30)的时候,PWM波对应的输出引脚就会输出有效电平,也就是高电平,当计数器的值大于你设定的阈值的时候,PWM波就会输出无效电平,也就是低电平;
这里我们选择输出极性(有效电平)为高电平,代码如下

fkdqt_OCInitStructure.fkdqt_OCPolarity=fkdqt_OCPolarity_High;

然后这个结构体的第三个成员就是选择输出状态是使能或者不使能,我们选择使能,代码如下

fkdqt_OCInitStructure.fkdqt_OutputState=fkdqt_OutputState_Enable;

到这就把PWM波的工作方式配置完了,然后就是把这些成员利用下面这个函数给导入到相应的寄存器中,代码如下

fkdqt_OC2Init(fkdqt3,&fkdqt_OCInitStructure);//注意此处的函数名字以及函数的入口参数

在这我们需要注意一下这个函数的名字fkdqt_OC2Init,它里面的2就代表着配置的是定时器的第二个通道,然后第一个参数就代表着配置的是定时器3,第二个参数就是刚才配置的结构体,总的来说就是配置了定时器3的第二个通道,如果要用到定时器3的其他通道,则把这个函数名字中的2改成对应的通道数就行。
定时器配置完了,接下来我们就要开始配置这次所用到的GPIO口了,代码如下

GPIO_InitTypeDef GPIO_InitStructure;//注意结构体声明必须放在函数的开头RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);

程序的第一行同样是定义一个结构体,然后第二行是开启GPIOB的时钟,然后第三行是开启复用功能的时钟,关于复用功能我简单说一下。我们今天想实现的是用定时器3的通道2来控制LED的亮度,在我使用的开发板上,今天用到的LED是接在PB5上,然而定时器3的通道2所产生的的PWM波却不是通过PB5引脚来输出的,所以说我们就需要开启32的复用功能,我么可以把定时器3的通道2 的PWM波输出给映射到PB5引脚上,这就可以实现让PWM波从PB5引脚上输出了,(重映射的引脚不是随意的,只能映射到固定的引脚)关于复用功能具体的大家可以百度查询。
然后程序的第四行就是配置GPIO口的工作模式,我们这里选择复用推挽输出模式。然后程序的第五、六、七行就不多说了。

这些都配置完之后,我们要再调用一个函数,如下

//把fkdqt3部分重映射到PB5 GPIO_PinRemapConfig(GPIO_PartialRemap_fkdqt3,ENABLE);

这个函数就是实现了把定时器3给重映射到了PB5引脚上。

然后我们用到了定时器3,所以就需要开启定时器3的时钟,代码如下

//使能fkdqt3时钟 fkdqt_Cmd(fkdqt3,ENABLE);

我们今天没有用到定时器中断,所以就不用再使能定时器中断的时钟了。
到此为止,我们time.c文件的程序都已经写好了,完整代码如下

#include "time.h"void time3_PWM_init(u16 arr,u16 psc){ //配置fkdqt3 fkdqt_TimeBaseInitTypeDef fkdqt_TimeBaseStructure;//注意结构体的声明必须在函数的开头 fkdqt_OCInitTypeDef fkdqt_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_fkdqt3,ENABLE); fkdqt_TimeBaseStructure.fkdqt_ClockDivision=fkdqt_CKD_DIV1; fkdqt_TimeBaseStructure.fkdqt_CounterMode=fkdqt_CounterMode_Up; fkdqt_TimeBaseStructure.fkdqt_Period=arr; fkdqt_TimeBaseStructure.fkdqt_Prescaler=psc; fkdqt_TimeBaseInit(fkdqt3,&fkdqt_TimeBaseStructure); //配置fkdqt3 Channel2 PWM fkdqt_OCInitStructure.fkdqt_OCMode=fkdqt_OCMode_PWM2; fkdqt_OCInitStructure.fkdqt_OCPolarity=fkdqt_OCPolarity_High; fkdqt_OCInitStructure.fkdqt_OutputState=fkdqt_OutputState_Enable; fkdqt_OC2Init(fkdqt3,&fkdqt_OCInitStructure);//注意此处的函数名字以及函数的入口参数 //配置GPIO口,并且设置成复用功能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); //把fkdqt3部分重映射到PB5 GPIO_PinRemapConfig(GPIO_PartialRemap_fkdqt3,ENABLE); //使能fkdqt3时钟 fkdqt_Cmd(fkdqt3,ENABLE);}

接下来开始写time.h文件,还是只需要把time.c文件中所定义的函数给声明一下就行,代码如下

#ifndef __fkdqtE_H#define __fkdqtE_H#include "sys.h"void time3_PWM_init(u16 arr,u16 psc);#endif

然后我们就开始写main.c文件中的程序了。先把全部代码贴出来

#include "sys.h"#include "delay.h"#include "time.h"int main(void){ u16 led0pwm=0; u8 dir=1; delay_init(); time3_PWM_init(899,0); while(1) { delay_ms(10); if(dir) led0pwm++; else if(!dir) led0pwm--; if(led0pwm>=300) dir=0; else if(led0pwm==0) dir=1; fkdqt_SetCompare2(fkdqt3,led0pwm); }}

在main.c文件的刚开始我们还是先写需要调用的头文件,因为我们今天主函数里面用到了延时函数,所以要添加头文件”delay.h”,调用的头文件如下

#include "sys.h"#include "delay.h"#include "time.h"

然后我们在主函数中定义了两个变量:led0pwm和dir,其中led0pwm是当做PWM波输出的那个阈值(就是前面举的例子中的那个30)的,然后变量dir是用来控制led0pwm的增长方向,以便实现呼吸灯的效果。然后我们还用到了另外一个重要的函数

fkdqt_SetCompare2(fkdqt3,led0pwm);

这个函数有两个入口参数,第一个参数就是选择对哪个定时器进行操作,第二个参数就是设置PWM波输出的那个阈值,我们在主函数中每隔10ms对led0pwm改变一次数值,也就是PWM波的那个阈值一直的在变化(每隔10ms变化一次),而每一个阈值对应的LED的发光亮度都会不一样,对于我们今天设定的工作方式来说,阈值越大,LED亮度越大,阈值越小,LED亮度越小。(因为我们刚才配置的PWM波工作模式为模式2,然后输出有效电平是高电平,而对于本人使用的开发板来说,给PB5引脚高电平,LED熄灭,给PB5引脚低电平,LED点亮,所以说当计数器的值小于led0pwm的时候,PWM波输出为无效电平,也就是低电平,这个时候LED点亮,而当计数器的值大于led0pwm的时候,PWM波输出有效电平,也就是高电平,这个时候LED熄灭,所以说我们的led0pwm的值越小,PWM波输出低电平的时间就越短,LED的亮度就越小,led0pwm的值越大,PWM波输出低电平的时间就越长,LED的亮度就越大)
综上所述,一直改变led0pwm的值,就可以一直改变LED的亮度,LED就会实现从暗到亮,然后从亮到暗,然后再从暗到亮,这样一直循环下去,就实现了呼吸灯的效果。
至此,本次用定时器3输出PWM波控制LED灯的实验就结束了,把代码烧录到开发板中,就可以看到正点原子精英版的开发板上DS0的亮度一直的在变化。
注意主函数中的那一条延时语句 delay_ms(10) 不能省略,否则我们将看不到LED的亮度变化,即我们不能让led0pwm的值变化的太快。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。