用定时器生成PWM波的方法

发布时间:2024-03-20  

用定时器生成PWM波


PWM全称是Pulse Width Modulation,通过控制高频信号的占空比,眼睛当成低通滤波器,可以控制亮暗。再循环更改PWM的阈值,就弄出了呼吸的效果,相关文章推荐:STM32中PWM的配置与应用详解。


这里采用一个比较简单的方法生成PWM波:设置定时器中断然后根据阈值判断置高和置低。


void TIM3_IRQHandler(void)  

{

TIM_ClearITPendingBit(TIM3,TIM_IT_Update);

        if(counter==255)            

            counter = 0;

        else 

counter+=1;

        if(mode == 0){

            if(counter < pwm)              

                GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1); 

            else 

                GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1);    

}

        if(mode == 1)

        {

            if(counter < pwm)              

                GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2); 

            else 

GPIO_ResetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2);

}

        if(mode ==2){

            if(counter < pwm)              

                GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_0); 

            else 

                GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_0); 

        }

}

程序流程


开启外设时钟(GPIO和TIM)


void RCC_Configuration(void)                

{

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);                                                       

     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4|RCC_APB1Periph_TIM3, ENABLE); 

}

配置GPIO


配置时钟, 使能中断(计数阈值,预分频,时钟分频,计数模式)


void tim3()                           //配置TIM3为基本定时器模式 ,约10us触发一次,触发频率约100kHz

{

TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;//定义格式为TIM_TimeBaseInitTypeDef的结构体的名字为TIM_TimeBaseStructure

TIM_TimeBaseStructure. TIM_Period =9;         //配置计数阈值为9,超过时,自动清零,并触发中断

TIM_TimeBaseStructure.TIM_Prescaler=71;//时钟预分频值,除以多少

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频倍数

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数方式为向上计数

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);      //  初始化tim3

TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除TIM3溢出中断标志

TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //  使能TIM3的溢出更新中断

TIM_Cmd(TIM3,ENABLE);                     //           使能TIM3

}

配置中断优先级


void nvic()                                 //配置中断优先级

{    

NVIC_InitTypeDefNVIC_InitStructure;////命名一优先级变量

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    //     将优先级分组方式配置为group1,有2个抢占(打断)优先级,8个响应优先级

 NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //该中断为TIM4溢出更新中断

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//打断优先级为1,在该组中为较低的,0优先级最高

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 响应优先级0,打断优先级一样时,0最高

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //  设置使能

NVIC_Init(&NVIC_InitStructure);//初始化

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //要用同一个Group

 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 溢出更新中断

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//    打断优先级为1,与上一个相同,不希望中断相互打断对方

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;     //  响应优先级1,低于上一个,当两个中断同时来时,上一个先执行

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 NVIC_Init(&NVIC_InitStructure);

}

写中断服务函数


代码实现


为了方便按键检测,除了TIM3配置PWM波之外,TIM4用来检测是否有输入。由于使用开漏输出,这里使用5V电源


#include "stm32f10x.h"

#include "math.h"

#include"stdio.h"


u8  counter=0; 

int  pwm=100;

int flag=0;

int mode =0;

int velocity =0;

int turning=1;


void RCC_Configuration(void);    //时钟初始化,开启外设时钟

void GPIO_Configuration(void);   //IO口初始化,配置其功能

void tim3(void);                 //定时器tim4初始化配置

void tim4(void);                 //定时器tim4初始化配置

void nvic(void);                 //中断优先级等配置

void exti(void);                 //外部中断配置

void delay_nus(u32);           //72M时钟下,约延时us

void delay_nms(u32);            //72M时钟下,约延时ms

void breathing(int velocity){

        switch(velocity){

                case 0:

                    if(flag)

                            pwm +=1;

                            if(pwm>240) flag=0;

                    if(flag == 0){

                            pwm -=1;

                            if(pwm<10) flag=1;

                    }

break;

                case 1:

                    if(flag)

                            pwm +=2;

                            if(pwm>240) flag=0;

                    if(flag == 0){

                            pwm -=2;

                            if(pwm<10) flag=1;

                    }

break;

                case 2:

                    if(flag)

                            pwm +=3;

                            if(pwm>240) flag=0;

                    if(flag == 0){

                            pwm -=3;

                            if(pwm<10) flag=1;

                    }

                    break;

        }

}



