1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一.PWM简介
PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调 制,简称脉宽调制。 PWM是一种对模拟信号电平进行数字编码 的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个 具体模拟信号的电平进行编码。PWM 信号仍然是数字的,因为在给定的 任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压 或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去 的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被 断开的时候。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。 PWM生成方法 计算法 根据拟合波形的频率、幅值和半周期脉冲数,准确计算 PWM 波各脉冲宽度和间隔,据此控制开关器件的通断,就可得到所需 PWM 波形; 调制法 拟合波形作调制信号,进行调制得到期望的 PWM 波;该方法一般采用等腰三角波为载波,其任一点水平宽度和高度成线性关系且左右对称。载波(等腰三角波)与平缓变化的调制信号波(即要拟合的波形)相交,在载波与信号波的交点控制器件通断,就得宽度正比于信号波幅值的脉冲,符合 PWM 的要求。相对于计算法,其处理过程计算简单。 二、PWM控制单色LED—单色呼吸灯 硬件说明 本文使用的是野火STM32F103指南者开发板 本开发板中设计的 RGB 灯控制引脚是经过仔细选择的,因为本实验的软件将使用STM32 的定时器控制输出 PWM 脉冲,然而并不是任意 GPIO都具有 STM32 定时器的输出通道功能,所以在设计硬件时,需要根据《STM32 中文数据手册》中的说明,选择具有定时器输出通道功能的引脚来控制 RGB 灯。 本实验中的 RGB灯使用阴极分别连接到了 PB5、PB0及 PB1,它们分别是定时器 TIM3的通道 2、3、4,其中 PB5 用于定时器输出通道时,需要使用重定义功能。 代码分析 这里用的例子是野火官方例程,可以去官网下载,在里面找到TIM—单色呼吸灯就可以了。 硬件相关宏定义文件bsp_breathing.h #ifndef __PWM_BREATHING_H #define __PWM_BREATHING_H #include “stm32f10x.h” /*PWM表中的点数*/ extern uint16_t POINT_NUM ; //控制输出波形的频率 extern __IO uint16_t period_class ; #define RED_LIGHT 1 #define GREEN_LIGHT 2 #define BLUE_LIGHT 3 /*要使用什么颜色的呼吸灯,可选RED_LIGHT、GREEN_LIGHT、BLUE_LIGHT*/ #define LIGHT_COLOR RED_LIGHT /********************定时器通道**************************/ #if LIGHT_COLOR == RED_LIGHT /************红灯***************/ #define BRE_TIMx TIM3 #define BRE_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd #define BRE_TIM_CLK RCC_APB1Periph_TIM3 #define BRE_TIM_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd #define BRE_TIM_GPIO_CLK (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO) //红灯的引脚需要重映射 #define BRE_GPIO_REMAP_FUN() GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); #define BRE_TIM_LED_PORT GPIOB #define BRE_TIM_LED_PIN GPIO_Pin_5 #define BRE_TIM_OCxInit TIM_OC2Init //通道选择,1~4 #define BRE_TIM_OCxPreloadConfig TIM_OC2PreloadConfig #define BRE_CCRx CCR2 #define BRE_TIMx_IRQn TIM3_IRQn //中断 #define BRE_TIMx_IRQHandler TIM3_IRQHandler #elif LIGHT_COLOR == GREEN_LIGHT /************绿灯***************/ #define BRE_TIMx TIM3 #define BRE_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd #define BRE_TIM_CLK RCC_APB1Periph_TIM3 #define BRE_TIM_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd #define BRE_TIM_GPIO_CLK (RCC_APB2Periph_GPIOB) //绿灯不需要重映射 #define BRE_GPIO_REMAP_FUN() #define BRE_TIM_LED_PORT GPIOB #define BRE_TIM_LED_PIN GPIO_Pin_0 #define BRE_TIM_OCxInit TIM_OC3Init //通道选择,1~4 #define BRE_TIM_OCxPreloadConfig TIM_OC3PreloadConfig #define BRE_CCRx CCR3 #define BRE_TIMx_IRQn TIM3_IRQn //中断 #define BRE_TIMx_IRQHandler TIM3_IRQHandler #elif LIGHT_COLOR == BLUE_LIGHT /************蓝灯***************/ #define BRE_TIMx TIM3 #define BRE_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd #define BRE_TIM_CLK RCC_APB1Periph_TIM3 #define BRE_TIM_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd #define BRE_TIM_GPIO_CLK (RCC_APB2Periph_GPIOB) //蓝灯不需要重映射 #define BRE_GPIO_REMAP_FUN() #define BRE_TIM_LED_PORT GPIOB #define BRE_TIM_LED_PIN GPIO_Pin_1 #define BRE_TIM_OCxInit TIM_OC4Init //通道选择,1~4 #define BRE_TIM_OCxPreloadConfig TIM_OC4PreloadConfig #define BRE_CCRx CCR4 #define BRE_TIMx_IRQn TIM3_IRQn //中断 #define BRE_TIMx_IRQHandler TIM3_IRQHandler #endif void TIMx_Breathing_Init (void); #endif /* __PWM_BREATHING_H */ 为方便切换LED 灯 的颜色,它定义了三组宏 , 通 过 修 改 代 码 中 的 “#defineLIGHT_COLOR RED_LIGHT”语句,可以切换使用红、绿、蓝种颜色的呼吸灯。在每组宏定义中,与全彩 LED 灯实验中的类似,定义了定时器编号、定时器时钟使能库函数、引脚重映射操作、GPIO 端口和引脚号、通道对应的比较寄存器名以及中断通道和中断服务函数名。 初始化GPIO口,代码: 本实验直接使用定时器输出通道的脉冲信号控制 LED 灯,此处代码把 ==GPIO ==相关的引脚配置成了复用推挽输出模式。其中由于红灯使用的引脚需要用到第二功能,本代码使用宏 BRE_GPIO_REMAP_FUN ()进行了该引脚的功能重定义操作。 这是PWM表: PWM 表记录了呼吸特性曲线,在本实验中,PWM 表的数据将会被赋 值到定时器的 CCRx 比较寄存器,从而控制输出占空比呈呼吸特性曲线变化的 PWM 波。 。定时器 PWM 配置 static void NVIC_Config_PWM(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Configure one bit for preemption priority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* 配置TIM3_IRQ中断为中断源 */ NVIC_InitStructure.NVIC_IRQChannel = BRE_TIMx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /** * @brief 配置TIM输出的PWM信号的模式,如周期、极性 * @param 无 * @retval 无 */ static void TIMx_Mode_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* 设置TIM3CLK 时钟 */ BRE_TIM_APBxClock_FUN ( BRE_TIM_CLK, ENABLE ); /* 基本定时器配置 ,配合PWM表点数、中断服务函数中的period_cnt循环次数设置*/ ************************************************************/ /* 基本定时器配置 */ TIM_TimeBaseStructure.TIM_Period = (1024-1);; //当定时器从0计数到 TIM_Period+1 ,为一个定时周期 TIM_TimeBaseStructure.TIM_Prescaler = (200-1); //设置预分频 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //设置时钟分频系数:不分频(这里用不到) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(BRE_TIMx, &TIM_TimeBaseStructure); /* PWM模式配置 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置为PWM模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出 TIM_OCInitStructure.TIM_Pulse = 0; //设置初始PWM脉冲宽度为0 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //当定时器计数值小于CCR1_Val时为低电平 BRE_TIM_OCxInit ( BRE_TIMx, &TIM_OCInitStructure ); //使能通道 BRE_TIM_OCxPreloadConfig ( BRE_TIMx, TIM_OCPreload_Enable ); //使能预装载 TIM_ARRPreloadConfig(BRE_TIMx, ENABLE); //使能TIM重载寄存器ARR /* TIM3 enable counter */ TIM_Cmd(BRE_TIMx, ENABLE); //使能定时器 TIM_ITConfig(BRE_TIMx, TIM_IT_Update, ENABLE); //使能update中断 NVIC_Config_PWM(); //配置中断优先级 } #python计算脚本 count.py #PWM点数 POINT_NUM = 110 #周期倍数 PERIOD_CLASS = 10 #定时器定时周期 TIMER_TIM_Period = 2**10 #定时器分频 TIMER_TIM_Prescaler = 200 #STM32系统时钟频率和周期 f_pclk = 72000000 t_pclk = 1/f_pclk #定时器update事件周期 t_timer = t_pclk*TIMER_TIM_Prescaler*TIMER_TIM_Period #每个PWM点的时间 T_Point = t_timer * PERIOD_CLASS #整个呼吸周期 T_Up_Down_Cycle = T_Point * POINT_NUM print (“呼吸周期:”,T_Up_Down_Cycle) #运行结果: 呼吸周期:3.12888 代码中初始化了控制 RGB 灯用的定时器, 它被配置为向上计数,PWM 通道输出也被配置成当计数器 CNT 的值小于输出比较寄存器CCRx的值时,PWM通道输出低电平,点亮 LED 灯。在函数的最后还使能了定时器中断,每当定时器的一个计数周期完成时,产生中断,配合中断服务函数,即可切换 CCRx 比较 寄存器的值。 代码中的 TIM_Period 和 TIM_Prescaler 是关键配置。其中 TIMPeriod 被配置为(1024-1),它控制控制定时器的定时周期,定时器的计数寄存器 CNT 从 0 开始,每个时钟会对计数器加 1,计数至 1023 时完成一次计数,产生中断,也就是说一共 1024 个计数周期,与 PWM 表元素中的最大值相同。若定时器的输出比较寄存器 CCRx被赋值为 PWM表中的元素,即可改变输出对应占空比的 PWM波,控制 LED灯。 main.c main 函数中直接调用了 TIMx_Breathing_Init 函数,而该函数内部又直接调用了GPIO和PWM配置函数:TIMx_GPIO_Config和TIMx_Mode_Config。初始化完成后,定时器开始工作,然后它会在中断服务函数中切换 PWM 数据,控制 LED 灯显示呼吸效果。 进行验证 示波器查看波形 这里因为我们点亮的是PB5所控制的LED灯,所以我们的测试点也是PB5。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1780 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1081 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1679 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
556浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 21:43 , Processed in 0.847137 second(s), Total 76, Slave 60 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号