单片机 PWM输入捕获【学习记录】

news2024/11/26 10:34:36

前言

学习是永无止境的,就算之前学过的东西再次学习一遍也能狗学习到很多东西,输入捕获很早之前就用过了,但是仅仅是照搬例程没有去进行理解。温故而知新!

定时器

定时器简介

定时器的分类

高级定时器 通用定时器 基本定时器,针对不同情况可以选择自己所需要的定时器,以下是这几种定时器的主要功能

高级定时器:

  1. 计数器单元
  2. 输入捕获
  3. 重复计数器
  4. PWM模式
  5. 互补输出和死区插入
  6. 支持针对定位的增量(正交)编码器和霍尔传感器电路
  7. 刹车功能
  8. DMA功能

通用定时器:

  1. 计数器单元
  2. 输入捕获
  3. PWM模式
  4. 支持针对定位的增量(正交)编码器和霍尔传感器电路
  5. DMA功能

基本定时器:

  1. 计数器单元
  2. 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 \frac{APBCLK}{ARR *Prescaler}。 

这里来解析一下为什么要使用 TIM_CLOCK_FREQ这个参数:

TIM_CLOCK_FREQ 代表的是定时器经过分频之后能够达到的极限频率,我们可以来推导一下,timer_clock(也就是主时钟APBCLK)分频之后 就是 \frac{timer_clock}{((timer_clock/TIM_CLOCK_FREQ))}

简单约去公约数,得到的就是TIM_CLOCK_FREQ,所以当重装载值为1的时候TIM_CLOCK_FREQ就是最高频率。再来解释一下周期是怎么得出的,由于1s之内计数器计数了TIM_CLOCK_FREQ次,所以一次需要的时间是1/TIM_CLOCK_FREQ,所以周期和重装载值之间的关系就是T= \frac{ARR*1}{TIM_CLOCK_FREQ},这里除以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输出,如果再讲下去就有点多了,这部分内容网上也有很多。

总结

输入捕获是高级定时器和通用定时器才有的功能,主要通过设置触发边沿和设置捕获频率来对脉宽进行一个测量,得出脉宽之后我们就可以很容易地计算出频率和周期。

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

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

相关文章

用TensorRT-LLM进行LLama的推理和部署

Deploy an AI Coding Assistant with NVIDIA TensorRT-LLM and NVIDIA Triton | NVIDIA Technical BlogQuick Start Guide — tensorrt_llm documentation (nvidia.github.io) 使用TensorRT-LLM的源码,来下载docker并在docker里编译TensorRT-LLM; 模型…

LabVIEW回热系统热经济性分析及故障诊断

开发了一种利用LabVIEW软件的电厂回热系统热经济性分析和故障诊断系统。该系统针对火电厂回热加热器进行优化,通过实时数据监控与分析,有效提高机组的经济性和安全性,同时降低能耗和维护成本。系统的实施大幅提升了火电厂运行的效率和可靠性&…

【调试笔记-20240617-Linux- frp 结合 nginx 实现内网网站在公网发布】

调试笔记-系列文章目录 调试笔记-20240617-Linux- frp 结合 nginx 实现内网网站在公网发布 文章目录 调试笔记-系列文章目录调试笔记-20240617-Linux- frp 结合 nginx 实现内网网站在公网发布 前言一、调试环境操作系统:Windows 10 专业版调试环境调试目标 二、调试…

CSS-0_2 CSS和继承(inherit initial)

文章目录 CSS的层叠和继承inheritinitial很多你以为的样式初始值,其实是用户代理样式 碎碎念 CSS的层叠和继承 在上一篇 CSS和层叠、样式优先级 里已经讲过了层叠和优先级之间的关系,但是在CSS中的层叠除了体现在争抢露脸机会的优先级之外,还…

HTML/CSS Xiaomi综合案例day 6.13-6.16

ok了家人们今天不做别的,今天浅做一个小米网站,话不多说看看怎么事 一.顶部 我们先看看代码 1,html 2,css代码 1.我们先消除浏览器自带的内外边距,添加一个总背景颜色为浅灰色,设置顶部盒子的大小&#x…

【电脑小白】装机从认识电脑部件开始

前言 在 B 站上刷到了一个很牛逼的电脑装机视频,很适合电脑小白学习,故用文本记录下。 推荐对组装台式电脑有兴趣的小伙伴都去看看这个视频: 原视频链接:【装机教程】全网最好的装机教程,没有之一_哔哩哔哩_bilibil…

JVM-GC-常用调优命令和GC参数

