stm32 输入捕获学习(一)
输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能。STM32 的输入捕获,简单地说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)中。
1. 相关寄存器介绍
1) 捕获/比较模式寄存器 (TIMx_CCMRx)
当在输入捕获模式下使用的时候,对应上图的第二行描述,从图中可以看出,TIMx_CCMR1 明显是针对 2 个通道的配置,低八位[7:0]用于捕获/比较通道 1 的控制,而高八位[15:8]则用于捕获/比较通道 2 的控制。同理,CCMR2 这个寄存器用来控制通道 3 和通道 4。今天的实验,我们用到的是 TIM5 的捕获/比较通道 1。
(1)CC1S[1:0],这两个位用于 CCR1 的通道配置,这里我们设置 CC1S[1:0]=01,也就是配置 IC1 映射在 TI1 上。如果不理解没有关系,看图就知道了。
从图中可以知道,IC1有三个输入源,分别是TI1,TI2,TRC。
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 这是通过库函数配置,映射到TI1。
头文件(stm32f10x_tim.h)定义如下:
#define TIM_ICSelection_DirectTI ((uint16_t)0x0001)
#define TIM_ICSelection_IndirectTI ((uint16_t)0x0002)
#define TIM_ICSelection_TRC ((uint16_t)0x0003)
(2)IC1F[3:0]
表格中的f_ck_int 是定时器的输入频率(TIMxCLK),f_dts 则是根据 TIMx_CR1 的 CKD[1:0]来确定。
上图就是TIMx_CR1寄存器。
#define TIM_CKD_DIV1 ((uint16_t)0x0000)
#define TIM_CKD_DIV2 ((uint16_t)0x0100)
#define TIM_CKD_DIV4 ((uint16_t)0x0200)
假定选IC1F[3:0]=0101,即采样频率为fDTS/2, N=8;
选CKD[1:0]=01,即 tDTS = 2 × tCK_INT;并假定 fCK_INT=72MHz。
这时可以算出,采样频率为72MHz/2/2=18MHz.
1/(18MHz)*8 = 0.4444us = 444.4ns.
因为N=8,所以滤波器可以滤除掉输入端小于444.4ns的脉冲。
“数字滤波器由一个事件计数器组成,它记录到N个事件后会产生一个输出的跳变”,这句话可以这样理解:
当滤波器连续采样到N个有效电平时,就输出这个有效电平。
当滤波器没有连续采样到N个有效电平时,再从0开始计数,输出一直保持上一次输出的有效电平。
例如:滤波器上一次输出是高电平,本次连续采样到(N-1)个高电平,但第N个是个低电平,那么滤波器仍然保持上次输出的高电平,并重新开始计数,记录1次低电平,如果其后采样的(N-1)个也是低电平,此时滤波才输出低电平,于是一个下降沿才出现在IC1上。
(3)IC1PSC[1:0]
这里的“事件”指的是上升沿或者下降沿,具体是哪个由TIMx_CCER寄存器的CCxP位决定。
2)捕获/比较使能寄存器:TIMx_CCER
所以,要使能输入捕获,必须设置 CC1E=1,而 CC1P 则根据自己的需要来配置(捕获发生在上升沿还是下降沿)。
3) DMA/中断使能寄存器(TIMx_DIER)
在实验中,我们需要允许位0和位1的中断。
#define TIM_IT_Update ((uint16_t)0x0001)
#define TIM_IT_CC1 ((uint16_t)0x0002)
#define TIM_IT_CC2 ((uint16_t)0x0004)
#define TIM_IT_CC3 ((uint16_t)0x0008)
#define TIM_IT_CC4 ((uint16_t)0x0010)
对应的库函数是:TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
4) 捕获/比较寄存器 (TIMx_CCRx)
该寄存器用来存储捕获发生时,TIMx_CNT的值,我们从 TIMx_CCR1 就可以读出通道 1 捕获发生时刻的 TIMx_CNT 值,通过两次捕获(一次上升沿捕获,一次下降沿捕获)的差值,就可以计算出高电平脉冲的宽度。
2. 实验设计
通过TIM3产生一路PWM(从PB5输出),把PB5连接到PA0上,PA0和 TIM5_CH1是同一个管脚。利用TIM5_CH1的输入捕获功能,测量出PWM的宽度。
3. 参考代码
//TIM5_CH1输入捕获配置
void TIM5_Cap_Init(u16 arr,u16 psc)
{
TIM_ICInitTypeDef TIM5_ICInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5时钟 //TIM5的配置
TIM_TimeBaseStructure.TIM_Period = arr; //重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //tDTS = tCK_INT
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //TIM5输入捕获配置
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //我们用通道1
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //无预分频器
TIM5_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 ,无滤波器
TIM_ICInit(TIM5, &TIM5_ICInitStructure); //中断优先级配置
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//打开更新中断和捕获中断 TIM_Cmd(TIM5,ENABLE ); //使能定时器5 }
#define START 0X01
#define WAIT_RISING 0X02
#define WAIT_FALLING 0X03 u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
u32 a[500] = {0}; //存放电平宽度
u32 i = 0; //数组下标
u8 overflow = 0; //记录定时器更新中断的次数
u8 state = START; //定时器5中断服务程序
void TIM5_IRQHandler(void)
{ if(i<500)
{
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
{
++overflow;
} if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获事件
{
if(state == START) //初始状态
{
overflow = 0;
TIM_SetCounter(TIM5,0);
state = WAIT_FALLING;
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置为下降沿捕获
}
else if(state == WAIT_RISING) //等待上升沿
{
TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);
a[i++] = TIM5CH1_CAPTURE_VAL + overflow*65536; overflow = 0;
TIM_SetCounter(TIM5,0);
state = WAIT_FALLING;
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置为下降沿捕获 }
else // wait falling
{
TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM5);
a[i++] = TIM5CH1_CAPTURE_VAL + overflow*65536; overflow = 0;
TIM_SetCounter(TIM5,0);
state = WAIT_RISING;
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置为上升沿捕获 }
}
} TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 TIM3_PWM_Init(999,71); // 72/(71+1)=1MHz, T=1us*(999+1) = 1ms
TIM_SetCompare2(TIM3,650); TIM5_Cap_Init(0XFFFF,71); //以1MHz频率计数
while(1)
{
;
}
}
4.实验结果
1) 仿真图
PWM 高电平= 350us, 低电平=650us
2) 得出的数组
高电平:347us, 低电平 647us
结论:实验OK
stm32 输入捕获学习(一)的更多相关文章
- stm32 输入捕获学习(二)
(本文参考STM32 开发指南 V1.3 -- ALIENTEK 战舰 STM32 开发板库函数教程 ) 1. 实验设计 我们用 TIM5 的通道 1(PA0)来做输入捕获,捕获 PA0 上高电 ...
- STM32输入捕获模式设置并用DMA接收数据
参考: STM32的PWM输入模式设置并用DMA接收数据 Input capture mode The input stage samples the corresponding TIx input ...
- STM32 输入捕获配置
在STM32 的定时器,除了 TIM6 和 TIM7,就是通过检测 TIMx_CHx 上的 边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候, 将当时定时器 的值(TIMx_CNT) 存放到对 ...
- [置顶]
STM32 输入捕获的脉冲宽度及频率计算
输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.以下是对脉冲宽度及频率的计算. 1.脉冲宽度 如下图所示,采集该高电平脉冲 ...
- STM32——输入捕获实验原理及配置步骤
输入捕获实验原理及配置步骤 一.输入捕获概念 STM32的输入捕获,简单的说就是通过检测 TIMx_CHx (定时器X的通道X)上的 边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定 ...
- STM32 输入捕获的脉冲宽度及频率计算
输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.以下是对脉冲宽度及频率的计算. 1.脉冲宽度 如下图所示,采集该高电平脉冲 ...
- stm32 输入捕获
根据定时器的计数频率,我们就可以算出t1-t2的时间,从而得到高电平脉宽 计算公式 N * ARR + CCRx2 首先设置定时器通道为上升沿捕获,这样在t1时刻,就会捕获到当前的CNT值,然后立即清 ...
- STM32输入捕获TIM2四通道
相比于一通道,原子的例程里因为清了计数时间,所以要对程序进行修改. 记录上升沿后的计数,然后记录下降沿的计数.相减后计算高电平时间,对于定时器中断间隔的边界要分开处理. 这里因为我的接收机时间是1ms ...
- stm32寄存器版学习笔记06 输入捕获(ETR脉冲计数)
STM32外部脉冲ETR引脚:TIM1-->PA12;TIMER2-->PA0:TIMER3-->PD2;TIMER4-->PE0… 1.TIM2 PA0计数 配置步骤 ①开启 ...
随机推荐
- Java50道经典习题-程序29 求矩阵对角线之和
题目:求一个3*3矩阵对角线元素之和分析:利用双重for循环控制输入二维数组,再将a[i][i]累加后输出. 例如:下面矩阵的对角线之和为24 1 4 6 2 5 3 9 7 8 public cla ...
- JavaScript知识体系索引
JavaScript 参考手册 www.w3school.com.cn JavaScript基础语法 JavaScript的数据类型 Javascript的对象分类 JavaScript内置对象 Ja ...
- c#写对象来读取TXT文本文件
本博文让你知道怎样写对象,怎样读取文本文件,怎样根据实际条件判断与获取需要的文本行.参考下面网友的问题,根据源文来看,有些行输出的格式,需要把“,”替换为空格. 第一行还附加入后面的子行每一行的后面, ...
- NMS---非极大值抑制
在物体检测中,NMS(Non-maximum suppression)应用十分广泛,其目的是为了消除多余的框,找到最佳的物体检测的位置.在RCNN系列算法中,会从一张图片中找出很多个候选框(可能包含物 ...
- 前端基础:call,apply,bind的的理解
背景 前两天在做小程序的需求的时候用到bind的时候才想起自己对这三的东西的了解比较浅薄,这个时候用的时候就有点怕.时候还是要好好学习下,理解下怎么玩. 正文 先说call 和 apply吧:ECMA ...
- [Django笔记] views.py 深入学习
views.py 是django MTV 中的主要逻辑层,相当于MVC中的 Controller 以下的实例都基于这样一个路由表: urlpatterns = [ url(r'^(index)?$', ...
- AngularJS(一)理论篇
前言 大概今年春天的时候,自己对这个词产生了兴趣,那会只是简单的查了一下,并没有深入研究过这部分知识块,现在终于开始接触这些东西. 内容 AngularJS在web应用方面是一个非常完美的JavaSc ...
- P1402 酒店之王 最大流
\(\color{#0066ff}{ 题目描述 }\) XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该 ...
- 关于MVC模型的NSNotification用法
对于iOS开发开发者, Model View Controller 模型能帮你快速理清开发思路,最近在使用Model给Controller传递数据时候了解了关于 NSNotification的一些用法 ...
- 阿里云服务器部署Tornado应用指南
本篇详细介绍tornado应用部署到阿里云服务器上的全过程. Tornado程序地址:github https://github.com/ddong8/ihasy.git 准备工作:阿里云服务器Cen ...