STM32学习和实践笔记(31):输入捕获实验

1.输入捕获介绍

  在定时器中断实验章节中我们介绍了通用定时器具有多种功能,输入捕获就是其中一种。STM32F1除了基本定时器TIM6TIM7,其他定时器都具有输入捕获功能。输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,通常用于测量输入信号的脉宽、测量 PWM 输入信号的频率及占空比。

  输入捕获的工作原理比较简单,在输入捕获模式下,当相应的 ICx 信号检测到跳变沿后,将使用捕获/比较寄存器(TIMx_CCRx)来锁存计数器的值。简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。下面我们以输入捕获测量脉宽为例,通过一个简图来介绍输入捕获的原理。 

  CNT计数的次数等于:有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间

上图以及公式N*ARR+CCRx2,简单解释如下:

首先,定时器在以一个固定次数不断重载并且计数,比如,重载值为1000,那么它就一直不断地从0计数到1000,然后再次从0计数到1000。与此同时,输入引脚在监测上升沿跳变,假定某一次计数到500的时候,监测到了一个上升沿,那么,这个时候就产生一个内部触发,定时器就立即重载,于是定时器马上从0开始再次计数,(所以,上图中T1的位置其实是错误的!)同时监测改为下降沿触发,开始监测下降沿!定时器从0开始计数后,有可能1000以前,比如,计到800,就监测到了下降沿,那么很简单,高电平的持续时间,就是800*一个计数的计数周期。如果计到1000后,仍然没有监测到下降沿,那么就从0开始计数,一直这样循环,直到发现下降沿为止。

2.输入捕获配置步骤

  接下来我们介绍下如何使用库函数对通用定时器的输入捕获进行配置。这个也是在编写程序中必须要了解的。其实输入捕获和前面定时器中断一样也是通用定时器的一个功能,因此还是要用到定时器的相关配置函数,具体步骤如下:(定时器相关库函数在stm32f10x_tim.c

stm32f10x_tim.h文件中)。

(1)使能定时器及端口时钟,并设置引脚复用器映射和引脚模式等

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;

(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等

voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*

TIM_TimeBaseInitStruct);

(3)设置通用定时器的输入捕获参数,开启输入捕获功能                              

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef*

TIM_ICInitStruct);

typedef struct

{

  uint16_t TIM_Channel; //通道

  uint16_t TIM_ICPolarity; //捕获极性

  uint16_t TIM_ICSelection;//映射

  uint16_t TIM_ICPrescaler;//分频系数

  uint16_t TIM_ICFilter; //滤波器长度

} TIM_ICInitTypeDef;

TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);

如果我们需要配置TIM5的通道1为输入捕获功能,并且为上升沿捕获

不分频、直接映射到TI,可以如下配置

TIM_ICInitTypeDef TIM_ICInitStructure;

TIM_ICInitStructure.TIM_Channel=TIM_Channel_1; //通道1

TIM_ICInitStructure.TIM_ICFilter=0x00;  //滤波

TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//捕获极性

TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数

TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到TI1

TIM_ICInit(TIM5,&TIM_ICInitStructure);

(4)开启捕获和定时器溢出(更新)中断                               

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);

(5)设置定时器中断优先级,使能定时器中断通道

NVIC初始化库函数是NVIC_Init()

(6)编写定时器中断服务函数

TIM5_IRQHandler

ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);

void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

TIM_SetCounter(TIM5,0); //定时器初值为0

(7)使能定时器

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

3.硬件电路

  本实验使用到硬件资源如下:

(1)D1指示灯

(2)K_UP按键

(3)串口1

(4)TIM5的通道1

D1指示灯用来提示系统正常运行,K_UP按键是接在PA0管脚上的,所以可以通过此按键输入一个高电平,通过串口1的printf函数打印捕获到的高电平时间。

4.编写输入捕获控制程序

  本实验所要实现的功能是:按下key_up键,产生一个高电平脉冲,使用TIM5CH1检测输入信号高电平脉宽,将检测的高电平脉宽时间通过printf函数打印出来,同时让D1指示灯不断闪烁表示系统正常运行。程序框架如下:

