STM32的通用定时器的触发输出和从模式测量输入信号的占空比(寄存器和HAL库两种代码实现方式)

本文是下文的续篇

用通用定时器的输入捕获功能测量输入信号周期和频率(寄存器和HAL两种代码实现方式)-CSDN博客

通用定时器框图:

定时器的触发信号分两大类:

触发输入信号(TRGI,本定时器就处于主从模式中的从模式):从外部来,或者从自己的输入通过来到本定时器。

功能:控制定时器具体操作,例如:复位,使能,计数(呼吸灯和测量输入信号的周期和频率都是默认内部时钟控制计数,来一个上升沿就计数+1,溢出就触发溢出事件,本例子我们就是选用输入捕获信号来控制本定时器的复位操作)

触发输出信号(TRGO,主模式):用本定时器输出到其他定时器或其他外设的信号,用于与其他定时器的级联(触发定时器的一些工作)或触发一些其他外设工作

注意:触发输入信号 != 本定时器时钟源。在常规输入捕获配置中,TRGI仅作为触发源,定时器的时钟源仍由APB总线决定。若需使用外部信号作为时钟源,需额外配置外部时钟模式

相关寄存器介绍 

 配从模式

100:上升沿和下降沿都会发生TI1F_ED,注意:边沿检测器只是决定捕获寄存器捕获上升沿还是

下降沿,不会滤波和整波

 我们选用101模式为例子,实现通用定时器的触发输出和从模式测量输入信号的占空比:

TI1经过滤波器和边沿检测器给到T1FP1和T2FP2上,T2FP2映射到IC2上

IC1捕获高电平有效(CCER_CC1P),IC2捕获低电平有效(CCER_CC2P)

IC1捕获到第一次高电平时计数器清零后记录IC2捕获到第一次低电平的自动将计数器数值给到CCR2,即为高电平在一个周期的时间,当IC1捕获到第二次高电平时,自动计数器值给到CCR1,那么CCR1/CCR2就是占空比

 配置通道:

配捕获选择:注意ETP和TIMx_ETP外部输入相关,我这是截多了

100:复位模式:输入信号给到TRGI,依赖输入信号的周期触发本定时器的更新事件

配置意义:捕获比较寄存器当捕获到上升沿还是下降沿时,将计数器的值赋值给自己(CCR) 

 寄存器代码实现:

和上篇代码搭配使用:

用通用定时器的输入捕获功能测量输入信号周期和频率(寄存器和HAL两种代码实现方式)-CSDN博客


//注意要看功能框图找寄存器,根据业务要求写代码,不要一个一个寄存器找啊,看啊,效率太低

void Driver_TIM4_Init(void)
{
    
//和一致用通用定时器的输入捕获功能测量输入信号周期和频率(寄存器和HAL两种代码实现方式)中代码一致,只是多添加了通道2的配置,删除了中断,以及配置了时钟来源

//配置TIM4时钟来源:TRGI TS-101
TIM4->SMCR |= TIM4_SMCR_TS_0;
TIM4->SMCR &=~TIM4_SMCR_TS_1;
TIM4->SMCR |= TIM4_SMCR_TS_2;

//配置从模式为复位模式100
TIM4->SMCR &=~TIM4_SMCR_SMS_0;
TIM4->SMCR &=~TIM4_SMCR_SMS_1;
TIM4->SMCR |= TIM4_SMCR_SMS_2;

    /* 4.4 通道1配置为输入,并把信号映射到IC2  CC1S=01*/
    TIM4->CCMR1 &= ~TIM_CCMR1_CC2S_0;
    TIM4->CCMR1 |= TIM_CCMR1_CC2S_1;

    /* 4.3 通道2: 上升沿 CCER_CC1P=0(0:不反相:捕获发生在IC2的上升沿;当用作外部触发器时,IC2不反相) , 1下降沿捕获*/
    TIM4->CCER |= TIM_CCER_CC1P;

    /* 4.6 通道2输入捕获使能 CCER_CC1E=1 */
    TIM4->CCER |= TIM_CCER_CC2E;

    /* 4.7 不需要开启通道捕获中断 和不用配优先级了,因为在从模式下通过输入信号做本定时器的复位处理*/

}

