首页 > 其他分享 >STM32(4)输出比较和输入捕获

STM32(4)输出比较和输入捕获

时间:2024-11-02 10:17:10浏览次数:5  
标签:输出 捕获 CCR STM32 TIM GPIO PWM 输入 时钟

OC输出比较

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

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

输出比较通道

在输出比较模块,会不断比较CNT和CCR的值,CCR是我们给定的一个值,当CNT大于、等于、小于CCR时,输出就会对应的置1、置0,从而输出一个电平不断跳变的PWM波形(REF)

可以将REF信号映射到主模式的TRGO输出上去

TIMX的四个通道有各自的CCR寄存器,但共用一个CNT计数器

PWM

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

PWM参数:      

频率 = 1 / TS            

占空比 = TON / TS          

分辨率 = 占空比变化步距

PWM模式

通过输出模式控制器的模式和极性选择,来决定要产生的PWM的形状

输出使能电路决定要不要输出

最后到OC1引脚,通过引脚定义表得知具体是哪个GPIO口

PWM频率:    Freq = CK_PSC / (PSC + 1) / (ARR + 1)

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

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

在设置参数时,先根据分辨率要求设置ARR,然后再设置占空比和PSC

代码

1.打开定时器和GPIO时钟

2.初始化GPIO,选择复用推挽输出模式

3.选择内部时钟源

4.时基单元初始化,不分频,向上计数,ARR,PSC

5.输出比较初始化,在这里我们只需要配置部分功能,所以先调用一个函数给OC赋初始值,然后单独修改要配置的值,PWM模式,极性,输出使能,初始CRR值

6.TIM使能

7.调用TIM_SetCompare1函数直接修改CCR的值

void PWM_Init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
	
	/*GPIO重映射*/
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);			//开启AFIO的时钟,重映射必须先开启AFIO的时钟
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);			//将TIM2的引脚部分重映射,具体的映射方案需查看参考手册
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);		//将JTAG引脚失能,作为普通GPIO引脚使用
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA0引脚初始化为复用推挽输出	
																	//受外设控制的引脚,均需要配置为复用模式		
	
	/*配置时钟源*/
	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 = 100 - 1;					//计数周期,即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 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_OC1Init(TIM2, &TIM_OCInitStructure);						//将结构体变量交给TIM_OC1Init,配置TIM2的输出比较通道1
	
	/*TIM使能*/
	TIM_Cmd(TIM2, ENABLE);			//使能TIM2,定时器开始运行
}

/**
  * 函    数:PWM设置CCR
  * 参    数:Compare 要写入的CCR的值,范围:0~100
  * 返 回 值:无
  * 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比
  *           占空比Duty = CCR / (ARR + 1)
  */
void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);		//设置CCR1的值
}

输入捕获

IC(Input Capture)输入捕获

输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数

每个高级定时器和通用定时器都拥有4个输入捕获通道

可配置为PWMI模式,同时测量频率和占空比

可配合主从触发模式,实现硬件全自动测量

频率测量

测频法:在闸门时间T内,对上升沿计次,得到N,则频率 f_x=N / T

测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率 f_x=f_c / N

输入信号进行滤波和极性选择后,来到了预分频器(每个通道各有一个),可以对前面的信号进行分频,分频之后的输出信号,就可以触发捕获电路进行工作,每来一个触发信号,CNT的值,就会向CCR转运一次,转运的同时,会触发一个捕获事件,这个事件会在状态寄存器置标志位,同时也可以产生中断,如果想在捕获的瞬间处理一些事情,就可以开启这个捕获中断,

主模式和从模式触发

主模式,可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设

从模式,接受其他外设或者自身外设的一些信号用于控制自身定时器的运行,也就是被别的信号控制

触发源选择,就是选择从模式的触发信号源

每次捕获后,都需要把CNT清零一下,可以从模式触发完成,触发源选择TIXFPX,从模式选择Reset,就能通过硬件自动完成

输入捕获单元配置

每个CCR的值都是从上一个上升沿到这个上升沿的计数值(如果选择上升沿触发)

信号频率太低的话,计数器可能溢出

可以配置一个引脚对应两个通道,一个选择上升沿触发直连,一个选择下降沿触发交叉连接,

CCR1的值是最新周期,CCR2的值是最新周期里高电平的计数值,从而可以同时测得一个引脚的频率和占空比

代码

/**
  * 函    数:输入捕获初始化
  * 参    数:无
  * 返 回 值:无
  */
