单片机 PWM输入捕获【学习记录】
前言
学习是永无止境的,就算之前学过的东西再次学习一遍也能狗学习到很多东西,输入捕获很早之前就用过了,但是仅仅是照搬例程没有去进行理解。温故而知新!
定时器
定时器简介
定时器的分类
高级定时器 通用定时器 基本定时器,针对不同情况可以选择自己所需要的定时器,以下是这几种定时器的主要功能。
高级定时器:
- 计数器单元
- 输入捕获
- 重复计数器
- PWM模式
- 互补输出和死区插入
- 支持针对定位的增量(正交)编码器和霍尔传感器电路
- 刹车功能
- DMA功能
通用定时器:
- 计数器单元
- 输入捕获
- PWM模式
- 支持针对定位的增量(正交)编码器和霍尔传感器电路
- DMA功能
基本定时器:
- 计数器单元
- DMA功能
定时器的功能
我们使用定时器很多时候使用都是用做于计数作用,同样也可以作为PWM输出,输入捕获(脉宽测量,频率检测)等等,有的时候我们还会使用DMA+PWM输出这样的功能,总之定时器对于我们进行产品开发是必不可少的。
定时器的配置
主要寄存器
这里我使用的是航芯ACM32FP0X系列的单片机,不过其他单片机用法也是一样的。

这里我们主要关注以上六个寄存器,中断使能寄存器、状态寄存器、事件产生寄存器、预分频寄存器、自动加载寄存器、捕获/比较寄存器。其他的寄存器不是说不重要,只是在本次实验中主要理解这几个寄存器就好。
PWM配置
因为本次实验没有使用外置的脉冲发生器,所以使用单片机上另一个通用定时器来配置PWM,然后使用高级定时器去进行输入捕获。
TIM_Handler_PWM.Instance = TIM15;TIM_Handler_PWM.Init.ARRPreLoadEn = TIM_ARR_PRELOAD_ENABLE; TIM_Handler_PWM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TIM_Handler_PWM.Init.CounterMode = TIM_COUNTERMODE_UP; TIM_Handler_PWM.Init.RepetitionCounter = 0; TIM_Handler_PWM.Init.Prescaler = (timer_clock/TIM_CLOCK_FREQ)*1 - 1; if (timer_clock%TIM_CLOCK_FREQ > TIM_CLOCK_FREQ/2) {TIM_Handler_PWM.Init.Prescaler = TIM_Handler_PWM.Init.Prescaler + 1; }TIM_Handler_PWM.Init.Period = (TIM_CLOCK_FREQ/100000)*20 - 1; // period = 1ms
首先是常规的配置,这里我选择的是定时器15作为PWM口进行输出,然后不分频所以APB的时钟就是定时器的时钟。然后就是自动重装载值ARR,和预分配系数Prescaler的配置;这两个参数共同决定了配置的PWM输出极限频率是多少。
PWM输出频率 Fre = 。
这里来解析一下为什么要使用 TIM_CLOCK_FREQ这个参数:
TIM_CLOCK_FREQ 代表的是定时器经过分频之后能够达到的极限频率,我们可以来推导一下,timer_clock(也就是主时钟APBCLK)分频之后 就是 ,
简单约去公约数,得到的就是TIM_CLOCK_FREQ,所以当重装载值为1的时候TIM_CLOCK_FREQ就是最高频率。再来解释一下周期是怎么得出的,由于1s之内计数器计数了TIM_CLOCK_FREQ次,所以一次需要的时间是1/TIM_CLOCK_FREQ,所以周期和重装载值之间的关系就是T= ,这里除以1000的原因是将秒的单位换算成毫秒。OK,也不知道讲清楚了没有,之前也搞不懂这个关系式,后来推导出来的时候还感觉蛮巧妙的。
配置完这些再配置一下模式和占空比(CCR)和引脚就行了
输入捕获的配置
TIM_IC_InitTypeDef Tim_IC_Init_Para; TIM_Handler.Instance = TIM1;TIM_Handler.Init.ARRPreLoadEn = TIM_ARR_PRELOAD_ENABLE; TIM_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TIM_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; TIM_Handler.Init.RepetitionCounter = 0; TIM_Handler.Init.Prescaler = 0; TIM_Handler.Init.Period = 0xFFFF; // max period TIM1_MSP_Pre_Init(&TIM_Handler); HAL_TIMER_Base_Init(&TIM_Handler); Tim_IC_Init_Para.TIFilter = TIM_TI1_FILTER_LVL(0); // no filter Tim_IC_Init_Para.ICPolarity = TIM_SLAVE_CAPTURE_ACTIVE_RISING_FALLING; Tim_IC_Init_Para.ICPrescaler = TIM_IC1_PRESCALER_1; Tim_IC_Init_Para.ICSelection = TIM_ICSELECTION_DIRECTTI; // TI1FP1 HAL_TIMER_Capture_Config(TIM_Handler.Instance, &Tim_IC_Init_Para, TIM_CHANNEL_1); TIM1_MSP_Post_Init();
上面也是一些很常规的配置,配置了分频系数(为1意味着定时器的频率和APB时钟一致),重装载值为0xFFFF,这些数据传达了一个怎样的信息呢?说明了使用输入捕获的频率可高达64MHz(APB时钟为64MHz),说明捕获精度可以达到1/64000000 s,也就是15ns,最长捕获时间间隔为1023us(15ns * 0xFFFF)。然后下一个就是设置捕获触发模式,可能不同的单片机的库设置起来会有细微差别,但是大致意思是相同的。由于我们需要收集这些鞋数据然后在串口上打印出来所以我这里使用了中断触发,在中断里面收集数据。
HAL_TIMER_Clear_Capture_Flag(&TIM_Handler, TIM_CHANNEL_1);NVIC_ClearPendingIRQ(TIM1_CC_IRQn); NVIC_ClearPendingIRQ(TIM1_BRK_UP_TRG_COM_IRQn);NVIC_EnableIRQ(TIM1_CC_IRQn); NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); HAL_TIMER_Base_Init(&TIM_Handler); HAL_TIM_ENABLE_IT(&TIM_Handler, TIM_IT_CC1);HAL_TIM_ENABLE_IT(&TIM_Handler, TIMER_INT_EN_UPD); //计数器向上溢出/向下溢出 用于记录更新次数HAL_TIM_Capture_Start(TIM_Handler.Instance, TIM_CHANNEL_1);
当然这里还加了个溢出中断,用于辅助捕获计算超出最大捕获长度的电平时间,具体思路就是当计数器溢出的时候在事件更新中断里面设置一个变量进行加加。
可以大致看一下捕获中断里面的函数,主要是获取触发了捕获中断之后将数据写入事先定义好的数组,然后在定义一个变量进行计数。
void TIM1_CC_IRQHandler(void)
{uint32_t status; status = TIM1->SR; if ( (status & TIMER_SR_CC1IF) && ((TIM1->CCMR1) & (BIT0|BIT1)) ) {if(flag1 == 1)flag2 = 1;flag1 = 1;Capture_data[0][capture_times] = TIM1->CCR1;}if ((status & TIMER_SR_CC2IF) && ((TIM1->CCMR1) & (BIT8|BIT9)) ) {Capture_data[1][capture_times] = TIM1->CCR2; }capture_times++; NVIC_ClearPendingIRQ(TIM1_CC_IRQn);
}
然后在主函数里面获取标志位之后打印显示就可以了

