STM32呼吸灯的PWM原理与代码实现

用定时器生成pwm波
    pwm全称是pulse width modulation,通过控制高频信号的占空比,眼睛当成低通滤波器,可以控制亮暗。再循环更改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 240) flag=0; if(flag == 0){ pwm -=1; if(pwm240) flag=0; if(flag == 0){ pwm -=2; if(pwm240) 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);     // 将pc14 pc15置为低电平        }   if(mode ==2){ if(counter < pwm) //当counter值小于pwm值时,将io口设为高;当counter值大于等于pwm时,将io口置低 gpio_setbits(gpioa,gpio_pin_2|gpio_pin_0); //将pc14 pc15置为高电平 else gpio_resetbits(gpioa,gpio_pin_2|gpio_pin_0); // 将pc14 pc15置为低电平 }} int main(void){ rcc_configuration(); gpio_configuration(); tim4(); tim3();  nvic();  while(1) {     }   } void delay_nus(u32 n) //72m时钟下,约延时us{ u8 i; while(n--) { i=7; while(i--); }}void delay_nms(u32 n) //72m时钟下,约延时ms{ while(n--) delay_nus(1000);}void rcc_configuration(void) //使用任何一个外设时,务必开启其相应的时钟{ rcc_apb2periphclockcmd(rcc_apb2periph_gpioc|rcc_apb2periph_gpioa|rcc_apb2periph_afio, enable); //使能apb2控制外设的时钟,包括gpioc, 功能复用时钟afio等, rcc_apb1periphclockcmd(rcc_apb1periph_tim4|rcc_apb1periph_tim3, enable); //使能apb1控制外设的时钟,定时器tim3、4,其他外设详见手册 }void gpio_configuration(void) //使用某io口输入输出时,请务必对其初始化配置{ gpio_inittypedef gpio_initstructure; //定义格式为gpio_inittypedef的结构体的名字为gpio_initstructure                                           //typedef struct { u16 gpio_pin; gpiospeed_typedef gpio_speed; gpiomode_typedef gpio_mode; } gpio_inittypedef; gpio_initstructure.gpio_mode = gpio_mode_ipu; //配置io口的工作模式为上拉输入(该io口内部外接电阻到电源) gpio_initstructure.gpio_speed = gpio_speed_50mhz; //配置io口最高的输出速率为50m gpio_initstructure.gpio_pin = gpio_pin_12|gpio_pin_13; //配置被选中的管脚,|表示同时被选中    gpio_init(gpioc, &gpio_initstructure);                  //初始化gpioc的相应io口为上述配置,用于按键检测 gpio_initstructure.gpio_mode = gpio_mode_out_od; //配置io口工作模式为 推挽输出(有较强的输出能力) gpio_initstructure.gpio_speed = gpio_speed_50mhz; //配置io口最高的输出速率为50m gpio_initstructure.gpio_pin = gpio_pin_0|gpio_pin_1|gpio_pin_2; //配置被选的管脚,|表示同时被选中 gpio_init(gpioa, &gpio_initstructure); //初始化gpioa的相应io口为上述配置 gpio_pinremapconfig(gpio_remap_swj_jtagdisable,enable); //失能stm32 jtag烧写功能,只能用swd模式烧写,解放出pa15和pb中部分io口}void tim4() //配置tim4为基本定时器模式,约10ms触发一次,触发频率约100hz{    tim_timebaseinittypedef  tim_timebasestructure;   //定义格式为tim_timebaseinittypedef的结构体的名字为tim_timebasestructure   tim_timebasestructure. tim_period =9999; // 配置计数阈值为9999,超过时,自动清零,并触发中断    tim_timebasestructure.tim_prescaler =71;         //  时钟预分频值,除以多少 tim_timebasestructure.tim_clockdivision = tim_ckd_div1; // 时钟分频倍数    tim_timebasestructure.tim_countermode = tim_countermode_up; // 计数方式为向上计数 tim_timebaseinit(tim4, &tim_timebasestructure); // 初始化tim4 tim_clearitpendingbit(tim4,tim_it_update); //清除tim4溢出中断标志 tim_itconfig(tim4,tim_it_update,enable); // 使能tim4的溢出更新中断 tim_cmd(tim4,enable); // 使能tim4}void tim3() //配置tim3为基本定时器模式 ,约10us触发一次,触发频率约100khz{    tim_timebaseinittypedef  tim_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_inittypedef nvic_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);}  


惠及消费类产品的智能线性执行器
利用PLC及特殊模块实现电子束焊接机专用控制电路的设计
IT领袖Cognizant让人工智能超越爬山
爆苹果将大规模推荐迄今最便宜的MacBook
北京移动将在年底前在北京五环内实现5G信号全覆盖
STM32呼吸灯的PWM原理与代码实现
动极思静 NF AUDIO广州耳机展首发静铁混合耳机
Mini/Micro LED等高端产品营收增长超 47%,三安新“答卷”
苹果正考虑为Apple Watch增加Touch ID和屏下隐藏式摄像头
PCB高频板材有哪些?如何选择?
多色LED二十面体的制作
AR市场规模2020年将达1200亿美元 中国抢占高地
中京电子泰国项目开工建设
RFID智能仓库管理系统的详细介绍
新闻:马云将从软银董事会辞职 美针对华为出口管制新规
OPPOR11最新消息:OPPOR11发布会明日揭晓来点不一样,OPPR11Plus+性能升级有理有据抢先看
为什么比特币和加密货币价格下跌到了最低点
芯片设计晶圆代工的3D IC架构挑战
亚洲视野下的RISC-V
光纤在视频监控当中是如何应用的