定位问题常用命令 top:查看内存/CPU占用情况top -Hp pid: 查看进程内线程情况jsp:查看java进程情况jstack 线程pid:查看进程内线程信息,一般查看线程状态,判断是否死锁。重点观察:WAITING、BLOCKED的线程,另外查看wait…

【网络安全】网络安全威胁及途径

1、网络安全威胁的种类及途径 (1)网络安全威胁的主要类型 网络安全面临的威胁和隐患种类繁多,主要包括人为因素、网络系统及数据资源和运行环境等影响。网络安全威胁主要表现为:黑客入侵、非授权访问、窃听、假冒合法用户、病毒…

【读博日记】拓扑结构(待修正)

Topology 拓扑学 内容来源于互联网,还在甄别中——20240617 拓扑结构指把实体抽象成与其形状大小无关的点,把连接实体的线路抽象成线,再研究这些电线之间的关系。 所谓相似的拓扑结构: 例如一个圆环变成正方形、长方形、三角形…

基 CanMV 的 C 开发环境搭建

不论是使用 CanMV 提供的基于 C 语言和 FreeRTOS 的应用开发方式开发应用程序或是编译 CanMV 固件,都需要搭建基于 CanMV 的 C 开发环境,用于编译 CanMV 源码。 1. 开发环境搭建说明 CanMV 提供了基于 C 语言和 FreeRTOS 的应用开发…

读AI新生:破解人机共存密码笔记04计算的极限

1. 计算的极限 1.1. 光靠速度是无法给我们带来人工智能的 1.1.1. 在速度更快的计算机上运行糟糕的算法并不会使算法变得更优秀,这只意味着你会更快地得到错误的答案 1.1.2. 数据越多,错误答案出现的机会就越大 1.…

EE trade:现货黄金杠杆比例的计算方法

现货黄金杠杆交易是一种利用保证金进行交易的方式,允许投资者用较少的资金控制较大的交易量,从而放大收益或损失。杠杆比例的计算方法相对简单,主要取决于交易所需的保证金和实际交易金额之间的关系。 杠杆比例的计算公式 杠杆比例 实际交…

使用插件永久解决IDEA使用Shift+F10失效问题(不需要换老版本输入法)

在日常编程中,使用快捷键可以大大提高开发效率。然而,有时候我们会遇到IDEA 中,ShiftF10 快捷键失效。这个蛋疼的问题现在终于可以得到解决,上个月在逛V2EX的时候看见一位大佬做的插件。 大佬链接:https://www.v2ex.c…

物联网技术-第4章物联网通信技术-4.1计算机网络

目录 1.1计算机网络拓扑与组成 (1)全连通式网络 (2)星型网 (3)环形网 (4)总线网 (5)不规则型网 1.2数据交换类型 (1)电路交换网 &…

STM32单片机DMA存储器详解

文章目录 1. DMA概述 2. 存储器映像 3. DMA框架图 4. DMA请求 5. 数据宽度与对齐 6. DMA数据转运 7. ADC扫描模式和DMA 8. 代码示例 1. DMA概述 DMA(Direct Memory Access)可以直接访问STM32内部的存储器,DMA是一种技术,…

C++ | Leetcode C++题解之第162题寻找峰值

题目&#xff1a; 题解&#xff1a; class Solution { public:int findPeakElement(vector<int>& nums) {int n nums.size();// 辅助函数&#xff0c;输入下标 i&#xff0c;返回一个二元组 (0/1, nums[i])// 方便处理 nums[-1] 以及 nums[n] 的边界情况auto get …

【漏洞复现】泛微OA E-Cology ln.FileDownload 任意文件读取漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

Debian12的#!bash #!/bin/bash #!/bin/env bash #!/usr/bin/bash #!/usr/bin/env bash

bash脚本开头可写成 #!/bin/bash , #!/bin/env bash , #!/usr/bin/bash , #!/usr/bin/env bash #!/bin/bash , #!/usr/bin/bash#!/bin/env bash , #!/usr/bin/env bash Debian12的 /bin 是 /usr/bin 的软链接, /sbin 是 /usr/sbin 的软链接, (Debian12默认没有ll命令,用的ls …

网络安全:数据库安全性

文章目录 网络安全&#xff1a;数据库安全性引言数据库安全性的重要性常见的数据库安全威胁数据库安全性的最佳实践数据加密访问控制审计和监控 结语 网络安全&#xff1a;数据库安全性 引言 在前两篇文章中&#xff0c;我们讨论了SQL注入的概念和防范措施。本篇文章将聚焦于…

5216万!国内自动化巨头,拟剥离旗下子业务

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 近日&#xff0c;中控技术发布公告称&#xff0c;为进一步优化资产结构和产业布局&#xff0c;提升公司核心竞争力&#xff0c;公司拟将其全资子…