首页 > 其他分享 >STM32学习记录-05 -2-TIM输出比较

STM32学习记录-05 -2-TIM输出比较

时间:2024-08-23 13:23:38浏览次数:15  
标签:TypeDef 05 void STM32 TIM uint16 GPIO TIMx

1 输出比较简介

OC(Output Compare)输出比较

输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形

每个高级定时器和通用定时器都拥有4个输出比较通道

高级定时器的前3个通道额外拥有死区生成和互补输出的功能

2 PWM简介

PWM(Pulse Width Modulation)脉冲宽度调制

在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域

PWM参数:

     频率 = 1 / TS            占空比 = TON / TS           分辨率 = 占空比变化步距

3 输出比较模式(输出模式控制器)

4 输出比较通道(通用)

左边为CNT计数器和CCR1第一路的捕获/比较寄存器进行比较,当CNT>CCR1或CNT=CCR1时,给输出模式控制器传一个信号后会改变输出oc1ref的高低电平(ref就是指信号的高低电平reference参考信号),上面的ETRF输入为定时器的小功能。ref信号可以前往主模式控制器映射到主模式的TRGO输出。下面一路进行极性选择,寄存器写0信号往上走即电平不翻转,写1信号往下走进行非门取反,然后输出使能电路选择是否输出,最后到OC1引脚即CH1通道引脚。

输出模式控制器:输入CNT和CCR的大小关系,输出ref高低电平

5 输出比较通道(高级)

左边和上方部分与通用定时器电路一样。右边OC1和OC1N外面通常接推挽电路(上管导通下管断开输出高电平,下管导通上管断开输出低电平,上下管都导通短路不允许,上下管都断开高阻态),OC1和OC1N为两个互补的输出端口控制上下管导通和关闭,在控制上下管状态时如果上管关闭瞬间下管立刻打开(由于硬件误差导致时间差),为了避免误差就有死区生成电路(上/下管关闭时延迟一段时间再导通下/上管,避免上下管同时导通的现象)

6 PWM基本结构

左边为时基单元和运行控制部分,再左边为时钟源选择(省略),配置好时基单元,CNT就可以自增运行。下面为输出比较单元(共4路),首先为CCR捕获/比较器,不断进行比较,后面的为输出模式控制器(右上角坐标图蓝色为CNT,黄色为ARR,红色为CCR,绿色为输出),有效电平为高电平,无效电平为低电平(输出占空比由CCR控制,CCR值高占空比大,CCR值低占空比小)。REF为频率可调,占空比也可调的PWM波形,最终经过极性选择,输出使能,最后通过GPIO口。

7 参数计算

8 PWM模块

        PWM输出比较对应库函数

                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);

                //四个为配置输出比较模块,OC为Output Compare 输出比较,参数为(TIMx选择定时器,TIM_OCInitStruct结构体)

                void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);//给输出比较结构体赋默认值

                void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

                void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

                void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

                void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

                //配置强制输出模式

                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);

                //配置CCR预装功能,影子寄存器

                void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

                void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

                void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

                void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

                //配置快速使能

                void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

                void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

                void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

                void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

                //外部事件清除REF信号

                void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

                void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

                void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

                void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

                void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

                void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

                void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

                //单独设置输出比较极性,NPolarityConfig高级定时器里互补通道的配置

                void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);

                void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

                //单独修改输出使能参数

                void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);//选择输出比较模式

                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);

                //单独更改CCR寄存器值的函数

                void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

                //使用高级定时器输出PWM需要调用函数使能主输出

        PWM初始化

        (1)RCC开启时钟,打开要用的TIM外设和GPIO外设

                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

        (2)配置时基单元,包括时钟源选择

                TIM_InternalClockConfig(TIM2);

                TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

                TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;

                TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

                TIM_TimeBaseInitStruct.TIM_Period = 100 - 1; //ARR

                TIM_TimeBaseInitStruct.TIM_Prescaler = 720 - 1; //PSC

                TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;

                TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);

        (3)配置输出比较单元(CCR值、输出比较模式、极性选择、输出使能)

                TIM_OCInitTypeDef TIM_OCInitStruct;

                TIM_OCStructInit(&TIM_OCInitStruct);//用此函数先全部赋初始值再改要用的

                TIM_OCInitStruct.TIM_OCMode = ;

                        TIM_OCMode_Timing 冻结模式

                        TIM_OCMode_Active相等置有效电平

                        TIM_OCMode_Inactive相等置无效电平

                        TIM_OCMode_Toggle相等电平翻转

                        TIM_OCMode_PWM1 模式1,TIM_OCMode_PWM2模式2

                        TIM_ForcedAction_Active,TIM_ForcedAction_InActive两种强制输出

                TIM_OCInitStruct.TIM_OCPolarity = ;

                        TIM_OCPolarity_High 高极性,REF有效时输出高电平

                        TIM_OCPolarity_Low 低极性,有效电平为低电平

                TIM_OCInitStruct.TIM_OutputState = ;

                        TIM_OutputState_Disable 失能,TIM_OutputState_Enable 使能

                TIM_OCInitStruct.TIM_Pulse = 50;//设置CCR寄存器值

                TIM_OC1Init(TIM2, &TIM_OCInitStruct);

        /*参数计算(频率1KHz,占空比50%)

        PWM频率:        Freq = CK_PSC / (PSC + 1) / (ARR + 1) =72M/720/100=1000

        PWM占空比:        Duty = CCR / (ARR + 1) =50/100=50%

        PWM分辨率:        Reso = 1 / (ARR + 1) =1/100=1%

        */

        (4)配置GPIO,初始化为复用推挽输出

                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

                GPIO_InitTypeDef GPIO_InitStructure;

                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出

                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

                GPIO_Init(GPIOA, &GPIO_InitStructure);

        //若想使用AFIO引脚重映射

                RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

                GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);

                GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

                解除调试端口复用

                GPIO_Remap_SWJ_NoJTRST 解除JTRST调试端口(PB4引脚)

                GPIO_Remap_SWJ_JTAGDisable 解除JTAG调试端口(PA15、PB3、PB4)

                GPIO_Remap_SWJ_Disable 解除全部SWD和JTAG端口(PA13-15、PB3-4)

        (5)运行控制,启动计数器

                TIM_Cmd(TIM2, ENABLE);

