当前位置: 首页 > article >正文

STM32的HAL库开发---通用定时器(TIMER)---定时器脉冲计数

一、脉冲计数实验原理

1、 外部时钟模式1:核心为蓝色部分的时基单元,时基单元的时钟源可以来自四种,分别是内部时钟PCLK、外部时钟模式1,外部时钟模式2、内部定时器触发(级联)。而脉冲计数就是使用外部时钟模式1和外部时钟模式2。

当使用外部时钟模式1的时候,输入信号主要来自定时器的通道1和通道2,然后通过信号TI1FP1和TI2FP2来到TRGI,然后经过从模式控制器来到时基单元。在从模式控制器里边的从模式选择外部时钟模式1,而外部时钟模式1实际上信号可以来自于TI1FP1、TI2FP2、TI1F_ED三种,其中TI1F_ED为双边沿检测,当来一个脉冲之后,无论是上升沿还是下降沿,TI1F_ED都有效,都会触发计数器计数,如果分频系数是1,一个脉冲会记两个数。而TI1FP1和TI2FP2只能是一种边沿,记一个信号。

分频系数为1时,直接读取计数器的值就是脉冲的个数。

2、外部时钟模式2:信号来自TIMx_ETR引脚,经过极性选择、边沿检测器、预分频器、输入滤波器,来到ETRF,设置从模式控制器模式为外部时钟模式2,然后来到时基单元。

例子:外部时钟模式1,信号配置成通道2输入。

设置SMS为111,外部时钟模式1,信号从定时器通道2来到TI2,然后首先经过滤波器,滤波器可以设置ICF进行设置。 然后设置边沿检测器,通过CC2P位来设置是上升沿还是下降沿有效,然后设置TRGI信号源,设置为110,信号来自TI2FP2,这块的设置跟输入捕获时候设置有些类似。

二、通用定时器脉冲计数实验配置步骤

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

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

3、HAL_TIM_SlaveConfigSynchro()函数,配置定时器从模式等。

4、HAL _TIM_IC_Start()函数,使能输入捕获并启动计数器。

5、__HAL_TIM_GET_COUNTERO()宏定义,获取计数器的值。

6、__HAL_TIM_SET_COUNTERO()宏定义,设置计数器的值。

 三、通用定时器脉冲计数实验

实验:将定时器2通道1输入的高电平脉冲作为定时器2的时钟,并通过串口打印脉冲数,定时器2通道1为PA0  PA0接的按键 按下一次产生一个脉冲

1、寄存器配置版本

注意:在配置过程中PSC设置为1时,都正常,但是PSC设置的值不是1时,一定要软件产生更新事件,由于PSC有影子寄存器,实际起作用的是影子寄存器,不软件产生更新事件,PSC的值会在计数器溢出的时候进入影子寄存器。

在HAL库里边这个软件更新事件在初始化函数最后写了。

#include "./BSP/TIMER/TIM_IC.h"

void TIM_IC_Init(void)
{
	//开启GPIOA时钟
	RCC->APB2ENR |= (1 << 2);
	
	//设置PA0为输入模式
	GPIOA ->CRL &= ~(0X03 << 0);
	
	//设置PA0为输入下拉
	GPIOA->CRL |= (1 << 3);
	GPIOA->CRL &= ~(1 << 2);	
	
	//开启定时器2时钟
	RCC->APB1ENR |= (1 << 0);
	
	//设置分频系数PSC
	TIM2->PSC = 5;
	
	//开启ARR寄存器缓冲功能
	TIM2->CR1 |= (1 << 7);
	
	//设置计数器向上计数模式
	TIM2->CR1 &= ~(1 << 4);
	
	//设置TS位  为 101接TI1FP1
	TIM2->SMCR |= (1 << 6);
	TIM2->SMCR &= ~(1 << 5);
	TIM2->SMCR |= (1 << 4);
	
	//设置SMS为外输时钟模式1  111
	TIM2->SMCR |= 0X07;
	
	//设置输入滤波 IC1F 0000
	TIM2->CCMR1 &= ~(0X0F << 4);		
	
	//设置CC1P 上升沿捕获
	TIM2->CCER &= ~(1 << 1);
	
	//设置ARR值为999 
	TIM2->ARR = 999;
	
	//使能计数器 CEN位
	TIM2->CR1 |= (1<< 0);

	//***********注意:重要****************
	//软件产生更新事件  使PSC的值立即生效  
	//由于PSC有影子寄存器  不软件产生更新事件  PSC的值会等到计数器溢出是才生效
	TIM2->EGR |= (1 << 0);
}

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 = TIM2;
	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);
	
	TIM_SlaveConfigTypeDef sSlaveConfig = {0};
	
	//设置双边沿触发
	//sSlaveConfig.InputTrigger = TIM_TS_TI1F_ED;
	//设置单边沿触发
	sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
	sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;	
	sSlaveConfig.TriggerFilter = 0X0;
	sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
	//这个是输入分频的  这个在外部时钟模式1没有用 外部时钟模式2有分频 
	sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
	//定时器从模式配置
	HAL_TIM_SlaveConfigSynchro(&htim, &sSlaveConfig);
	
	//启动定时器 
	HAL_TIM_IC_Start(&htim, TIM_CHANNEL_1);
}

void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
	if(htim ->Instance == TIM2)
	{
		//开启定时器2时钟
		__HAL_RCC_TIM2_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_PULLDOWN;
		GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;//速度是输出用的 可以不设置
		
		//初始化PA0为下拉输入
		HAL_GPIO_Init(GPIOA, &GPIO_Init);		
		
	}
}


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"


uint8_t count = 0;//捕获高电平完成
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(0 ,999);
    while(1)
    { 
		LED0(1);
		LED1(0);
		delay_ms(500);
		
		LED0(0);
		LED1(1);
		delay_ms(500);
		count = TIM2->CNT;
		printf("脉冲个数:%d\r\n",count);
		
    }
}


http://www.kler.cn/a/536780.html

相关文章:

  • AI 编程工具—Cursor 进阶篇 文章改写生成整理爬取
  • 瞬态分析中的时域分析与频域分析:原理、对比与应用指南
  • 集合类不安全问题
  • EGO-Planner文章解读(一)——论文原理和算法实现
  • 策略模式(Strategy)
  • 《图解设计模式》笔记(五)一致性
  • 01C#入门篇(D1_C#入门前的认知)
  • Github - 记录一次对“不小心包含了密码的PR”的修复
  • 机器学习数学基础:13.逆矩阵
  • 自然语言处理的统计学原理
  • centOS8安装MySQL8设置开机自动启动失败
  • # C指针地址CUP寄存器访问IO内存映射
  • 暴雨信创服务器推动DeepSeek本地化部署
  • Effective Objective-C 2.0 读书笔记——类对象
  • 人人皆可创建自己的AI应用:DigitalOcean GenAI平台正式上线
  • GSMA eSIM IoT 技术规范 SGP.32 v1.0.1 笔记
  • kafka服务端之控制器
  • 音视频流媒体中的实 时 流式 传 输 (Realtime (progressive streaming)。streaming )和 顺 序 流式 传 输
  • 从零开始:CentOS 7系统中Docker的安装与卸载全记录
  • 数据结构和算法
  • 网络编程(历史,网络协议模型),预备知识,基于socket的TCP通信
  • Linux基础命令之CA认证
  • MySQL--loaddata infile、outfile into及mysqldump高效导入导出数据_mysql load outfile
  • 小语言模型,生成式AI的未来?
  • GPIO【ARM接口技术】
  • 【实战篇】Idea 集成主流 AI 插件的方法实战