【STM32基础】第四篇、控制PWM占空比

这篇具有很好参考价值的文章主要介绍了【STM32基础】第四篇、控制PWM占空比。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

第一部分、STM32定时器的基本知识

1、STM32定时器的分类(图片来自野火文档)

2、开发过程中定时器的常用基础功能

3、定时器挂在的总线

 第二部分、能用的代码

  1、定时器计时代码

2、定时器输出PWM代码

第三部分、总结

第一部分、STM32定时器的基本知识

1、STM32定时器的分类(图片来自野火文档)

        输入捕获通道应用:在测量方波信号的脉宽或者频率。输出比较应用在:PWM波形输出,控制电机转速或者呼吸灯等。

【STM32基础】第四篇、控制PWM占空比

2、开发过程中定时器的常用基础功能

        在STM32的使用过程中,我常用的两个功能如下:(1)间隔多少时间来一次定时器中断,可以用做计算时间、退出某一程序或者用来做LCD显示。(2)产生PWM波,通过控制PWM波的占空比,然后实现对电机转速的控制。

        注意:定时器定时时间的计算公式 T =((arr+1)*(psc+1))/72M  (单位为  s秒)

                                                               F = 72M /{(arr+1)*(psc+1) (单位为  Hz赫兹)

3、定时器挂载的总线

        其实在开发过程中,如果经常使用正点原子或者野火例程中的代码,那么这一点常常不会被关注到,因为这些基本的配置代码别人都给你配置好了,所以你在使用的过程中不会出现错误,但是了解一下,对开发是有帮助的。

        STM32的AHB 总线延伸出来的两条 APB2 和 APB1 总线,上面挂载着 STM32 各种各样的特色外设。我们经常说的 GPIO、串口、 I2C、 SPI 这些外设就挂载在这两条总线上。

      记忆方法: APB1 总线上一般挂载的都是比较高级,速度比较快的外设, 而APB2总线上挂载的都是一些比较low的外设。(细节详情请参考:《零死角玩转 STM32—基于野火 F103[MINI]开发板》这本书,上传不了,直接去野火论坛下载野火电子论坛 - Powered by Discuz! (firebbs.cn))

【STM32基础】第四篇、控制PWM占空比

 第二部分、能用的代码

  1、定时器计时代码

        代码写法可能不是最好的,但是用起来没问题。我记录下来,方便自己下次直接Copy,可能对你没帮助哦。

 time.c配置代码 

#include "timer.h"
//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u32 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(  //使能或者失能指定的TIM中断
		TIM3, //TIM2
		TIM_IT_Update ,
		ENABLE  //使能
		);
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}


extern int hour_return;
extern int min_return;
extern int sec_return;


void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{
			TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
			sec_return++;
					
				                                   
			if(sec_return == 60) 
			{
				sec_return = 0;
				min_return++;
				if(min_return == 60)
				{
					min_return = 0;
					hour_return ++;
					if(hour_return == 24) hour_return = 0;
					
				}
			}
		}
}

main.c初始化

        注意:这里时间的变量要到前面定义,

//主函数
int main()
{
/*定时器*/		
	TIM3_Int_Init(9999,7199);         //设置延时1s
    while(1)
    {
    }
}

2、定时器输出PWM代码

        pwm.c文件

#include "pwm.h" 

//电机初始化
void Motor_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PC端口时钟
	
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				
 GPIO_Init(GPIOA, &GPIO_InitStructure);					 
 GPIO_ResetBits(GPIOA,GPIO_Pin_5);						 
}

//定时器复用功能引脚初始化
static void ADVANCE_TIM_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	// 输出比较通道 GPIO 初始化
	RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);

	// 输出比较通道互补通道 GPIO 初始化
	RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);

	// 输出比较通道刹车通道 GPIO 初始化
	RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);
	// BKIN 引脚默认先输出低电平
	GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT,ADVANCE_TIM_BKIN_PIN);
}

/*电机占空比*/

extern unsigned char ADVANCE_TIM_PULSE;

