概述
开发板:野火霸道V1
芯片:stm32f103ZET6
定时器:TIM3
输出通道:CH3
GPIO:PB0
PWM
PWM即脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的
一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领
域中。
在stm32中,除了基本定时器TIM6、TIM7,其他的都可以用来产生PWM输出。其中高级定时器TIM1、TIM8可以产生7路的PWM输出;而通用定时器TIM2~TIM5可以产生4路的PWM输出。
频率
F = 72M / ((ARR+1)*(PSC+1))
单位:Hz
占空比
Duty_Cycle = ((TIMx->CCRx) / ARR)*100
单位:%
下面的试验是通过调节PWM占空比来观察LED小灯的亮度变化
LED小灯电路
TIM3通道对应的GPIO
通道 | GPIO |
---|---|
CH1 | PA6 |
CH2 | PA7 |
CH3 | PB0 |
CH4 | PB1 |
由于小灯连接到了PB0 所以使用TIM3的通道3
输出比较
输出比较模式由寄存器 CCMRx 的位 OCxM[2:0] 配置
PWM模式有2种
输出比较结构体
typedef struct {
uint16_t TIM_OCMode; // 比较输出模式
uint16_t TIM_OutputState; // 比较输出使能
uint16_t TIM_OutputNState; // 比较互补输出使能
uint32_t TIM_Pulse; // 脉冲宽度
uint16_t TIM_OCPolarity; // 输出极性
uint16_t TIM_OCNPolarity; // 互补输出极性
uint16_t TIM_OCIdleState; // 空闲状态下比较输出状态
uint16_t TIM_OCNIdleState; // 空闲状态下比较互补输出状态
} TIM_OCInitTypeDef;
通用定时器输出PWM只需配置部分成员即可
1、TIM_OCMode:比较输出模式选择,总共有八种,常用的为 PWM1/PWM2。它设定 CCMRx 寄存器 OCxM[2:0] 位的值
2、TIM_OutputState:比较输出使能,决定最终的输出比较信号 OCx 是否通过外部引脚输出。它设定 TIMx_CCER 寄存器 CCxE/CCxNE 位的值
3、TIM_OCPolarity:比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定 CCER 寄存器的 CCxP 位的值
时基单元结构体
typedef struct
{
uint16_t TIM_Prescaler; // 预分频器
uint16_t TIM_CounterMode; // 计数模式
uint32_t TIM_Period; // 定时器周期
uint16_t TIM_ClockDivision; // 时钟分频
uint8_t TIM_RepetitionCounter; // 重复计算器
} TIM_TimeBaseInitTypeDef;
1、TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器计数时钟 CK_CNT,它设定 PSC 寄存器的值。计算公式为:计数器时钟频率 (fCK_CNT) 等于 fCK_PSC / (PSC[15:0] + 1),可实现 1 至 65536 分频。
2、TIM_CounterMode:定时器计数方式,可设置为向上计数、向下计数以及中心对齐。高级控制定时器允许选择任意一种。
3、TIM_Period:定时器周期,实际就是设定自动重载寄存器 ARR 的值, ARR 为要装载到实际自动重载寄存器(即影子寄存器)的值,可设置范围为 0 至 65535。
4、TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与死区发生器以及数字滤波器采样时钟频率分频比。可以选择 1、 2、 4 分频。
5、 TIM_RepetitionCounter:重复计数器,只有 8 位,只存在于高级定时器
TIM3复用功能重映像
使用到的函数
输出比较寄存器
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
预装载寄存器
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
配置的是CCMRx寄存器的OCxPE位
设置占空比
//可以用于输出PWM时改变占空比
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);
配置的是CCRx寄存器
上面的函数是与我们选择的通道相对应的
比如本次实验使用的是通道3,所以我们选择
TIM_OC3PreloadConfig()、TIM_SetCompare3()、TIM_OC3Init这三 个函数
编程步骤
- 初始化定时器通道的GPIO
- 配置时基单元
- 配置输出比较寄存器
- 使能预装寄存器
- 使能定时器
- 设置占空比
代码实现
#include "bsp_GeneralTimer.h"
//初始化用到的 GPIO
static void GENERALTIMER_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APBxPeriphClockCmd(GENERALTIMER_CHANNEL_GPIO_CLOCK | RCC_APB2Periph_AFIO,ENABLE); //使能GPIO外设和AFIO复用功能时钟
GPIO_InitStruct.GPIO_Pin = GENERALTIMER_CHANNEL_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERALTIMER_CHANNEL_GPIO_PORT,&GPIO_InitStruct);
}
//初始化定时器模式
static void GENERALTIMER_MODE_Config(void)
{
//时基
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//输出比较
TIM_OCInitTypeDef TIM_OCInitStruct;
GENERALTIMER_TIMx_CLOCK_FUN(GENERALTIMER_TIMx_CLOCK,ENABLE);
//配置时基单元
TIM_TimeBaseInitStruct.TIM_Prescaler = GENERALTIME_PSC; //预分频值
TIM_TimeBaseInitStruct.TIM_Period = GENERALTIME_Period; //自动重装载寄存器周期的值 ARR
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(GENERAL_TIMEx,&TIM_TimeBaseInitStruct);
//配置输出比较
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式配置为2
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; //输出使能
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //定时器通道有效电平
TIM_OCxInit(GENERAL_TIMEx,&TIM_OCInitStruct);
//使能预装载寄存器
TIM_OCxPreloadConfig(GENERAL_TIMEx,TIM_OCPreload_Enable);
//使能寄存器
TIM_Cmd(GENERAL_TIMEx,ENABLE);
}
void GENERALTIME_Config(void)
{
GENERALTIMER_GPIO_Config();
GENERALTIMER_MODE_Config();
}
.h文件
#ifndef _BSP_GENERALTIMER_H
#define _BSP_GENERALTIMER_H
//TIM3 -> CH3 PB0
#include "stm32f10x.h"
//定时器 GPIO
#define RCC_APBxPeriphClockCmd RCC_APB2PeriphClockCmd
#define GENERALTIMER_CHANNEL_GPIO_CLOCK RCC_APB2Periph_GPIOB
#define GENERALTIMER_CHANNEL_GPIO_PORT GPIOB
#define GENERALTIMER_CHANNEL_GPIO_PIN GPIO_Pin_0
//定时器
#define GENERAL_TIMEx TIM3
#define GENERALTIMER_TIMx_CLOCK_FUN RCC_APB1PeriphClockCmd
#define GENERALTIMER_TIMx_CLOCK RCC_APB1Periph_TIM3
#define GENERALTIME_PSC (36-1)
#define GENERALTIME_Period (100-1)
//PWM相关函数
#define TIM_OCxInit TIM_OC3Init
#define TIM_OCxPreloadConfig TIM_OC3PreloadConfig
#define TIM_SetComparex TIM_SetCompare3
void GENERALTIME_Config(void);
#endif
在主函数中改变占空比来观察小灯的亮度变化
#include "bsp_GeneralTimer.h"
int main()
{
GENERALTIME_Config();
while (1)
{
TIM_SetComparex(TIM3,10);
}
}
由占空比计算公式得知此时占空比为:10%
最后
以上就是糟糕钢笔为你收集整理的stm32输出PWM的全部内容,希望文章能够帮你解决stm32输出PWM所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复