double TIM4_GetPWMDutyCycle(void)
{
//占空比
return TIM4->CCR2/TIM4->CCR1;

}

#include <stdio.h>
#include "stm32f4xx_hal.h"

#define BUFFER_SIZE 64

void Send_Data(UART_HandleTypeDef *huart, float t, float f,double c) {
    char buffer[BUFFER_SIZE];
    int len = snprintf(buffer, sizeof(buffer), "t=%.4fms, f=%.4fHz , duty = %.2lf%% \r\n", t, f,c);
    
HAL_UART_Transmit(huart, (uint8_t*)buffer, len,0xff);
}

//这个处理函数放主函数里
Send_Data(&huart1, Driver_TIM4_GetPWMCycle(),  Driver_TIM4_GetPWMFreq(),TIM4_GetPWMDutyCycle()*100);

HAL库代码实现含CubeMX配置:

TI1经过滤波器和边沿检测器给到T1FP1和T2FP2上,T2FP2映射到IC2上

IC1捕获高电平有效(CCER_CC1P),IC2捕获低电平有效(CCER_CC2P)

IC1捕获到第一次高电平时计数器清零后记录IC2捕获到第一次低电平的自动将计数器数值给到CCR2,即为高电平在一个周期的时间,当IC1捕获到第二次高电平时,自动计数器值给到CCR1,那么CCR1/CCR2就是占空比

按下面的选择配置: Input Capture indirect mode用T1映射到IC2

 Slave Mode 从属模式的配置已经在上面定死了,所以下面 Slave Mode Controller只有一种选择

由于我们没有用到TRGO就默认值即可,TIM5的配置看用通用定时器的输入捕获功能测量输入信号周期和频率(寄存器和HAL两种代码实现方式)-CSDN博客

是一样的,注意TIM5不用配TRGI和TRGO 

Polarity Selection:选择 IC1捕获高电平有效(CCER_CC1P),IC2捕获低电平有效(CCER_CC2P)

//在主函数中开启通道
//开启定时器5通道2
HAL_TIM_PWM_Start_IT(&hitm5,TIM_CHANNEL_1);
//开启定时器4通道1
HAL_TIM_IC_Start_IT(&hitm4,TIM_CHANNEL_1);
//开启定时器4通道2
HAL_TIM_IC_Start_IT(&hitm4,TIM_CHANNEL_2);

注意我们TIM4不再需要中断处理,因为:


/* 返回PWM的周期 ms*/
double Driver_TIM4_GetPWMCycle(void)
{
    return __HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_1) / 1000.0;
}

/* 返回PWM的频率 */
double Driver_TIM4_GetPWMFreq(void)
{
    return 1000000 / __HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_1);
}

double TIM4_GetPWMDutyCycle(void)
{

//占空比CCR2/CCR1
return __HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_2)/__HAL_TIM_GetCompare(&htim4, TIM_CHANNEL_1);

}
#include <stdio.h>
#include "stm32f4xx_hal.h"

#define BUFFER_SIZE 64

void Send_Data(UART_HandleTypeDef *huart, float t, float f,double c) {
    char buffer[BUFFER_SIZE];
    int len = snprintf(buffer, sizeof(buffer), "t=%.4fms, f=%.4fHz , duty = %.2lf%% \r\n", t, f,c);
    
HAL_UART_Transmit(huart, (uint8_t*)buffer, len,0xff);
}

//这个处理函数放主函数里
Send_Data(&huart1, Driver_TIM4_GetPWMCycle(),  Driver_TIM4_GetPWMFreq(),TIM4_GetPWMDutyCycle()*100);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值