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,一经查实,立即删除!

相关文章

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

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

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

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

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

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

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

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

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

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

23种设计模式顺口溜

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

亚马逊云科技介绍

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

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

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

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

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

基于transformers框架实践Bert系列4-文本相似度

本系列用于Bert模型实践实际场景,分别包括分类器、命名实体识别、选择题、文本摘要等等。(关于Bert的结构和详细这里就不做讲解,但了解Bert的基本结构是做实践的基础,因此看本系列之前,最好了解一下transformers和Bert…

STM32入门笔记(02):USART串口通信注意事项笔记(SPL库函数版)

这是通过串口通信发送过来的数据,里面包括了故障码,电压,电流,频率等信息,请你用STM32f103系列单片机的串口1读取该数据并解析出电压和电流是多少? 要用STM32F103系列单片机的串口1读取并解析发电机上的逆…

【Django项目】 音乐网站spotify复刻

代码:https://github.com/tomitokko/spotify-clone 注:该项目不是自己提供mp3文件,而是使用spotify 的api接口获取。

MySQL主从复制故障:“ Slave_SQL_Running:No“ 两种解决办法

问题 今天搭建MySQL的主从复制,查看从机状态时show slave status\G,发现这个参数为NO,导致主从复制失败。 Slave_SQL_Running: No 后面上网查阅了一下资料,大概就是因为在连接支持数据库后,也就是这个命令后&#xff…

c-lodop 打印面单 内容串页

场景:使用c-lodop程序调取打印机连续打印多张快递单时,上页内容,打到了下一页了 问题原因: 由于是将所有面单内容放到了一个页面,c-lodop 在打印时,发现一页放不下,会自动分割成多页 页面元素…

【在Postman中,如果后端返回的是String类型的数据但不是JSON格式,报错】

在Postman中,如果后端返回的是String类型的数据但不是JSON格式 问题描述解决办法 postman后端返回的String数据,不是json,怎么设置结果的接收? 问题描述 在postman中测试接口,报错Error:Abort,或者显示返回数据校验失…

coveralls使用pytest进行本地测试时报错SyntaxError: invalid escape sequence \S

## 错误复现: git clone gitgithub.com:TheKevJames/coveralls-python.git cd coveralls-python poetry install poetry run pytest## 错误内容: ## 完整的打印信息 test session starts platform darwin -- Python 3.8.18, pytest-8.2.1, pluggy-1.5.…

使用 LlamaParse 进行 PDF 解析并创建知识图谱

此 Python 笔记本提供了有关利用 LlamaParse 从 PDF 文档中提取信息并随后将提取的内容存储到 Neo4j 图形数据库中的综合指南。本教程在设计时考虑到了实用性,适合对文档处理、信息提取和图形数据库技术感兴趣的开发人员、数据科学家和技术爱好者。 该笔记本电脑的主…

可视化大屏,不搞点3D效果,感觉有点对不起观众呢。

使用3D模型可以为可视化展现增加更多的维度和真实感,提供更直观、生动的视觉效果。以下是一些3D模型在可视化展现中的作用: 增强沉浸感:通过使用3D模型,可以让观众感受到更真实的场景和物体,增强他们的沉浸感。这有助…