1 舵机简介

舵机是一种根据输入PWM信号占空比来控制输出角度的装置

输入PWM信号要求:周期为20ms,高电平宽度为0.5ms~2.5ms

2 硬件电路

黑色电源负极GND,红色电源正极+5V,黄色PWM信号线

1 直流电机及驱动简介

直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转

直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作

TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向

2 硬件电路

左下角VM为电机电源正极(接大电流电源,和舵机电源保持一致)。VCC逻辑电平输入端(和控制器电源保持一致,如STM32为3.3V)。AO1、AO2、BO1、BO2为两路电机输出,分别接两个电机。PWMA、AIN2、AIN1(控制AO1、AO2)直接接到GPIO口,PWMA要接PWM信号输出端。STBY待机控制引脚,接GND芯片处于待机状态不工作,接逻辑电源VCC芯片正常工作(需要待机模式可接到GPIO口给高低电平控制)。

程序源码

PWM.c
#include "stm32f10x.h"                  // Device header

/**
  * 函    数:PWM初始化
  * 参    数:无
  * 返 回 值:无
  */
void PWM_Init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA1引脚初始化为复用推挽输出	
																	//受外设控制的引脚,均需要配置为复用模式
	
	/*配置时钟源*/
	TIM_InternalClockConfig(TIM2);		//选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
	
	/*时基单元初始化*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;				//计数周期,即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;				//预分频器,即PSC的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
	
	/*输出比较初始化*/ 
	TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量
	TIM_OCStructInit(&TIM_OCInitStructure);                         //结构体初始化,若结构体没有完整赋值
	                                                                //则最好执行此函数,给结构体所有成员都赋一个默认值
	                                                                //避免结构体初值不确定的问题
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;               //输出比较模式,选择PWM模式1
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       //输出极性,选择为高,若选择极性为低,则输出高低电平取反
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //输出使能
	TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值
	TIM_OC2Init(TIM2, &TIM_OCInitStructure);                        //将结构体变量交给TIM_OC2Init,配置TIM2的输出比较通道2
	
	/*TIM使能*/
	TIM_Cmd(TIM2, ENABLE);			//使能TIM2,定时器开始运行
}

/**
  * 函    数:PWM设置CCR
  * 参    数:Compare 要写入的CCR的值,范围:0~100
  * 返 回 值:无
  * 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比
  *           占空比Duty = CCR / (ARR + 1)
  */
void PWM_SetCompare2(uint16_t Compare)
{
	TIM_SetCompare2(TIM2, Compare);		//设置CCR2的值
}
Servo.c
#include "stm32f10x.h"                  // Device header
#include "PWM.h"

/**
  * 函    数:舵机初始化
  * 参    数:无
  * 返 回 值:无
  */
void Servo_Init(void)
{
	PWM_Init();									//初始化舵机的底层PWM
}

/**
  * 函    数:舵机设置角度
  * 参    数:Angle 要设置的舵机角度,范围:0~180
  * 返 回 值:无
  */
