32单片机基础:输入捕获测频率

 接线图如下图所示:

我们复制之前写过的代码6-3 PWM驱动LED呼吸灯

在PWM模块中,执行的逻辑是,初始化TIM2的通道1,产生一个PWM波形,输出引脚是PA0,通过SetCompare1的函数,可以调节CCR1寄存器的值,从而控制PWM的占空比。目前PWM的频率是在初始化里面写好了的,是固定的,运行时调节不太方便,所以我们在最后加一个函数,用来快捷调节PWM的频率。

我们知道PWM频率=更新频率=72M/(PSC+1)/(ARR+1)所以PSC和ARR都可以调节频率,但是占空比等于CRR/(ARR+1),所以通过ARR调节频率,还同时会影响到占空比,而通过PSC调节频率,不会影响占空比,显然比较方便,所以我们计划是,固定ARR为100-1.通过调节PSC来改变PWM频率,另外,ARR为100-1,CCR的数值直接就是占空比

void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); 

这个函数就是单独写入PSC的函数

我们写一个函数单独改变PSC的值。

void PWM_SetPrescaler(uint16_t Prescaler)
{
	TIM_PrescalerConfig(TIM2,Prescaler, TIM_PSCReloadMode_Immediate);
}

在主函数写入这些代码,就可以输出频率为1Khz,占空比为50%的波形了

    PWM_SetPrescaler(720-1);    //Freq=72M/(PSC+1)/(ARR+1)
	PWM_SetCompare1(50);         //Duty=CCR/(ARR+1)

建立输入捕获的.c,.h文件

首先对IC(输入捕获)初始化,怎么初始化呢?目前我们需要配置电路连接成下图所示的这个样子

 第一步:RCC开启时钟,把GPIO和TIM的时钟打开

第二步:GPIO初始化,把GPIO配置成输入模式,一般选择上拉输入和浮空输入

第三步:配置时基单元,让CNT计数器在内部时钟的驱动下自增运行。

第四步:配置输入捕获单元,包括滤波器,直连通道还是交叉通道,分频器这些参数。用一个结构体就可以统一配置了。

第五步:选择从模式的触发源,触发源选择为TI1FP1,这里调用一个库函数,给一个参数就OK了。

第六步:选择触发之后执行的操作,执行Reset操作,这里也是调用一个库函数就OK了。

最后,当这些电路都配置好了,调用TIM_Cmd函数,开启定时器。

这样所有的电路就能配合起来,按照我们之前的要求工作了。当我们需要读取最新一个周期的频率时,直接读取CCR寄存器,然后按照fc/N,计算一下就行了。

我们了解一下需要的库函数:

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

这个是用结构体配置输入捕获单元的函数,另外注意,输入捕获和输出比较都有四个通道,ICInit是共用一个函数的,所以在结构体里会额外有一个参数,可以选择具体配置哪个通道。因为可能有交叉通道的配置,所以函数合在一起比较方便。

void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

这个函数与上一个函数类似。都是用于初始化输入捕获单元的,上一个函数只是单一的配置一个通道,而这个函数,可以快速配置两个通道,把外设电路结构配置成PWMI模式

void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);

可以给输入捕获结构体赋一个初始值。

void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

选择输入触发源TRGI,对应下图所示:调用这个函数,就能选择从模式触发源了。

void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);

选择输出触发源TRGO,对应下图所示,选择主模式的触发源

void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);

选择从模式

void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);

分别单独配置通道1,2,3,4的分频器

uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);

分别读取四个通道的CCR,这四个函数和上面的SetCompare1,2,3,4是对应的,读写的都是CCR寄存器,输出比较模式下,CCR是只写的,要用SetCompare写入,输入捕获模式下,CCR是只读的,要用GetCapture读出, 

下面是输入捕获频率的代码:

main.c

#include "stm32f10x.h"                  // Device header              
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"

int main()
{
	
	OLED_Init();
	PWM_Init();
	IC_Init();
	
	OLED_ShowString(1,1,"Freq:00000Hz");
	
    PWM_SetPrescaler(720-1);    //Freq=72M/(PSC+1)/(ARR+1)
	PWM_SetCompare1(50);         //Duty=CCR/(ARR+1)
	while(1)
	{
      OLED_ShowNum(1,6,IC_GetFreq(),5);
	}
}