这样在主函数当中我们就可以是去使用到这些数据然后打印到串口。这里要注意一点我使用的是双边沿触发所以打印出来的不是一个周期,而是两段占空比的数值。
当然这里我还使用了DMA+PWM进行PWM输出,如果再讲下去就有点多了,这部分内容网上也有很多。

总结
输入捕获是高级定时器和通用定时器才有的功能,主要通过设置触发边沿和设置捕获频率来对脉宽进行一个测量,得出脉宽之后我们就可以很容易地计算出频率和周期。
相关文章:
单片机 PWM输入捕获【学习记录】
前言 学习是永无止境的,就算之前学过的东西再次学习一遍也能狗学习到很多东西,输入捕获很早之前就用过了,但是仅仅是照搬例程没有去进行理解。温故而知新! 定时器 定时器简介 定时器的分类 高级定时器 通用定时器 基本定时器…...
3.1、前端异步编程(超详细手写实现Promise;实现all、race、allSettled、any;async/await的使用)
前端异步编程规范 Promise介绍手写Promise(resolve,reject)手写Promise(then)Promise相关 API实现allraceallSettledany async/await和Promise的关系async/await的使用 Promise介绍 Promise是一个类,可以翻…...
3.1. 马氏链-马氏链的定义和示例
马氏链的定义和示例 马氏链的定义和示例1. 马氏链的定义2. 马氏链的示例2.1. 随机游走2.2. 分支过程2.3. Ehrenfest chain2.4. 遗传模型2.5. M/G/1 队列 马氏链的定义和示例 1. 马氏链的定义 对于可数状态空间的马氏链, 马氏性指的是给定当前状态, 其他过去的状态与未来的预测…...
红利之外的A股底仓选择:A50
内容提要 华泰证券指出,当前指数层面下行风险不大,市场再入震荡期下,可关注三条配置线索:1)A50为代表的产业巨头;2)以家电/食饮/物流/出版为代表的稳健消费龙头,3)消费电…...
wondershaper 一款限制 linux 服务器网卡级别的带宽工具
文章目录 一、关于wondershaper二、文档链接三、源码下载四、限流测试五、常见报错1. /usr/local/sbin/wondershaper: line 145: tc: command not found2. Failed to download metadata for repo ‘appstream‘: Cannot prepare internal mirrorlist: No URLs.. 一、关于wonder…...
独孤思维:盲目进群,根本赚不到钱
01 我看有些伙伴,对标同行找写作素材和灵感的时候。 喜欢把对标文章发给ai提炼总结。 这个方法好是好,但是,有一个问题。 即,无法感受全文的细节。 更无法感受作者的情感和温度。 就好像电影《记忆大师》一样。 我提取了记…...
针对indexedDB的简易封装
连接数据库 我们首先创建一个DBManager类,通过这个类new出来的对象管理一个数据库 具体关于indexedDB的相关内容可以看我的这篇博客 indexedDB class DBManager{}我们首先需要打开数据库,打开数据库需要数据库名和该数据库的版本 constructor(dbName,…...
网络编程--网络理论基础(二)
这里写目录标题 网络通信流程mac地址、ip地址arp协议交换机路由器简介子网划分网关 路由总结 为什么ip相同的主机在与同一个互联网服务通信时不冲突公网ip对于同一个路由器下的不同设备,虽然ip不冲突,但是因为都是由路由器的公网ip转发通信,接…...
Python MongoDB 基本操作
本文内容主要为使用Python 对Mongodb数据库的一些基本操作整理。 目录 安装类库 操作实例 引用类库 连接服务器 连接数据库 添加文档 添加单条 批量添加 查询文档 查询所有文档 查询部分文档 使用id查询 统计查询 排序 分页查询 更新文档 update_one方法 upd…...
Node.js 入门:
Node.js 是一个开源、跨平台的 JavaScript 运行时环境,它允许开发者在浏览器之外编写命令行工具和服务器端脚本。以下是一些关于 Node.js 的基础教程: 1. **Node.js 入门**: - 了解 Node.js 的基本概念,包括它是一个基于 Chro…...
java8 List的Stream流操作 (实用篇 三)
目录 java8 List的Stream流操作 (实用篇 三) 初始数据 1、Stream过滤: 过滤-常用方法 1.1 筛选单元素--年龄等于18 1.2 筛选单元素--年龄大于18 1.3 筛选范围--年龄大于18 and 年龄小于40 1.4 多条件筛选--年龄大于18 or 年龄小于40 and sex男 1.5 多条件筛…...
机器学习python实践——数据“相关性“的一些补充性个人思考
在上一篇“数据白化”的文章中,说到了数据“相关性”的概念,但是在统计学中,不仅存在“相关性”还存在“独立性”等等,所以,本文主要对数据“相关性”进行一些补充。当然,如果这篇文章还能入得了各位“看官…...
MySQL——触发器(trigger)基本结构
1、修改分隔符符号 delimiter $$ $$可以修改 2、创建触发器函数名称 create trigger 函数名 3、什么样在操作触发,操作哪个表 after :……之后触发 before :……之后触发 insert :……之后触发 update :……之后触…...
数字孪生定义及应用介绍
数字孪生定义及应用介绍 1 数字孪生(Digital Twin, DT)概述1.1 定义1.2 功能1.3 使用场景1.4 数字孪生三步走1.4.1 数字模型1.4.2 数字影子1.4.3 数字孪生 数字孪生地球平台Earth-2 参考 1 数字孪生(Digital Twin, DT)概述 数字孪…...
数据赋能(122)——体系:数据清洗——技术方法、主要工具
技术方法 数据清洗标准模型是将数据输入到数据清洗处理器,通过一系列步骤“清理”数据,然后以期望的格式输出清理过的数据。数据清洗从数据的准确性、完整性、一致性、惟一性、适时性、有效性几个方面来处理数据的丢失值、越界值、不一致代码、重复数据…...
【SCAU数据挖掘】数据挖掘期末总复习题库简答题及解析——中
1. 某学校对入学的新生进行性格问卷调查(没有心理学家的参与),根据学生对问题的回答,把学生的性格分成了8个类别。请说明该数据挖掘任务是属于分类任务还是聚类任务?为什么?并利用该例说明聚类分析和分类分析的异同点。 解答: (a)该数据…...
2024年注册安全工程师报名常见问题汇总!
注册安全工程师报名 24年注册安全工程师报名已正式拉开序幕,报名时间为6月18日—7月10日,考试时间为10月26日—10月27日。 目前经有12个地区公布了2024年注册安全工程师报名时间: 注册安全工程师报名信息完善 根据注安报名系统提示&am…...
JRebel-JVMTI [FATAL] Couldn‘t write to C:\Users\中文用户名-完美解决
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 热部署下载参考博客解决第一步第二步第三步:第四步: 热部署下载 下载后启动报错:JRebel-JVMTI [FATAL] Couldn’t write to C:\…...
STM32基于DMA数据转运和AD多通道
文章目录 1. DMA数据转运 1.1 初始化DMA步骤 1.2 DMA的库函数 1.3 设置当前数据寄存器 1.4 DMA获取当前数据寄存器 2. DMA数据转运 2.1 DMA.C 2.2 DMA.H 2.3 MAIN.C 3. DMAAD多通道 3.1 AD.C 3.2 AD.H 3.3 MAIN.C 1. DMA数据转运 对于DMA的详细解析可以看下面这篇…...
安卓应用开发——Android Studio中通过id进行约束布局
在Android开发中,布局通常使用XML文件来描述,而约束(如相对位置、大小等)可以通过多种方式实现,但直接使用ID进行约束并不直接对应于Android的传统布局系统(如LinearLayout、RelativeLayout等)。…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
