单片机 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等)。…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...