void assert_failed(uint8_t* file, uint32_t line)

{

    printf("Wrong parameters value: file %s on line %d

", file, line);

    while(1);

}


void TIM4_IRQHandler(void)   //TIM4的溢出更新中断响应函数 ,读取按键输入值,根据输入控制pwm波占空比

{

        u8 key_in1=0x01,key_in2=0x01;

TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清空TIM4溢出中断响应函数标志位

        key_in1= GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_12);  // 读PC12的状态

key_in2=GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13);//读PC13的状态

if(key_in1&&key_in2)turning=1;

breathing(velocity);

        if(key_in1==0 && turning){

                turning =0;

        velocity = (velocity + 1) % 3;

}//调速度

    if(key_in2==0 && turning){

                turning =0;

        mode = (mode + 1) % 3;

    }//调颜色

}   



void TIM3_IRQHandler(void)      //    //TIM3的溢出更新中断响应函数,产生pwm波

{

TIM_ClearITPendingBit(TIM3,TIM_IT_Update);////清空TIM3溢出中断响应函数标志位

        if(counter==255)            //counter 从0到255累加循环计数,每进一次中断,counter加一

            counter = 0;

        else 

counter+=1;

        if(mode == 0){

            if(counter < pwm)              //当counter值小于pwm值时,将IO口设为高;当counter值大于等于pwm时,将IO口置低

                GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1); //将PC14 PC15置为高电平

            else 

                        GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1);     // 将PC14 PC15置为低电平

}

        if(mode == 1)

        {

            if(counter < pwm)              //当counter值小于pwm值时,将IO口设为高;当counter值大于等于pwm时,将IO口置低

                GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2); //将PC14 PC15置为高电平

            else 

GPIO_ResetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2);//将PC14PC15置为低电平

}

        if(mode ==2){

            if(counter < pwm)              //当counter值小于pwm值时,将IO口设为高;当counter值大于等于pwm时,将IO口置低

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    网络通讯协议等。 互感器与电能表接线方法 四户进线单相表表箱以及布线接线图 空开与漏保梯形接线方法......
    电动机顺序控制电路的工作原理和接线方法;电动机顺序控制电路的工作原理 电动机顺序控制电路是一种用于控制多个电动机依次运行和停止的电子电路。其主要作用是在机器正常启动和停止时,通过......
    转等工作状态,则需要连接控制线,例如启动按钮、停止按钮、正反转按钮等。控制线的接线也需要按照标准方法连接,以保证控制动作正确。   4. 电流互感器接线:有些电机保护器需要使用电流互感器来检测电机电流,电流互感器接线方法......
    指令 6、西门子PLC编程指令集(二)-赋值指令、定时器指令-字逻......
    如何从正电压电源获得负电压,正电压转负电压的方法图解;该电路图显示了如何从电源获得。该电路的另一个优点是,与原始正电源一起可用于模拟双电源。该电路基于定时器ICNE555。NE555作为非稳态多谐振荡器接线......
    控制器种类有手动按钮、定时器、接触器等,根据控制需求选择相应的控制器。 (1)电源接线:将电源的火线、零线接入控制器的端子上,一般为L1、L2、公共线N。 (2)控制信号接线:各种控制器都有相应的接线......
    机需要搭配多大断路器选型 15.时间继电器接线方法 16.时间继电器实物接线图 ①.直流......
    14.电动机需要搭配多大断路器选型 15.时间继电器接线方法 16.时间继电器实物接线......
    必须学的几个英文单词   6.压力传感器与变频器接线方法   7.变频器的接线方法   8.PLC外部按钮的接法 第一种S/S和0V短接按钮开关接到PLC的24V 第二种S/S和24V短接按钮开关接到PLC......
    液位变送器接线方法_液位变送器的工作原理;  液位变送器接线方法   压力变送器是把气体或液体的压力转换为可使用的电信号的器件。压力变送器按接线方式,可分二线制,三线制,四线制。看到......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>