void Servo_SetAngle(float Angle)
{
	PWM_SetCompare2(Angle / 180 * 2000 + 500);	//设置占空比
												//将角度线性变换,对应到舵机要求的占空比范围上
}
main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"

uint8_t KeyNum;			//定义用于接收键码的变量
float Angle;			//定义角度变量

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	Servo_Init();		//舵机初始化
	Key_Init();			//按键初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Angle:");	//1行1列显示字符串Angle:
	
	while (1)
	{
		KeyNum = Key_GetNum();			//获取按键键码
		if (KeyNum == 1)				//按键1按下
		{
			Angle += 30;				//角度变量自增30
			if (Angle > 180)			//角度变量超过180后
			{
				Angle = 0;				//角度变量归零
			}
		}
		Servo_SetAngle(Angle);			//设置舵机的角度为角度变量
		OLED_ShowNum(1, 7, Angle, 3);	//OLED显示角度变量
	}
}

标签:TypeDef,05,void,STM32,TIM,uint16,GPIO,TIMx
From: https://blog.csdn.net/2302_81517810/article/details/141299581

相关文章

  • c++ chrono头文件内Duration 、time_point和Clock
    前言        http://t.csdnimg.cn/eprLZ中介绍了关于chrono的基本操作,本文来介绍chrono与其他类的关系。内容Duration    duration表示一段时间间隔template<classRep,classPeriod=std::ratio<1>>classduration        Rep表示持续时......
  • 05-02 Relationships Between Objects(对象之间的关系 )
    RelationshipsBetweenObjects(对象之间的关系)XPOsupportsthreetypesofrelationshipsbetweenobjects.Thetypeofarelationshipthatiscreateddependsuponhowrelatedobjectsaredefined.XPO支持对象之间的三种类型的关系。创建的关系类型取决于相关对......
  • 05-03 Map Persistent Objects to Database Views(将持久对象映射到数据库视图 )
    MapPersistentObjectstoDatabaseViews(将持久对象映射到数据库视图)CreateaPersistentClass(创建持久类)Createapersistentclass.Theclassnameshouldmatchtheviewname.创建一个持久类。类名应与视图名匹配。AssignthePersistentattributetotheper......
  • 05-04 Basics of Creating Persistent Objects for Existing Data Tables(为现有数据表
    BasicsofCreatingPersistentObjectsforExistingDataTables(为现有数据表创建持久对象的基础知识)ToaccessanexistingdatatableinadatabaseandworkwithitusingthefunctionalityprovidedbyeXpressPersistentObjects(XPO),youneedtocreateap......
  • 05-01 Create a Persistent Object(创建持久对象)
    CreateaPersistentObject(创建持久对象)TheXPOORMcanloadandsavetoadatastoreonlypersistentobjects.XPOORM只能加载持久对象并将其保存到数据存储中。Youmakeyourbusinessobjectspersistentinanyofthefollowingways:您可以通过以下任何方式......
  • STM32学习记录-04-EXTI外部中断
    1中断系统(1)中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行(2)中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源(3)中断嵌......
  • STM32学习记录-03-OLED显示屏(调试)
    1OLED简介OLED(OrganicLightEmittingDiode):有机发光二极管OLED显示屏:性能优异的新型显示屏,具有功耗低、相应速度快、宽视角、轻薄柔韧等特点0.96寸OLED模块:小巧玲珑、占用接口少、简单易用,是电子设计中非常常见的显示屏模块(4行16列)供电:3~5.5V,通信协议:I2C(4针脚)/SPI(7针脚),分......
  • P10559 [ICPC2024 Xi'an I] The Last Cumulonimbus Cloud 题解
    这种题有一个常见的根号分治做法:设\(d\)为度数,显然有\(O(1)\)修改单点,\(O(d)\)查询邻域和\(O(d)\)修改邻域,\(O(1)\)查询单点两种暴力。对度数大于\(\sqrtn\)的点使用前者,度数小于等于\(\sqrtn\)的点使用后者,可以做到\(O(m\sqrtn)\)的时间复杂度。这种做法的本......
  • python 05-标准库:csv、json、sqlite3、datetime模块
    csv模块importcsv#data.csv不存在时,会现在当前目录下创建一个data.csv文件withopen("data.csv","w",encoding='utf-8')asfile:writer=csv.writer(file)writer.writerow(["trasanction_id","product_id","pric......
  • Towards Mitigating ChatGPT’s Negative Impact on Education: Optimizing Question
    文章目录题目摘要引言概述实验结果结论和未来工作题目减轻ChatGPT对教育的负面影响:通过布鲁姆分类法优化问题设计论文地址:https://ieeexplore.ieee.org/document/10223662摘要    生成文本AI工具在回答问题方面的流行引发了人们对其可能对学生学业成......