PWM.c

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	//时基单元的代码写过,我们找之前定时中断的代码复制一下
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开时钟、
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//重映射
	
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable ,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;     //GPIO_Pin_15
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
    TIM_InternalClockConfig(TIM2);//选择内部时钟
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//初始化时基单元
	TIM_TimeBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1 ;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up ;
	TIM_TimeBaseInitStructure.TIM_Period=100-1;//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//PSC
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	//初始化输出比较单元
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1 ;
	TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse=0;//CCR   等下再算
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);
	//通道已经初始化完成,在TIM2的OC1通道上就可以输出PWM波形了,这个波形借用GPIO口输出
	 
	 //初始化GPIO
	
	TIM_Cmd(TIM2,ENABLE);//启动定时器
}

void PWM_SetCompare1(uint16_t Compare)
{
	 TIM_SetCompare1(TIM2,Compare);
}

void PWM_SetPrescaler(uint16_t Prescaler)
{
	TIM_PrescalerConfig(TIM2,Prescaler, TIM_PSCReloadMode_Immediate);
}

PWM.h

#ifndef __OLED_H
#define __OLED_H

void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
void PWM_SetPrescaler(uint16_t Prescaler);
#endif

IC.c

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	//时基单元的代码写过,我们找之前定时中断的代码复制一下
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //打开时钟、
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;     //GPIO_Pin_15
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
    TIM_InternalClockConfig(TIM3);//选择内部时钟
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//初始化时基单元
	TIM_TimeBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1 ;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up ;
	TIM_TimeBaseInitStructure.TIM_Period=65536-1;//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//PSC
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
	
	//初始化输入捕获单元
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter=0xF;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3,&TIM_ICInitStructure);
	
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3,ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000/ (TIM_GetCapture1(TIM3)+1);
}

IC.h

#ifndef __IC_H
#define __IC_H

void IC_Init(void);
uint32_t IC_GetFreq(void);
#endif

下面,我们讲解一下代码的操作步骤和逻辑。

开启时钟,配置GPIO,配置时基单元,TIM2输出PWM,TIM3输入捕获。GPIO的时钟。看一下引脚定义表,比如我选择TIM3的通道1,就是PA6,

配置好了之后,初始化输入捕获单元。在tim.h找相应的函数,

接下来找函数把主从模式配置好。

配置TRGI的触发源为TI1FP1.

开启时钟,

之后再写一个函数读取CCR进行计算。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法相关计算

1 内存管理相关 1 .1 float 6.9 f 的内存计算方法 二进制小数的计算: (1)小数的二进制算法和整数的大致相反,就是不断的拿小数部分乘以2取积的整数部分,然后正序排列。比如求0.9的二进制: 0.9*21.8 取 1…

【网络】主机连接 TCP 三次握手

【网络】主机连接 TCP 三次握手 一、TCP连接3次握手二、TCP连接4次挥手三、为什么tcp要三次握手,两次行不四、为什么TCP挥手需要4次五、Netstat命令的连接状态包括:六、练习题 一、TCP连接3次握手 1、建立连接的时候是3次握手,客户端向服务器端发送SYN&…

微软亚太区AI智能应用创新业务负责人许豪,将出席“ISIG-AIGC技术与应用发展峰会”

3月16日,第四届「ISIG中国产业智能大会」将在上海中庚聚龙酒店拉开序幕。本届大会由苏州市金融科技协会指导,企智未来科技(AIGC开放社区、RPA中国、LowCode低码时代)主办。大会旨在聚合每一位产业成员的力量,深入探索A…

手写分布式配置中心(四)增加实时刷新功能(长轮询)

上一篇文章中实现了短轮询,不过短轮询的弊端也很明显,如果请求的频率较高,那么就会导致服务端压力大(并发高);如果请求的频率放低,那么客户端感知变更的及时性就会降低。所以我们来看另一种轮询…

(上海电力展)2024上海国际智慧电力与电气设备展览会

2024上海国际智慧电力与电气设备展览会 2024 Shanghai International Intelligent Power and Electrical Equipment Exhibition 时 间:2024年7月13-15日 地 点:上海新国际博览中心 展会简介Introduction 随着全球进入互联网和数字经济时…

精品中国货出海wordpress外贸独立站建站模板

旗袍唐装wordpress外贸网站模板 旗袍、唐装、华服wordpress外贸网站模板,适合做衣服生意的外贸公司官网使用。 https://www.jianzhanpress.com/?p3695 劳动防护wordpress外贸独立站模板 劳动防护wordpress外贸独立站模板,劳动保护、劳动防护用品外贸…

“首件检验”为什么至关重要?(内附流程规范)

在产品的设计及生产过程中,经常会出现设计变更、工艺变更、制程调整、非计划停线及转产、转线等“变化”。 如何确保这些“变化”不影响产品后续的生产品质?这就需要在作业准备验证、停产后验证阶段,进行不能缺少的重要环节——“首件检验”。…

VGW在 Windows 平台上局域网就绪的旁路由器程序

