STM32的HAL库开发-通用定时器输入捕获实验

一、通用定时器输入捕获部分框图介绍

1、捕获/比较通道的输入部分(通道1)

首先设置 TIM_CCMR1的CC1S[1:0]位,设置成01,那么IC1来自于TI1,也就是说连接到TI1FP1上边。设置成10,那个IC1来自于TI2,连接到TI2FP1上。设置成11,将IC1连接到TRC上边。

假设IC1连接到TI1FP1上,那么TIMx_CH1作为输入,首先来到一个滤波器,滤波器需要设置TIMx_CCMR1的ICF[3:0]位设置滤波方式,配合着通过设置TIMx_CR寄存器的CKD[1:0]位,设置采样频率fCKD。这个在前面通用定时器讲过。

然后输入信号来到边沿检测器,通过设置TIMx_CCER的CC1P位设置边沿检测方式。设置之后上升沿或者下降沿只有一个信号能进来,然后经过一个捕获分频器,通过设置TIMx_CCMR1的IC1PS[1:0]位,设置捕获分频系数。

最后使能TIMx_CCER的CC1E位,信号就来到了捕获/比较寄存器了。

2、捕获/比较通道1的主电路---输入部分

首先CC1S需要设置成输入模式,同时将CC1E设置为1,使能捕获。图中IC1PS信号来自于前面的分频后的捕获信号。 经过一个与门结果为1,上面的或门至少有一个为1,结果为1,与门为1那么经过或门还是1,下面的那个CC1G信号为软件产生捕获事件。这样就会产生一个捕获事件,计数器的值就会转移到捕获/比较影子寄存器里边。

捕获/比较影子寄存器不能直接读,需要将值转移到捕获/比较寄存器里边,那么需要capture_transfer条件。需要与门的两个信号都是1,CC1S信号一定是1,上面那个信号是raed操作,也就是说在读CCR1寄存器的时候不能转移数据。

例子:捕获信号一个脉冲信号

假如有一个脉冲信号,首先配置上升沿捕获,当上升沿来的时候,经过前面的滤波器分频器来到IC1PS,然后产生捕获事件,计数器的值转移到捕获/比较寄存器里边,然后程序读取CCR1的值即为CNT1,马上将输入设置为下降沿触发,然后再读取CCR1寄存器的值,设置为CNT2,利用CNT2的值减去CNT1的值,得到计数的个数,乘上一个数的事件,就得到了脉冲事件。

二、通用定时器输入捕获脉宽测量原理

首先将输入捕获通道配置成上升沿触发,对应图中就是在t1时刻产生上升沿,此实计数器的值会转移到捕获比较寄存器里,记为CCRx1。然后同是将计数器的值设置为0。之后有两种发情况,一种就是高电平时间非常短,在计时器一个周期里边下降沿就来了,那么计数个数就是t2时刻对应的CCRx2的值。第二种情况是在t1时刻与t2时刻之间,计数器发生了N次溢出事件,那么总共的计数器个数就是(ARR + 1)*N + CRRx2。计时器记一个数的时间乘上总共记得个数,就是高电平总共时间。时钟频率PCLK除分频系数PSC,就是计数器得工作频率,再取倒数,就是记一个数得时间。

三、通用定时器输入捕获实验配置步骤

1、HAL_TIM_IC_init()函数,配置定时器基础工作参数。,与base_init()函数一样

2、HAL_TIM_IC_MspInit()函数,配置NVIC、CLOCK、GPIO等。

3、HAL_TIM_IC_ConfigChannel()函数,配置输入通道映射、捕获边沿等。

4、HAL_NVIC_SetPriority()、HAL_NVIC_EnablelRQ()函数,设置优先级,使能中断。

5、__HAL_TIM_ENABLE IT()宏定义,使能定时器更新中断。

6、HAL_TIM_IC_Start_IT()函数,使能捕获、捕获中断及计数器。

7、TIMx IROHandler()->HAL TIM IROHandler(),中断服务函数。

8、HAL_TIM_PeriodElapsedCallback()函数,更新中断回调函数

HAL_TIM_IC_CaptureCallback()函数,输入捕获中断回调函数。

四、通用定时器输入捕获实验

实验:通过定时器5通道1来捕获按键高电平脉宽时间,通过串口打印出来

1MHz频率测量精度高,计数器计一个数就是1us。ARR的值随便设置,设置小的话溢出次数多。

1、使用寄存器配置输入捕获