//定时器模式配置
void ADVANCE_TIM_Mode_Config(void)
{
	// 开启定时器时钟,即内部时钟 CK_INT=72M
	ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);

	/*--------------------时基结构体初始化-------------------------*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	// 自动重装载寄存器的值,累计 TIM_Period+1 个频率后产生一个更新或者中断
	TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD;
	// 驱动 CNT 计数器的时钟 = Fck_int/(psc+1)
	TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC;
	// 时钟分频因子 ,配置死区时间时需要用到
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	// 计数器计数模式,设置为向上计数
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
	// 重复计数器的值,没用到不用管
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
	// 初始化定时器
	TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);

	/*--------------------输出比较结构体初始化-------------------*/
	TIM_OCInitTypeDef TIM_OCInitStructure;
	// 配置为 PWM 模式 1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	// 输出使能
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	// 互补输出使能
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	/* 设置占空比大小 */
	TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE;
	// 输出通道电平极性配置
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	// 互补输出通道电平极性配置
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
	// 输出通道空闲电平极性配置
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
	// 互补输出通道空闲电平极性配置
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
	TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable);

	/*-------------------刹车和死区结构体初始化-------------------*/
	// 有关刹车和死区结构体的成员具体可参考 BDTR 寄存器的描述
	TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
	TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
	TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
	TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
	// 输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述
	// 这里配置的死区时间为 152ns
	TIM_BDTRInitStructure.TIM_DeadTime = 11;
	TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
	// 当 BKIN 引脚检测到高电平的时候,输出比较信号被禁止,就好像是刹车一样
	TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
	TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
	TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);

	// 使能计数器
	TIM_Cmd(ADVANCE_TIM, ENABLE);
	// 主输出使能,当使用的是通用定时器时,这句不需要
	TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE);

 }

 void ADVANCE_TIM_Init(void)
{
	ADVANCE_TIM_GPIO_Config();
	ADVANCE_TIM_Mode_Config();		
}

        pwm.h文件

#ifndef __PWM_H
#define __PWM_H
#include "stdio.h"	
#include "sys.h" 

//电机
#define MOTOR PAout(5)	// PA5
#define PWM_ShaChe PBout(12)	// PB12
void Motor_Init(void);

//宏定义
/************高级定时器 TIM 参数定义,只限 TIM1 和 TIM8************/
// 当使用不同的定时器的时候,对应的 GPIO 是不一样的,这点要注意
// 这里我们使用高级控制定时器 TIM1

#define ADVANCE_TIM TIM1
#define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK RCC_APB2Periph_TIM1

/********PWM 的周期和占空比******************/
/*可供修改公式  F = TIM_CLK/{(ARR+1)*(PSC+1)*/
/* TIM_CLK 等于 72MHZ*/
#define ADVANCE_TIM_PERIOD (80-1)   //ARR 即自动重装载寄存器的值
#define ADVANCE_TIM_PSC (900-1)     //PSC 即计数器时钟的分频因子
//#define ADVANCE_TIM_PULSE1 10        //和ARR的数值有关,ARR的一半表示PWM高低各占一半(计数到40反转)

#define ADVANCE_TIM_IRQ TIM1_UP_IRQn
#define ADVANCE_TIM_IRQHandler TIM1_UP_IRQHandler

// TIM1 输出比较通道
#define ADVANCE_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA
#define ADVANCE_TIM_CH1_PORT GPIOA
#define ADVANCE_TIM_CH1_PIN GPIO_Pin_8

// TIM1 输出比较通道的互补通道
#define ADVANCE_TIM_CH1N_GPIO_CLK RCC_APB2Periph_GPIOB
#define ADVANCE_TIM_CH1N_PORT GPIOB
#define ADVANCE_TIM_CH1N_PIN GPIO_Pin_13

// TIM1 输出比较通道的刹车通道
#define ADVANCE_TIM_BKIN_GPIO_CLK RCC_APB2Periph_GPIOB
#define ADVANCE_TIM_BKIN_PORT GPIOB
#define ADVANCE_TIM_BKIN_PIN GPIO_Pin_12

static作用
静态函数不能被其它文件所用;
其它文件中可以定义相同名字的函数,不会发生冲突;
//static void ADVANCE_TIM_GPIO_Config(void);
void ADVANCE_TIM_Mode_Config(void);

void ADVANCE_TIM_Init(void);

#endif

        main.c文件的简易使用代码,需要更改。

/*设置占空比*/
unsigned char ADVANCE_TIM_PULSE = 0;
int main()
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断控制器分组设置
    /*高级定时器PWM初始化 */
    ADVANCE_TIM_Init();    //PWM   PA8
    Motor_Init();          //电机初始化PA5
    while(1)
    {
        ADVANCE_TIM_PULSE = 40;
        ADVANCE_TIM_Mode_Config();   //PWM  可以更换   
    }
}

第三部分、总结

        这上面的代码如果你想使用,需要你有一定的32开发基础,我这里做笔记,只是为了方便自己下次使用。文章来源地址https://www.toymoban.com/news/detail-469312.html

