我是靠谱客的博主 糟糕钢笔,最近开发中收集的这篇文章主要介绍stm32输出PWM,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

开发板:野火霸道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
CH1PA6
CH2PA7
CH3PB0
CH4PB1

由于小灯连接到了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这三 个函数

编程步骤

  1. 初始化定时器通道的GPIO
  2. 配置时基单元
  3. 配置输出比较寄存器
  4. 使能预装寄存器
  5. 使能定时器
  6. 设置占空比

代码实现

#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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部