#include "./BSP/TIMER/TIM_IC.h"void TIM_IC_Init(void)
{//开启定时器5时钟RCC->APB1ENR |= (1 << 3);//开启ARR寄存器缓冲功能TIM5->CR1 |= (1 << 7);//设置计数器向上计数模式TIM5->CR1 &= ~(1 << 4);//设置输入滤波 IC1F 0000TIM5->CCMR1 &= ~(0X0F << 4);//设置输入分频 IC1PSC 00 不分频TIM5->CCMR1 &= ~(0X03 << 2);//设置CC1S为输入模式 将IC1映射到通道一 01TIM5->CCMR1 |= (1 << 0);TIM5->CCMR1 &= ~(1 << 1);//设置CC1P 上升沿捕获TIM5->CCER &= ~(1 << 1);//设置分频系数PSCTIM5->PSC = 71;//设置ARR值为999 计数器溢出一次时间为0.1sTIM5->ARR = 999;//开启定时器3捕获比较通道1的捕获中断请求TIM5->DIER |= (1 << 1);//开启定时器三更新中断TIM5->DIER |= (1 << 0);//开启GPIOA时钟RCC->APB2ENR |= (1 << 2);//设置PA0为输入模式GPIOA ->CRL &= ~(0X03 << 0);//设置PA0为输入浮空GPIOA->CRL |= (1 << 2);GPIOA->CRL &= ~(1 << 3);	//使能定时器3中断HAL_NVIC_SetPriority(TIM5_IRQn, 2, 2);HAL_NVIC_EnableIRQ(TIM5_IRQn);TIM5->SR  = 0;//使能计数器 CEN位TIM5->CR1 |= (1<< 0);//开启输入捕获 CC1E位TIM5->CCER |= (1 << 0);
}uint16_t IC_Value = 0;//定义输入捕获寄存器的值
uint8_t rising = 0;//定义捕获到上升沿 1为已经捕获到上升沿
uint8_t flag = 0;//捕获高电平完成
uint16_t yichu = 0;
void TIM5_IRQHandler(void)
{//判断计数器溢出中断if(TIM5->SR & (1 << 0)){TIM5->SR &= ~(1 << 0);yichu ++;}//这里注意标志位一定要进中断立马清除  不要放在if里边 //因为如果条件不能成立 那么标志位没有清除 他会一直进中断  要不然就是使用库函数  捕获出现这种情况//清空SR输入捕获事件标志位  if(flag == 0 && TIM5->SR & (1 << 1)){		//还没有上升沿if(rising == 0 ){//清空计数器值TIM5->CNT = 0;//将输入捕获设置为下降沿TIM5->CCER  |= (1 << 1);rising = 1;//捕获到上升沿yichu = 0;}else{	//读取计数器得值IC_Value = TIM5->CCR1;//将输入捕获设置为上降沿TIM5->CCER  &= ~(1 << 1);			rising = 0;flag = 1;IC_Value = 1000*yichu + IC_Value;}}TIM5->SR &= ~(1 << 1);}

在配置过程中,最开始将SR中断标志位清除写在了if判断里边,导致条件一直不满足,就一直进入中断,主函数里边的程序也一直被中断卡着。

注意:这个程序捕获的额第一次数据不准确,目前还没有找到问题在哪,怀疑是第一次上升沿触发有问题。从第二次捕获开始,数据准确。

2、使用库函数配置输入捕获

tim_inCapture.h头文件

#ifndef __TIM_INCAPTURE_H
#define __TIM_INCAPTURE_H#include "stm32f1xx.h"void TIM_IC_Init(uint16_t psc,uint16_t arr);#endif

tim_inCapture.c源文件

#include "./BSP/TIMER/tim_inCapture.h"TIM_HandleTypeDef htim;void TIM_IC_Init(uint16_t psc,uint16_t arr)
{htim.Instance = TIM5;htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;htim.Init.CounterMode = TIM_COUNTERMODE_UP;htim.Init.Period = arr;htim.Init.Prescaler = psc;//定时器初始化 PSC ARR 计数模式 ARR缓冲功能HAL_TIM_IC_Init(&htim);//这个要给初始化0  不然里边的值是随机的  会影响配置TIM_IC_InitTypeDef sConfig = {0};sConfig.ICFilter = 0x0;sConfig.ICPolarity = TIM_ICPOLARITY_RISING;sConfig.ICPrescaler = TIM_ICPSC_DIV1;sConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;//定时器输入捕获配置 滤波器 分频器 输入极性(上升沿、下降沿) IC1来连接到通道1  还是连接到通道2HAL_TIM_IC_ConfigChannel(&htim, &sConfig, TIM_CHANNEL_1);//开启更新事件中断__HAL_TIM_ENABLE_IT(&htim, TIM_IT_UPDATE);//启动定时器 输入捕获使能 输入捕获中断HAL_TIM_IC_Start_IT(&htim, TIM_CHANNEL_1);
}void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{if(htim ->Instance == TIM5){//开启定时器5时钟__HAL_RCC_TIM5_CLK_ENABLE();//开启GPIOA时钟__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitTypeDef GPIO_Init;GPIO_Init.Mode = GPIO_MODE_INPUT;GPIO_Init.Pin = GPIO_PIN_0;GPIO_Init.Pull = GPIO_NOPULL;GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;//速度是输出用的 可以不设置//初始化PA0为浮空输入HAL_GPIO_Init(GPIOA, &GPIO_Init);		HAL_NVIC_SetPriority(TIM5_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM5_IRQn);}
}//定时器5中断处理函数
void TIM5_IRQHandler(void)
{HAL_TIM_IRQHandler(&htim);
}uint16_t IC_Value = 0;//定义输入捕获寄存器的值
uint8_t rising = 0;//定义捕获到上升沿 1为已经捕获到上升沿
uint8_t flag = 0;//捕获高电平完成
uint16_t yichu = 0;//定时器输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim ->Instance ==TIM5){//还没有捕获到高电平if(flag ==0){//还没有捕获到上升沿if(rising ==0){//已经捕获到了上升沿rising = 1;yichu = 0;//设置计数器的值为0__HAL_TIM_SET_COUNTER(htim, 0);//设置为下降沿捕获__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);}else{//获取捕获寄存器的值IC_Value = __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_1);//设置为上降沿捕获__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);rising = 0;flag =1;IC_Value = 1000*yichu + IC_Value;}}}
}void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim ->Instance ==TIM5){yichu++;}
}