到了这里,关于【STM32基础】第四篇、控制PWM占空比的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 定时器及PWM计算占空比计算周期

    文使用Cubemx+MDK5开发方式(纯新手向 记录一下) 定时器时间计算 两步 (特别特别特别注意 单位换算 简单无脑) 1MHZ = 1000KHZ 1KHZ = 1000HZ 1HZ 的周期是1秒 1s = 1000毫秒(ms) 1ms =  1000 微秒(μs) 1μs = 1000纳秒(ns) 第一步: 定时器所在时钟总线频率 / 预分频 / 定时器计数值 = 频率 //频率

    2024年02月14日
    浏览(30)
  • stm32 笔记 PWM输入模式测量脉宽和占空比原理

    在测量占空比之前,我们先一步一步来,先让 STM32 可以测量脉宽。 TIM3_CH1(tim3 定时器通道 1)捕获模式测量脉宽步骤如下: 1.输入捕获到 PWM 上升沿触发 2.发送中断,通知用户此时被触发,用户获得当前计数器值 3.计数器清零,然后继续计数... 让 STM32 芯片一直重复这三步即

    2024年01月15日
    浏览(29)
  • STM32L4 HAL库通过串口通信改变PWM占空比

    使用串行通信的目的是为了让上位机能控制STM32来改变PWM的输出 这里用的是定时器TIM4的3通道,当然也可以改为其他的定时器,具体请参考手册 偷下懒,直接拿正点原子的例子程序修改了一下。 示例用的是UART1 引脚是PA9(TX),PA10(RX) 主要修改的地方在接收数据的部分,我用l

    2024年02月15日
    浏览(33)
  • [FOC-Stm32]设置PWM占空比(比较值)的几种方法

    近期博主在阅读一些基于STM32的FOC代码中,对PWM占空比的设置问题很感兴趣,于是找了分别拿出来做了一下对比,来看看都是怎么来调整PWM输出的。 下图给出了PWM占空比调整的原理,在定时器循环中,有两个量:ARR 重装载值和 CCR 比较值。定时器内的计数器从0到ARR循环记录数

    2024年02月15日
    浏览(35)
  • STM32-TIM3-PWM实现不同占空比波形

    目录 硬件准备 PWM介绍 产生PWM方法  TIM3模块介绍  代码部分 详细步骤 总结 首先,需要准备一块带有STM32芯片的开发板,例如STM32F103C8T6或STM32F407VET6。连接开发板到电脑上,并使用Keil,IAR等软件进行编程。本文章用的是Keil软件。 PWM(Pulse Width Modulation)即脉冲宽度调制,在具

    2024年02月03日
    浏览(32)
  • STM32笔记——定时器输入捕获功能(测量PWM的频率和占空比)

    目录 一、概述 二、输入捕获功能 2.1 输入捕获简介 2.2 输入捕获通道  三、输入捕获功能测量PWM波的频率和占空比 3.1 测量频率的方法 3.2 测量过程         主要介绍通用定时器的输入捕获功能,输入信号由GPIO口进入输入捕获通道,之后输入部分对相应的TIx输入信号采样,并

    2024年02月06日
    浏览(62)
  • 一文搞懂STM32定时器翻转模式(产生多路频率、占空比的PWM)

    在STM32定时器配置中,我们知道可以将定时器配置为PWM输出模式,也叫输出比较模式,通过修改ARR寄存器中的值可以改变PWM周期,通过修改CCR寄存器中的值可以修改,PWM的占空比,但是这种普通的PWM输出模式较为单一,能输出PWM的定时器有4个通道,这种方式只能够产生4路周期

    2024年02月12日
    浏览(37)
  • STM32主从模式实现两路同步PWM脉冲输出,频率、占空比可调

    原理:定时器1为主模式,定时器8为从模式,TIM1的定时器使能操作作为触发输出[TRGO]触发TIM8并使能TIM8的计数器,同时输出两路频率、占空比以及脉冲数量(小于256个,高级定时器重复计数功能为8位)可调PWM波形。 关键代码: 定时器1(TIM1)设为主模式: 定时器2(TIM8)设为从

    2024年02月13日
    浏览(29)
  • STM32实现PWM输出频率1kHz占空比50%的方波和呼吸灯

    板子:野火指南者 芯片:STM32f103VET6 PWM通道:TIM3的通道1和通道3 GPIO:PA6和PB0 本文主要讲需要怎么做,简要讲解原理,提供全部代码,有利于快速上手。 打开STM32f103VET6的芯片数据手册,打开目录Pinouts and pindescriptions——High-density STM32F103xC/D/E pin definitions,如图所示。 这里选

    2024年02月05日
    浏览(40)
  • STM32 PWM模式与输出比较模式的区别。PWM占空比不生效,在STM32CubeMX中配置PWM的两种模式——蓝桥杯嵌入式

      🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都已更新完毕,欢迎大家前往订阅本专题🎏 🎏【蓝桥杯嵌入式】蓝桥杯第十届省赛真题 🎏【蓝桥杯嵌入式】蓝桥杯第十二届省赛程序真题 🎏【蓝桥杯嵌入式】蓝桥杯第十三届

    2023年04月15日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包