在查阅本篇文章之前可以查看下,本人前两年写的关于VGW软件路由器的文章 Linux 平台上面单网卡 TUN/TAP实现局域网其它设备上网_linux 物理网卡与tun同网段-CSDN博客 VGW软件路由器是一个工作IEEE以太网(L2)链路层的路由器程序,它…

第三讲 汇编初步 课程随手记

一、寄存器 32位CPU通用寄存器如下图所示: 因为教材依照的是32位CPU寄存器,而我安装的是64位寄存器,所以找了一下64位的寄存器的资料 PS:一般来说,Intel处理器字节存储顺序为小端法存储,是指数据的高字节保…

el-table 表格多选, 批量删除功能

一、基础的多选el-table ElementUI 提供了多选行table&#xff0c;同时若依框架也提供了成熟的多选表格。 1.table基础结构 需要绑定selection-change方法 <el-tablev-loading"loading"stripe:data"productList"selection-change"handleSelect…

常见的几种echarts类型

一&#xff1a;折线图 let option {tooltip: {},animation: false,grid: {top: "20%",bottom: "33%", //也可设置left和right设置距离来控制图表的大小left: 5%,right: 5%},xAxis: {boundaryGap:false,data: [1,2,3,4,5],axisLine: {show: true, //隐藏X轴…

【常见索引使用】⭐️Mysql中索引的类型以及使用方式和失效场景

目录 一、前言 二、数据准备 三、索引的分类 四、索引示例 示例1、主键索引&#xff08;Primary Key Index&#xff09;与 唯一索引&#xff08;Unique Index&#xff09; 示例2、前缀索引&#xff08;Prefix Index&#xff09; 示例3、联合索引&#xff08;复合索引&am…

智能驾驶规划控制理论学习07-规划算法整体框架

一、解耦合策略 1、路径-速度解耦策略概述 路径-速度解耦指的是将车辆的运动分成路径规划和速度规划两部分&#xff0c;对两个部分分别进行研究。 路径规划&#xff1a; 假设环境是“静态的”&#xff0c;将障碍物投射到参考路径上&#xff0c;并规划一条避开它们的路径&…

2024年【安全员-C证】找解析及安全员-C证模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-C证找解析是安全生产模拟考试一点通总题库中生成的一套安全员-C证模拟考试&#xff0c;安全生产模拟考试一点通上安全员-C证作业手机同步练习。2024年【安全员-C证】找解析及安全员-C证模拟考试 1、【多选题】…

第十二篇 - IAB 标准技术条款和定义-我为什么要翻译介绍美国人工智能科技巨头IAB公司?

前言 这是2021年IAB公司发布的《市场营销人工智能使用案例及最佳实践报告》的最后一篇译文。翻译工作不难&#xff0c;但是非常考验一个人的态度&#xff0c;需要译者忠于自己的初心&#xff0c;严谨对待所有文字、数据、信息、技术和观点。时代变化如此之快&#xff0c;3年前…

【小黑嵌入式系统第十八课】结课总结(二)——软件部分(系统架构调试测试运行系统软件设计)

上一课&#xff1a; 【小黑嵌入式系统第十七课】结课总结&#xff08;一&#xff09;——硬件部分&#xff08;系统&总线&处理器&外设&通信&#xff09; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分…

js节点操作

js节点操作 一.DOM节点二.查找节点三.增加节点3.1.创建节点3.2.追加节点3.3.克隆节点 四. 删除节点 一.DOM节点 DOM树里每一个内容都称之为节点 节点类型&#xff1a;元素节点&#xff08;所有的标签 比如 body&#xff0c;div等&#xff0c;html 是根节点&#xff09; 属性节…

前缀和+哈希表:联手合击Leetcode 560.和为k的子数组

题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#xff1a; 输入&#xff1a;nums [1,2…

C++指针(四)

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 前言 相关文章&#xff1a;C指针&#xff08;一&#xff09;、C指针&#xff08;二&#xff09;、C指针&#xff08;三&#xff09; 本篇博客是介绍函数指针、函数指针数组、回调函数、指针函数的。 点赞破六…

YOLOSHOW - YOLOv5 / YOLOv7 / YOLOv8 / YOLOv9 基于 Pyside6 的图形化界面

YOLOSHOW 是一个基于 PySide6&#xff08;Qt for Python&#xff09;开发的图形化界面应用程序&#xff0c;主要用于集成和可视化YOLO系列&#xff08;包括但不限于YOLOv5、YOLOv7、YOLOv8、YOLOv9&#xff09;的目标检测模型。YOLOSHOW 提供了一个用户友好的交互界面&#xff…
最新文章