这个是用库函数版本的程序,没啥问题,数据全是准确的。

main.c主函数

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/tim_inCapture.h"extern uint16_t IC_Value;//定义输入捕获寄存器的值
extern uint8_t flag;//捕获高电平完成
int main(void)
{HAL_Init();                         /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */delay_init(72);                     /* 延时初始化 */led_Init();                         /* LED初始化 */usart_init(115200);TIM_IC_Init(71 ,999);while(1){ LED0(1);LED1(0);delay_ms(500);LED0(0);LED1(1);delay_ms(500);printf("脉冲时间为%dUS\r\n",IC_Value);flag = 0;}
}

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

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

相关文章

SpringBoot中的多环境配置管理

SpringBoot中的多环境配置管理 文章目录 SpringBoot中的多环境配置管理SpringBoot中的多环境配置管理 多环境配置的概述1. 为什么需要多环境配置&#xff1f;2. Spring Boot 中如何实现多环境配置&#xff1f;3. 多环境配置的应用场景4. 如何实现配置隔离&#xff1f; Spring B…

全网多平台媒体内容解析工具使用指南

一、工具特性概述 近期体验了一款基于Web端的多媒体解析服务&#xff0c;该平台通过技术创新实现跨平台内容解析功能&#xff0c;主要特点如下&#xff1a; 1.1 跨平台支持 兼容主流社交媒体&#xff1a;Bilibili、YouTube、Twitter、Instagram等 支持短视频平台&#xff1a…

C# winforms 使用菜单和右键菜单

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

网工_以太网MAC层

2025.02.05&#xff1a;网工老姜学习笔记 第12节 以太网MAC层 2.1 MAC层的硬件地址2.2 MAC地址特殊位含义2.3 终端适配器&#xff08;网卡&#xff09;具有过滤功能2.4 MAC帧的格式2.4.1 DIX Ethernet V2标准&#xff08;先私有&#xff0c;后开放&#xff0c;用得比较多&#…

鼠标滚轮冒泡事件@wheel.stop

我有一个页面,是在画布上的组件,但是组件中有一个table,table中数据多了,就会出现滚动条,正常情况下,滚动条用鼠标滚轮就可以滑动,但是这个table是在画布上,滚动滚轮会让画布缩放 在table外层的div上加上 wheel.stop,就生效了 wheel.stop 用途&#xff1a;这个修饰符用于处理鼠…

探索从传统检索增强生成(RAG)到缓存增强生成(CAG)的转变

在人工智能快速发展的当下&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已成为众多应用的核心技术。检索增强生成&#xff08;RAG&#xff09;&#xff08;RAG 系统从 POC 到生产应用&#xff1a;全面解析与实践指南&#xff09;和缓存增强生成&#xff08;CAG&#x…

graphRAG的原理及代码实战(1)基本原理介绍(上)

1、基本介绍 GraphRAG通过利用大模型从原始文本数据中提取知识图谱来满足跨上下文检索的需求。该知识图将信息表示为互连实体和关系的网络&#xff0c;与简单的文本片段相比&#xff0c;提供了更丰富的数据表示。这种结构化表示使 GraphRAG 能够擅长回答需要推理和连接不同信息…

论文翻译学习:《DeepSeek-R1: 通过强化学习激励大型语言模型的推理能力》