void IC_Init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);			//开启TIM3的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA6引脚初始化为上拉输入
	
	/*配置时钟源*/
	TIM_InternalClockConfig(TIM3);		//选择TIM3为内部时钟,若不调用此函数,TIM默认也为内部时钟
	
	/*时基单元初始化*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;               //计数周期,即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;               //预分频器,即PSC的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit,配置TIM3的时基单元
	
	/*输入捕获初始化*/
	TIM_ICInitTypeDef TIM_ICInitStructure;							//定义结构体变量
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;				//选择配置定时器通道1
	TIM_ICInitStructure.TIM_ICFilter = 0xF;							//输入滤波器参数,可以过滤信号抖动
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;		//极性,选择为上升沿触发捕获
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;			//捕获预分频,选择不分频,每次信号都触发捕获
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;	//输入信号交叉,选择直通,不交叉
	TIM_ICInit(TIM3, &TIM_ICInitStructure);							//将结构体变量交给TIM_ICInit,配置TIM3的输入捕获通道
	
	/*选择触发源及从模式*/
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);					//触发源选择TI1FP1
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);					//从模式选择复位
																	//即TI1产生上升沿时,会触发CNT归零
	
	/*TIM使能*/
	TIM_Cmd(TIM3, ENABLE);			//使能TIM3,定时器开始运行
}

标签:输出,捕获,CCR,STM32,TIM,GPIO,PWM,输入,时钟
From: https://blog.csdn.net/weixin_49723219/article/details/143440690

相关文章

  • stm32疑难杂症之电压不够程序跑飞
    在开发阶段,如果出现程序不断重启的情况。首先先检查是不是代码问题。1.数组越界。定义的数组只有50个单元,但是程序运行的过程中,却给他赋给50+个单元。2.中断耗时太长,刚出中断又进去了。这时的现象是程序一直在中断中执行,回不到主函数。一般出现在中断嵌套中。3.中断或主函......
  • 基于stm32f403zet6游戏摇杆手柄
     一、硬件准备    (1)stm32f403zet6   (2)游戏摇杆扩展板                (3)oled模块        (4)hc-05蓝牙模块(5)电动小马达(6)其它模块温湿度模块,led灯和其它按键都集成在stm32f403zet6上了。如果有需要,也可以单独购买。二、设......
  • 基本输入函数的应用
    前言:从本质上来说,C语言的全部功能都是通过各种函数实现的,故可认为C语言是典型的函数式语言。输入函数scanf函数:(运用该输入函数的时候不要忘记写取地址符号&)以回车键表示输入完毕相必各位在刚开始学习输入函数的时候,输入东西时会这样写,就比如请输入两个整型数字,大家很可能会......
  • STM32开发 —— 新工程创建思路终于清晰了
    目录工程创建三步法一、工程文件夹创建二、管理工程项三、配置工程参数工程创建三步法从ST官网下载好stm32标准库或HAL库,HAL库目录如下。在Keil开发环境中创建STM32工程,分三大步即可完成工程的创建:一步:在本地磁盘创建工程文件夹,从下载好的库文件中拷贝相关文件......
  • 上电时通过 VIN 脚给芯片供电 ,输入电压
    led车灯驱动线性芯片产品体积小外围简单AP5101c产品描述AP5101C是一款高压线性LED恒流芯片,外围简单、内置功率管,适用于6-100V输入的高精度降压LED恒流驱动芯片。最大电流2.0A。AP5101C可实现内置MOS做2.0A,外置MOS可做3.0A的。AP5101C内置温度保护功能......
  • AP3464 包含多重保护功能:过温保护,输出短路保护和输入欠压/过压保护等。
    产品描述AP5103是一款效率高,稳定可靠的LED灯恒流驱动控制芯片,内置高精度比较器,固定关断时间控制电路,恒流驱动电路等,特别适合大功率LED恒流驱动。AP5103采用ESOP8封装,散热片内置接SW脚,通过调节外置电流检测的电阻值来设置流过LED灯的电流,支持外加电压线性调光,最大电......
  • 启用 iPhone 原生的五笔输入
    聊聊如何在iOS中使用原生的五笔输入法本文虽然介绍的是如何添加五笔键盘,其实其他键盘(双拼,外语键盘、第三方输入法)也是类似的添加方式。‍使用原生的理由虽然之前的文章列了不少第三方的五笔输入法,但其实原生的也不错的:无需安装,运行更稳定,没有各种跳转打开,无需询问完全权限......
  • STM32--CAN和RS485等半双工形式总线的多设备挂载接法详解
    在工业通信和自动化系统中,CAN总线和RS-485总线是两种常用的半双工通信总线。对于这些总线的多设备挂载接法,通常有两种方式:星型接法和手拉手型接法。本文将详细介绍这两种接法的特点、优缺点以及如何正确接线。星型接法星型接法是指所有设备都连接到一个中心节点,形成放射状......
  • STM32--STM32 微控制器详解
    STM32是STMicroelectronics(意法半导体)推出的一系列基于ARMCortex微控制器家族的产品。它们广泛应用于嵌入式系统领域,因其丰富的特性、低功耗和合理的价格而受到青睐。STM32的特点处理器核心:STM32微控制器基于不同的ARMCortex核心,如Cortex-M0、M3、M4、M7等。存储:包括闪......
  • STM32的USB接口介绍
    STM32微控制器系列提供了强大的USB功能,支持USB设备和主机模式。本文将详细介绍STM32的USB接口,包括其主要特征、寄存器和缓存映射、时钟要求以及如何通过代码实现USB通信。一、USB简介STM32的USB外设实现了USB2.0全速总线和APB总线间的接口。它支持USB挂起/恢复操作,可以停......