历史上的今天
今天是:2024年12月09日(星期一)
2021年12月09日 | 【STM32】PWM 输出 (标准库)
2021-12-09 来源:eefocus
一、PWM简介
PWM:脉冲宽度调制(Pulse width modulation,PWM)
脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。——百度百科
二、PWM输出模式
PWM 输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装 寄存器 ARR 的值决定,占空比由 比较寄存器 CCR 的值决定。
PWM 模式分为两种,PWM1和 PWM2。区别如下:

三、初始化结构体
1. TIM_TimeBaseInitTypeDef
typedef struct {
uint16_t TIM_Prescaler; // 预分频器
uint16_t TIM_CounterMode; // 计数模式
uint32_t TIM_Period; // 定时器周期
uint16_t TIM_ClockDivision; // 时钟分频
uint8_t TIM_RepetitionCounter; // 重复计算器
} TIM_TimeBaseInitTypeDef;
结构体具体介绍参见:【STM32】TIM—基本定时器
2. TIM_OCInitTypeDef
/**
* @brief TIM Output Compare Init structure definition
*/
typedef struct
{
uint16_t TIM_OCMode; /*!< Specifies the TIM mode.
This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
uint16_t TIM_OutputState; /*!< Specifies the TIM Output Compare state.
This parameter can be a value of @ref TIM_Output_Compare_State */
uint16_t TIM_OutputNState; /*!< Specifies the TIM complementary Output Compare state.
This parameter can be a value of @ref TIM_Output_Compare_N_State
@note This parameter is valid only for TIM1 and TIM8. */
uint32_t TIM_Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
This parameter can be a number between 0x0000 and 0xFFFF */
uint16_t TIM_OCPolarity; /*!< Specifies the output polarity.
This parameter can be a value of @ref TIM_Output_Compare_Polarity */
uint16_t TIM_OCNPolarity; /*!< Specifies the complementary output polarity.
This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_Idle_State
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
@note This parameter is valid only for TIM1 and TIM8. */
} TIM_OCInitTypeDef;
(1) TIM_OCMode:比较输出模式选择,总共有八种,常用的为 PWM1/PWM2。它设定 CCMRx寄存器 OCxM[2:0]位的值。
(2) TIM_OutputState:比较输出使能,决定最终的输出比较信号 OCx是否通过外部引脚输出。它设定 TIMx_CCER寄存器 CCxE/CCxNE 位的值。
(3) TIM_OutputNState:比较互补输出使能,决定 OCx的互补信号 OCxN是否通过外部引脚输出。它设定 CCER寄存器 CCxNE 位的值。
(4) TIM_Pulse:比较输出脉冲宽度,实际设定比较寄存器 CCR的值,决定脉冲宽度。可设置范围为 0至 65535。
(5) TIM_OCPolarity:比较输出极性,可选 OCx为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定 CCER寄存器的 CCxP位的值。
(6) TIM_OCNPolarity:比较互补输出极性,可选 OCxN 为高电平有效或低电平有效。它设定 TIMx_CCER寄存器的 CCxNP位的值。
(7) TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出 1或输出 0,即在空闲状态(BDTR_MOE 位为 0)时,经过死区时间后定时器通道输出高电平或低电平。它设定 CR2寄存器的 OISx位的值。
(8) TIM_OCNIdleState:空闲状态时互补通道输出电平设置,可选输出 1 或输出 0,即在空闲状态(BDTR_MOE 位为 0)时,经过死区时间后定时器互补通道输出高电平或低电 平,设定值必须与 TIM_OCIdleState 相反。它设定是 CR2 寄存器的 OISxN 位的值。
四、PWM输出实验
编程思路
初始化 LED
初始化延时函数
开启定时器时钟
设置定时器周期和预分频器
初始化定时器
主函数中修改比较值和占空比
pwm.h
// =============================================
# @Time : 2020-10-24
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: pwm.h
# @Software: keil5 MDK
// =============================================
#ifndef _TIME_H
#define _TIME_H
#include "stm32f4xx.h"
void TIM3_PWM_Init(u32 ARR , u32 PSC);
#endif
pwm.c
// =============================================
# @Time : 2020-10-24
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: pwm.c
# @Software: keil5 MDK
// =============================================
#include "pwm.h"
#include "bsp_led.h"
extern void TIM3_PWM_Init(u32 ARR , u32 PSC);
void TIM3_PWM_Init(u32 ARR , u32 PSC)
{
//此部分需手动修改IO口设置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //TIM3时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3); //GPIOA6复用为定时器3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //GPIOFA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA6
TIM_TimeBaseStructure.TIM_Prescaler=PSC; //定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=ARR; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);//初始化定时器3
//初始化TIM14 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR1上的预装载寄存器
TIM_ARRPreloadConfig(TIM3,ENABLE);//ARPE使能
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
main.c
// =============================================
# @Time : 2020-10-24
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: main.c
# @Software: keil5 MDK
// =============================================
#include "stm32f4xx.h"
#include "delay.h"
#include "pwm.h"
#include "bsp_led.h"
int main(void)
{
u16 ledpwmval=0;
u8 flag=1;
delay_init(168); //初始化延时函数
LED_GPIO_Config(); //初始化LED
TIM3_PWM_Init(100-1,84-1); //初始化定时器
while(1)
{
delay_ms(10);
if(flag)ledpwmval++;
else ledpwmval--;
if(ledpwmval==0)flag=1;
if(ledpwmval==40)flag=0;
TIM_SetCompare1(TIM3,ledpwmval); //修改比较值,修改占空比
}
}
五、总结
PWM输出,观察到 LED 缓慢变亮又缓慢变暗的状态(呼吸灯)
通过对定时器初始化数据和比较值的修改,可以改变亮暗时间
【参考文献】
[1] 《零死角玩转 STM32—基于野火 F407[霸天虎]开发板 》
史海拾趣
|
请问org 和 creg 这两个命令的区别。用Cx51时,其默认的startup.a51中有creg at 0,后面跟着很多代码,请问这样会不会占用中断地址(0x03, 0x0b......)??… 查看全部问答> |
|
不知道那位大虾能指点一下8962中断控制的问题,具体是怎么实现的! 我看了一些资料,说的都太学术了,没有讲中断控制的具体实现步骤! 例外uCosii 中断跟任务管理是怎么实现的,问题实在是太多了,盼高手解救~~~ 多谢!!!… 查看全部问答> |
|
各位坛子的大虾,小弟昨天刚刚下载了个AVRSTUDIO,不知为什么编译程序总是不通过它里面提示是这样的:make: Makefile: No such file or directorymake: *** No rule to make target `Makefile\'. Stop.是什么回事啊?能告诉我一下吗?急啊 ...… 查看全部问答> |
|
学习了郭天祥的51单片机,晕头了。 我只想做一个固定显示的房价牌,上面是万年历的那种,自己想焊可是无奈水平还不行,有没有朋友能告诉我,需要买什么材料,焊接流程的呢,因为这类房价牌网上有编好的程序,我只想做硬件组装。… 查看全部问答> |
|
可能大家注意到了,手机或相当设备上,在音频的去耦上,习惯用33P及10P的电容。 理论上说,用瓷片电容,容量越大去耦效果越好。实际中,104的电容与33P的电容价格是一样的。 为什么要用33P及10P的呢? 欢迎讨论,好帖加分!… 查看全部问答> |
|
请问各位,只编译NV_RESTORE这一选项与只编译NV_INIT这一选项以及与同时编译NV_INIT和NV_RESTORE这两个选项,这三种编译方式所产生的结果有什么区别吗?希望能得到各位的解答,谢谢 … 查看全部问答> |
|
用的是cyclonev soc这块板子,系统已经搭建好了,目前想完成的测试时我在HPS断对FPGA的DDR3进行读取,按照官网给的VIP_demo的例子,已经完成了基本的配置和地址映射,也得到了DDR3的虚拟地址 h2p_memory_addr= axi_virtual_base + ( ( unsigned lon ...… 查看全部问答> |