摘要 我们介绍了我们的第一代推理模型 DeepSeek-R1-Zero 和 DeepSeek-R1。DeepSeek-R1-Zero 是一个通过大规模强化学习&#xff08;RL&#xff09;训练的模型&#xff0c;没有经过监督微调&#xff08;SFT&#xff09;作为初步步骤&#xff0c;展示了卓越的推理能力。通过强化…

使用 Ollama 在腾讯云服务器环境部署 DeepSeek 大模型实战指南

文章目录 前言Ollama核心特性 实战步骤安装 Ollama验证安装结果部署 DeepSeek 模型拉取模型启动模型 交互体验命令行对话调用 REST API 总结个人简介 前言 近年来&#xff0c;大语言模型&#xff08;LLM&#xff09;的应用逐渐成为技术热点&#xff0c;而 DeepSeek 作为国产开…

DeepSeek R1 简单指南:架构、训练、本地部署和硬件要求

DeepSeek 的 LLM 推理新方法 DeepSeek 推出了一种创新方法&#xff0c;通过强化学习 (RL) 来提高大型语言模型 (LLM) 的推理能力&#xff0c;其最新论文 DeepSeek-R1 对此进行了详细介绍。这项研究代表了我们如何通过纯强化学习来增强 LLM 解决复杂问题的能力&#xff0c;而无…

【现代深度学习技术】深度学习计算 | 读写文件

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

退格法记单词(类似甘特图)

退格法记单词&#xff0c;根据记忆次数或熟练程度退格&#xff0c;以示区分&#xff0c;该方法用于短时高频大量记单词&#xff1a; explosion爆炸&#xff0c;激增 mosquito蚊子granary粮仓&#xff0c;谷仓 offhand漫不经心的 transient短暂的slob懒惰而邋遢的…

深入理解 DeepSeek MOE(Mixture of Experts)

1. 什么是 MOE&#xff1f; MOE&#xff08;Mixture of Experts&#xff0c;专家混合&#xff09;是一种模型架构&#xff0c;旨在通过多个专家&#xff08;Experts&#xff09;模型的协同工作来提高计算效率和模型性能。在 MOE 结构中&#xff0c;不是所有的专家都参与计算&a…

MySQL数据库基础(创建/删除 数据库/表)

一、数据库的操作 1.1 显示当前数据库 语法&#xff1a;show databases&#xff1b; <1>show 是一个关键字&#xff0c;表示要执行的操作类型 <2>databases 是复数&#xff0c;表示显示所有数据库 上面的数据库中&#xff0c;除了java113&#xff0c;其它的数据库…

Git 常用命令汇总

# 推荐一个十分好用的git插件---->GitLens 其实很多命令操作完全界面化了&#xff0c;鼠标点点就可以实现但是命令是必要的&#xff0c;用多了你就知道了 Git 常用命令汇总 1. Git 基础操作 命令作用git init初始化本地仓库git clone <repo-url>克隆远程仓库到本地g…

数据分析系列--⑦RapidMiner模型评价(基于泰坦尼克号案例含数据集)

一、前提 二、模型评估 1.改造⑥ 2.Cross Validation算子说明 2.1Cross Validation 的作用 2.1.1 模型评估 2.1.2 减少过拟合 2.1.3 数据利用 2.2 Cross Validation 的工作原理 2.2.1 数据分割 2.2.2 迭代训练与测试 ​​​​​​​ 2.2.3 结果汇总 ​​​​​​​ …

Deepseek-v3 / Dify api接入飞书机器人go程序

准备工作 开通了接收消息权限的飞书机器人&#xff0c;例如我希望用户跟飞书机器人私聊&#xff0c;就需要开通这个权限&#xff1a;读取用户发给机器人的单聊消息 im:message.p2p_msg:readonly准备好飞书机器人的API key 和Secretdeepseek-v3的api keysecret&#xff1a;http…

红黑树原理及C语言实现

目录 一、原理 二、操作示例 三、应用场景 四、C语言实现红黑树 五、代码说明 六、红黑树和AVL树对比 一、原理 熟悉红黑树之前&#xff0c;我们需要了解二叉树与二叉查找树概念&#xff0c;参见前述相关文章&#xff1a;二叉查找树BST详解及其C语言实现-CSDN博客 红黑…

DeepSeek V2报告阅读

概况 MoE架构&#xff0c;236B参数&#xff0c;每个token激活参数21B&#xff0c;支持128K上下文。采用了包括多头潜在注意力&#xff08;MLA&#xff09;和DeepSeekMoE在内的创新架构。MLA通过将KV缓存显著压缩成潜在向量来保证高效的推理&#xff0c;而DeepSeekMoE通过稀疏计…

TCP服务器与客户端搭建

一、思维导图 二、给代码添加链表 【server.c】 #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <fcntl.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.…