STM32快速复习(三)定时器中断(TIM)部分三 配置输入比较模块

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

IC(Input Capture)输入捕获;输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
每个高级定时器和通用定时器都拥有4个输入捕获通道
可配置为PWMI模式,同时测量频率和占空比
可配合主从触发模式,实现硬件全自动测量

输出配置可以生成PWM波形,输入捕获用于读取PWM波形


一、输入比较是什么?输入比较有什么用?

在这里插入图片描述
时基单元: 与之前的相同,CNT就是就是测周法用于计时的东西。注意测频率的标准频率是预分频之后的频率。
TI1FP1: 兵分两路,一路用于触发转运CNT到CCR,一路用于触发清零CNT。硬件执行时肯定是先转运再清零,或者是两者同时非阻塞进行。
读取CCR值: 需要测频率时就读取CCR值,不需要测频率时整个电路自动运行,也不占用软件资源。
关于CNT: 计数最大值是65535,所以待测频率不能太低。
在这里插入图片描述

在这里插入图片描述
使用两个通道同时捕获一个引脚,可以同时测量周期和占空比。
TI1FP1: 上升沿触发,和之前相同。通道1的捕获寄存器CCR1表示整个周期的时间。
TI1FP2: 配置为下降沿触发,通过交叉通道触发通道2的捕获单元。于是通道2的捕获寄存器CCR2就表示高电平周期。
在这里插入图片描述
TIMx_CH1 ~ TIMx_CH4: 4个输入引脚,参考引脚定义表可以知道引脚复用在哪个位置。
三输入异或门: 数据选择器可以使其不起作用。起作用时主要是为三相无刷电机服务,此时三个输入接三相无刷电机的霍尔传感器(检测转子位置),然后这个定时器就可以作为换相电路的接口定时器,驱动换相电路工作。本节不涉及。
输入滤波器: 对输入信号进行滤波,避免一些高频的毛刺信号误触发。
边沿检测器: 与外部中断类似,可以选择高电平触发、低电平触发等。
TI1FP1、TI1FP2: 是两套独立的信号,都经过各自的滤波器、极性选择,进而输出到后续电路。之所以设计成交叉电路,主要有两个好处:可以灵活切换后续捕获电路的输入,而不需要重新初始化;将一个引脚输入同时映射到两个捕获单元,是PWMI模式的经典结构。下面三路的信号同理。
TRC1: 来源于时钟源的选择,也可以作为输入捕获信号的输入。
预分频器: 对信号进行分频,其输出的信号触发捕获电路进行工作:每来一个触发信号,CCR就会读取一次CNT的值,同时发生一个捕获事件ICxPS,这个事件会在状态寄存器置标志位,同时也可以产生中断(捕获中断)。
例(测周法): 比如可以配置上升沿触发捕获,没来一次上升沿,CNT就将值转运到CCR,由于CNT由内部时钟源驱动,此时CNT的值实际上就是两次上升沿之间的时间间隔,于是就实现了测周法。
注:要想在一次捕获后将CNT清零,可以使用 主从触发模式 配置硬件自动完成。

在这里插入图片描述

二、输入比较标准库函数及示例

1.引入库

(1)TIM_ICInit 【常用】:初始化输入捕获单元,只能配置单一通道。注意与输出比较模块的四个通道各自有一个初始化函数不同,输入捕获模块的四个通道共用一个初始化函数。这是
因为有交叉通道的配置,整合在一个函数中会比较方便。
(2)TIM_PWMIConfig 【常用】:初始化输入捕获单元。可以快速的配置通道1和通道2的PWMI模式。
(3)TIM_ICStructInit :给输入捕获结构体赋一个初值。
(4)TIM_GetCapture1 【重要】:读取输入捕获通道1的 输入/捕获寄存器CCR1 的值。第二、三、四路同理。
下面四个函数是配置主从触发模式:
(5)TIM_SelectOutputTrigger 【常用】:选择主模式的输出触发源TRGO。
(6)TIM_SelectInputTrigger 【常用】:选择从模式的输入触发源TRGI。
(7)TIM_SelectSlaveMode 【常用】:选择从模式要执行的操作。
(8)TIM_SelectMasterSlaveMode :选择是否使能主从触发模式。
下面是单独修改输入捕获通道某些参数:
TIM_SetIC1Prescaler :单独配置输入捕获通道1的预分频值。第二、三、四路同理。

2.读入数据

代码如下(示例):
PWM_Init();
PWM_SetDuty(50);//占空比(单位:%)
PWM_SetFreq(10000); //PWM频率(单位:Hz)

   InputCapture_Init();
   上述代码放入主函数中
 #include "stm32f10x.h"                  // Device header
 //输入捕获初始化-TIM3输入捕获通道1-PA6
 void InputCapture_Init(void){
    //1.开启外设时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
     //2.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);
    //3.时基单元配置
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period = 0xffff;
    TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
    TIM_Cmd(TIM3, ENABLE);
    //4.输入捕获单元配置
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//输入捕获通道1
    TIM_ICInitStructure.TIM_ICFilter = 0x3;
    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);
    //4.从模式配置
    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
 }
 //根据输入捕获的值计算频率
//计算范围:16HZ~500kHz,较为精准的范围:16Hz~10kHz,高频分辨率约为15Hz
 uint32_t InputCapture_GetFreq(void){
    return (uint32_t)1000000/(uint32_t)(TIM_GetCapture1(TIM3)+1);
 }
#include "stm32f10x.h"                  // Device header
 //PWMI模式初始化-TIM3输入捕获通道1-PA6
 void InputCapture_PWMIInit(void){
    //1.开启外设时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    //2.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);
    //3.时基单元配置
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period = 0xffff;
    TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
    TIM_Cmd(TIM3, ENABLE);
    //4.输入捕获单元配置
    //输入捕获通道1
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel     = TIM_Channel_1;//输入捕获通道1
    TIM_ICInitStructure.TIM_ICFilter    = 0x3;
    TIM_ICInitStructure.TIM_ICPolarity  = TIM_ICPolarity_Rising;//上升沿计数
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//不选择交叉通道
    TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);//注意只是这里换了!!!使用该函数不需要再初始化通道2
    //4.从模式配置
    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
 }
 //根据输入捕获的值计算占空比-PWMI模式初始化才能调用
//计算范围:1%~100%,占空比分辨率1%
 uint16_t InputCapture_GetDuty(void){
 //    float duty;
 //    duty = ((float)(TIM_GetCapture2(TIM3)+1))/((float)(TIM_GetCapture1(TIM3)+1));
 //    return (uint16_t)(duty*100);
    return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1);
 }
 //别忘了将这两个函数在InputCapture.h头文件中声明

总结

输入比较模块简单来讲就是一个计数模块
通过读取外部频率测量的CNT计数值,进行中断程序的触发。
看懂电路图,看懂例子。会使用即可。毕竟STM32只是工具。
但还是强烈建议自己敲敲所有代码。最开始学51的时候,好多代码无法理解,纯纯是敲出来的,敲完再改部分参数,再烧录,看效果。
通过各种修改参数看效果,再网上看的帖子;会的定时器,会的IIC。可以说,我单片机就是这么入门的。。。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值