(1)初始化PA0管脚为TIM5通道1输入捕获功能,开启捕获和溢出中断等

(2)编写TIM5中断服务函数

(3)编写主函数

main.c:

#include "system.h"
#include "led.h"
#include "SysTick.h"
#include "usart.h"
#include "input.h"int main()
{u32 indata=0;u8 i=0;SysTick_Init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组LED_Init();USART1_Init(9600);TIM5_CH1_Input_Init(0xffff,71);//自动重载值设为最大,且计数频率为1M,每次计数为1us,这样计数的总数就是高电平的持续时间while(1){if(TIM5_CH1_CAPTURE_STAUS&0x80){indata=TIM5_CH1_CAPTURE_STAUS&0x3f;indata*=0xffff;indata+=TIM5_CH1_CAPTURE_VALUE;printf("高电平持续时间:%d us\r\n",indata);TIM5_CH1_CAPTURE_STAUS=0;//清空以便再次捕获}i++;if(i%20 ==0){led1=!led1;//LED1闪,用来指示主程序循环是否运行}delay_ms(50);}
}

               

input.c

#include "input.h"
#include "SysTick.h"u8 TIM5_CH1_CAPTURE_STAUS;//这个标志不仅用来判断是否产生了中断,同时也用来记录溢出中断的次数
u16 TIM5_CH1_CAPTURE_VALUE;//保存捕获到下降沿中断时,计数器的数值void TIM5_CH1_Input_Init(u16 period,u16 prescaler)
{GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//结构体变量声明TIM_ICInitTypeDef TIM_ICInitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能TIM5时钟GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;	//GPIO_Init(GPIOA,&GPIO_InitStructure);TIM_TimeBaseInitStructure.TIM_Period=period;   //装入函数传过来的自动装载值TIM_TimeBaseInitStructure.TIM_Prescaler=prescaler; //装入函数传过来的分频系数TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//1分频(没有分频)TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式:从0开始计数到自动重载值后溢出产生中断TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);//初始化TIM5各参数:自动重装值、分频系统、计数方式等TIM_ICInitStructure.TIM_Channel=TIM_Channel_1; //通道1TIM_ICInitStructure.TIM_ICFilter=0x00; //滤波TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//捕获极性设为上升沿TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到TI1TIM_ICInit(TIM5,&TIM_ICInitStructure);TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//开启捕获和定时器溢出(更新)中断//设置定时器中断优先级,使能定时器中断通道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_Cmd(TIM5,ENABLE );//使能定时器}void TIM5_IRQHandler(void)
{if((TIM5_CH1_CAPTURE_STAUS&0x80)==0)//在进入打印输出时,不检测、不捕获{if(TIM_GetITStatus(TIM5,TIM_IT_Update))//判断是否产生溢出中断	{if(TIM5_CH1_CAPTURE_STAUS&0x40){if((TIM5_CH1_CAPTURE_STAUS&0x3f)==0x3f)//处理高电平时间过长的情况{TIM5_CH1_CAPTURE_STAUS |= 0x80;TIM5_CH1_CAPTURE_VALUE=0xffff;} else{TIM5_CH1_CAPTURE_STAUS++;//保存定时溢出中断的次数}}}if(TIM_GetITStatus(TIM5, TIM_IT_CC1))//判断是否产生上升捕获中断{if(TIM5_CH1_CAPTURE_STAUS&0x40) //0x40 = 0100 0000,判断是否捕获到下降沿{TIM5_CH1_CAPTURE_STAUS |= 0x80;TIM5_CH1_CAPTURE_VALUE=TIM_GetCapture1(TIM5);TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);//重新改为上降沿触发}else //产生上升捕获后先进else,把定时器重载,以从0开始重新计数{TIM5_CH1_CAPTURE_STAUS =0;TIM5_CH1_CAPTURE_VALUE =0;TIM5_CH1_CAPTURE_STAUS|= 0x40;//这就是为在第二次捕获(即捕获到下降沿)时能进入上面的if语句里TIM_Cmd(TIM5,DISABLE );TIM_SetCounter(TIM5,0); //设定定时器初值为0以重新计数TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);//改为下降沿触发TIM_Cmd(TIM5,ENABLE );//使能定时器}}}TIM_ClearITPendingBit(TIM5, TIM_IT_Update|TIM_IT_CC1);//清除溢出标志}

input.h

#ifndef _input_H
#define _input_H#include "system.h"
extern u8 TIM5_CH1_CAPTURE_STAUS;
extern u16 TIM5_CH1_CAPTURE_VALUE;void TIM5_CH1_Input_Init(u16 period,u16 prescaler);
void TIM5_IRQHandler(void);#endif

程序烧写到开发板运行,实验结果如下:实验是成功的!

            

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/14213.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【博客主页】博客主旨 精华

前言 与博客园不同, 最近CSDN在进行资本化的转型.其一部分的VIP代码和小册我也有相关消费, 个人认为是一部分做的比较成过, 另一部分又不是特别成功. 其CSDN博客已经失去其原本技术交流的意义, 变成一种免费的知识引流和收费交流. 这其实与我们的开源社区背道而驰, 但是又吸引…

世界电信日 | 紫光展锐以科技创新支撑数字经济可持续发展

专注科技创新,打造全球数字经济技术基石 紫光展锐坚持科技创新,为数字经济蓬勃发展提供基石力量。 面对5G-A技术的巨大潜力,紫光展锐与众多生态伙伴紧密合作,积极推动5G-A的商用进程。紫光展锐提出的两项R18 eRedCap演进方案已被3GPP标准采…

为什么要实现设备之间的互通?

设备之间的互通是电信设备的普遍性要求,特别是在接入网领域中,不同厂商的局端设备与用户端(终端)设备之间的互通显得尤其重要。 一、互通能为产业链的各个环节带宽积极影响。 (1)对用户而言,互…

安装新版的Ubuntu WSL以使能BBR拥塞控制算法

【多次尝试成功的方案】通过> wsl - -list -online列出可以安装的版本,用命令> wsl --install -d Ubuntu-24.04 安装。 【未成功的方案】通过挂在ubuntu24.04.iso到E盘后,用命令> wsl --import Ubuntu24.04 C:\WSL\Ubuntu24.04\ E:\ --versio…

Redis系统架构中各个处理模块是干什么的?no.19

Redis 系统架构 通过前面的学习,相信你已经掌握了 Redis 的原理、数据类型及访问协议等内容。本课时,我将进一步分析 Redis 的系统架构,重点讲解 Redis 系统架构的事件处理机制、数据管理、功能扩展、系统扩展等内容。 事件处理机制 Redis…

API-BigInteger、BigDecimal

BigInteger: demo1: package BigInteger;import java.math.BigInteger; import java.util.Random;public class demo1 {public static void main(String[] args) {//获取一个随机最大整数BigInteger bd1 new BigInteger(5, new Random());System.out.println(bd1…

SSMP整合案例第一步 制作分析模块创建与开发业务实体类

制作分析 我们要实现一个模块的增删改查 实际开发中mybatisplus用的不多,他只能对没有外键的单表进行简单的查询 但在这个案例中我们还是选择mybatisplus开发 模块创建 我们把所有服务器都放在一起 就不用前后端分离 我们尝试用后端开发进行全栈开发 新建项目添…

macos brew安装多版本protobuf,切换指定版本protobuf 为默认版本方法

protobuf 不同的版本语法相差很大, 而在不同的项目中可能使用的protobuf版本也不同,所以我们的电脑就可能需要安装多个版本的protobuf, 下面介绍macos下如何通过brew安装多版本和设置想要的默认版本的方法 安装,则可以先执行 bre…

Thinkphp3.2.3网站后台不能访问如何修复

我是使用Thinkphp3.2.3新搭建的PHP网站,但是网站前台可以访问,后台访问出现如图错误: 由于我使用的Hostease的Linux虚拟主机产品默认带普通用户权限的cPanel面板,对于上述出现的问题不清楚如何处理,因此联系Hostease的…

(3)医疗图像处理:MRI磁共振成像-快速采集--(杨正汉)

目录 一、磁共振快速采集技术基础 1.K空间的基本特点 2.快速成像的理由: 3.快速成像的硬件要求: 二、磁共振快速采集技术 1.采集更少的相位编码线 2.平行采集技术PAT 3.其他与快速采集有关的技术 1)部分回波技术 2)频率…

java实现一个动态监控系统,监控接口请求超时的趋势

目录 整体思路案例实现1. 数据收集2. 数据聚合3. 趋势分析4. 异常检测5. 异常处理定时任务 整体思路 理想情况下,你可以实现一个简单的动态监控算法来检测渠道请求的响应时间趋势,并在发现频繁超时的情况下进行处理。以下是一个可能的算法框架&#xff…

Oracle表关联更新几种方法

1、测试表及数据准备 create table T_update01(ID int ,infoname varchar2(32),sys_guid varchar2(36)); create table T_update02(ID int ,infoname varchar2(32),sys_guid varchar2(36));insert into T_update01 select 1,N1_updateName,sys_guid() from dual union select …

java如何获取IP和IP的归属地?

在Java中,获取IP地址通常指的是获取本地机器的IP地址或者通过某种方式(如HTTP请求)获取的远程IP地址。代码案例如下: 而要获取IP的归属地(地理位置信息),则通常需要使用第三方IP地址查询服务,我…

c++ 排序算法merge使用要求

在C中&#xff0c;std::merge是一个算法&#xff0c;它用于合并两个已排序的范围&#xff08;例如数组或容器中的一部分&#xff09;到一个新的范围中。这个函数在<algorithm>头文件中定义。 输入范围必须已排序 std::merge要求输入的两个范围都必须是已排序的&#xf…

23种设计模式顺口溜

口诀&#xff1a; 原型 抽风 &#xff0c;单独 建造 工厂 &#xff08;寓意&#xff1a;&#xff08;这里代指本来很简单的东西&#xff0c;却要干工厂这里复杂的业务&#xff09; 抽风&#xff1a;抽象工厂单独&#xff1a;单例桥代理组合享元适配器&#xff0c;&#xff0…

Microsoft VBA Excel 去重小工具

问题简述 在本工作表中&#xff0c;A1:B3单元格样式如下&#xff0c;通过名称管理器B列的单元格被命名为"LinkFile"、“SheetName”、“InputArea”&#xff0c;请实现以下功能&#xff1a;读取Excel文件中的数据&#xff0c;去除重复的数据&#xff0c;并记录每个数…

亚马逊云科技介绍

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、亚马逊云科技云计算1.1 云计算的优势 二、领先的云平台三、亚马逊云科技区域的全球网络…

最简单的,在mac笔记本上安装Unix-v6系统,进行“Unix内核源码剖析”

Unix V6 已经是 1975 年的系统了&#xff0c;但是其源代码拢共只有 1w 行左右&#xff0c;并且使用了 C 语言&#xff08;K & R 之前的标准&#xff09;&#xff0c;还是现代操作系统的鼻祖&#xff0c;所以说是初学者最好的研究对象。 安装模拟器 brew install simh …

【MySQL精通之路】SQL优化(1)-查询优化(3)-索引合并

主博客&#xff1a; 【MySQL精通之路】SQL优化(1)-CSDN博客 上一篇&#xff1a; 【MySQL精通之路】SQL优化(1)-查询优化(2)-范围查询优化-CSDN博客 下一篇&#xff1a; 目录 1.索引合并-交集访问算法 2.索引合并联合访问算法 3.索引合并-排序联合访问算法 4.影响索引合…

平衡发展与环保:理性看待地下式污水处理厂建设|中联环保圈

这些年啊&#xff0c;随着城市化进程越来越快&#xff0c;还有环境保护意识不断提高&#xff0c;这地下式污水处理厂慢慢就成了热门的建设趋势了。据相关统计&#xff0c;全球现在运行着 200 多座地下式污水处理厂呢&#xff0c;咱国家建成和在建的数量也差不多快到 200 座啦。…