关于STM32F103输入捕获高精度采集频率信号的方法

这篇具有很好参考价值的文章主要介绍了关于STM32F103输入捕获高精度采集频率信号的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

前段时间需要做一款频率采集设备,由于成本考虑,使用了APM32F103作为主控,APM32F103和STM32F103基本完全通用,有极个别BUG。不影响本次试验。客户要求的频率信号为11KHz到23KHz,精度要求在任何频率范围误差不能大于当前频率的万分之一以上(排除温度影响),采集速度要100次每秒以上。占空比可能会有变化。这种要求其实也只能选择STM32的输入捕获功能,我使用TIM2时钟的外部输入捕获,定时器采用36MHz时钟,时钟两分频。硬件输入分频设置为不分频,因为外部有硬件滤波器和信号处理电路,在此则不加输入滤波器。(时钟跑72M,遇到定时器中断少进或多进的BUG,所以改为36M)
(注:2023/08/09修改了部分程序和文案修改)

一、程序思路

其实采集频率的思路很简单,就是根据脉冲与脉冲直接的时间长短,得出周期时间。我采用的是全部上升沿捕获,而不是上升沿后改为下降沿。作用是防止占空比的变化影响采集精度。上升沿第一次进入中断后将TIM2计数器清空,将中间寄存器加一后退出,当中间寄存器大于等于10时,将TIM2中的计数值读取到采样寄存器中。当前采集到的就是80个输入脉冲周期的计数器值,根据要求,最小采样速度为100次每秒,11KHZ采集速度最快为137.5次每秒,也勉强满足要求。

二、程序

定时器初始化代码:

void TIM2_signal_input_Init(void)
{	 
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//使能TIM2时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);						 //PA0 下拉
	
	//定时器
	TIM_TimeBaseStructure.TIM_Prescaler =1; 	//预分频  
	TIM_TimeBaseStructure.TIM_Period = 0XFFFF; //自动重装值 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 
  
	//输入捕获
	TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1;//该是那就映射到那
	TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 //配置输入分频,不分频 
    TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	//上升沿捕获
    TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
    TIM2_ICInitStructure.TIM_ICFilter = 0x00;//不滤波
    TIM_ICInit(TIM2, &TIM2_ICInitStructure);
	
	//中断
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中断
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级2级
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 
	TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断	
    TIM_Cmd(TIM2,ENABLE ); 	//使能定时器2
}

中断代码:

//定时器2中断服务程序	 
void TIM2_IRQHandler(void)
{ 
 static unsigned char H_C=0;
	 
 	if((TIM2CH1_CAPTURE_STA&0X80)==0)//捕获成功后等待数据处理完成后,再次捕获	
	{	  
		if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
		{	    
			if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)  //频率太低了,不检测了
			{
				TIM2CH1_CAPTURE_STA|=0X80;
				TIM2CH1_CAPTURE_VAL=0XFFFF;
			}
			else TIM2CH1_CAPTURE_STA++;	 
		}
	if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
		{	
			if(TIM2CH1_CAPTURE_STA&0X40)		
			{//捕获10个周期了	
				TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
				TIM2CH1_CAPTURE_STA|=0X80;		//出去处理数据,防止再次进入中断
			}else  								
			{//第一次捕获上升沿
			    if(H_C==0)
			    {
				  TIM2CH1_CAPTURE_STA=0;			//清空
				  TIM2CH1_CAPTURE_VAL=0;
				  TIM_SetCounter(TIM2,0);
				}
				H_C++;
				if(H_C==divider)  //divider :该变量表示将多少个频率周期整合在一起运算,以降低误差
				{//捕获(divider-1)个周期了
				   H_C=0;
				   TIM2CH1_CAPTURE_STA|=0X40;		
				}
			}		    
		}			     	    					   
 	}
 
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}

转换为实际频率:

		 if(TIM2CH1_CAPTURE_STA&0X80)//成功捕获到八分频扭矩频率周期
		{
			temp=TIM2CH1_CAPTURE_STA&0X3F;
			temp*=65536;//溢出时间总和
			temp+=TIM2CH1_CAPTURE_VAL;//得到总的时间
			frequent_input=(36000000.0*divider)/temp; //根据当前的分频系数divider计算实际值
			frequent_input=frequent_input-(pow((frequent_input/100),2)*(0.00312/(divider)));//消除静差 
	        if(frequent_input>1000) divider=frequent_input/1000;     //根据当前频率大小修改下次采集的分频系数
	        else divider=1;	
			ui_cst=(unsigned int)frequent_input;
			
			//备注:上面的系数0.00312可根据实际误差修改,采集到的频率数据偏大,则将该数据增加,反之减小。
			//系数的目的为消除定时器在进入中断时,没有迅速读取CNT的数据,而多累加的值。
	        //可以自己加入数据输出函数
	        //
	        //
	        
		    TIM2CH1_CAPTURE_STA=0;			
		}

下载到板子

这是20KHZ,实际采样和输出对比。
stm32输入捕获最高频率,单片机,stm32,嵌入式硬件
stm32输入捕获最高频率,单片机,stm32,嵌入式硬件
这是10KHZ,实际采样和输出对比。
stm32输入捕获最高频率,单片机,stm32,嵌入式硬件

stm32输入捕获最高频率,单片机,stm32,嵌入式硬件

三、程序移植

因为我现在的程序在一个较为大型程序中,剔除的话有很多变量和函数封装。而且上面的这段程序有很大的优化空间。谨慎移植。很多读者想了解移植办法,那我就简单说下移植办法。这三个程序段则为整个数据处理的底层。仅仅是部分全局变量未加入其中。

void TIM2_signal_input_Init(void) 这个函数放在主函数的初始化中。裸机时放在main函数的主while循环前。
void TIM2_IRQHandler(void) 这个函数就是中断服务函数,没强制要求放在固定位置。
if(TIM2CH1_CAPTURE_STA&0X80) 开头的函数为数据处理函数,如果使用RTOS,则最好使用消息队列。如果是裸机跑的话,建议放在main函数的主while循环内,或者定时器的中断服务函数内。

总结

如果要求采样速度有降低,可以分频系数拉大,数据可以更精确。当前程序实际测试重复精度在十万分之五左右。可以看出程序和正点原子很像,感谢正点原子的教程与例程参考。文章来源地址https://www.toymoban.com/news/detail-618028.html

到了这里,关于关于STM32F103输入捕获高精度采集频率信号的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 关于两个STM32F103系列单片机的蓝牙通信

       毕设做的是掌控小车,因此采用蓝牙通信作为小车和手部通信,前段时间做出实物,对其遇到的问题以及解决的方法做一些总结。一个主控芯片采用STM32F103ZET6,另一个主控芯片采用STM32F103C8T6,原因是本来准备了两个主控C8T6,不小心烧了一个。 1.两个蓝牙的配对  需要准

    2024年02月13日
    浏览(58)
  • STM32F103C8T6 ADC输入电流电压特性

    ADC 输入电压范围:0-VDDA(0-3.3V) 输入电流范围:0-220µA 输入电阻:50kΩ 采样频率:0.6-14MHz   官方STM32C103C8系列数据手册: https://www.st.com/en/microcontrollers-microprocessors/stm32f103c8.html

    2024年02月13日
    浏览(38)
  • [嵌入式软件][启蒙篇][仿真平台] STM32F103实现串口输出输入、ADC采集

    上一篇:[嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键 学C语言时,使用的printf()函数,就是通过串口打印出来的。 跟外部器件通信,比如GPS模块、蓝牙模块、wifi模块; 两个开发板之间通信,制定私有协议。 PC电脑通信,使用上位机显示数据或控制下位机。 操作:打

    2024年01月22日
    浏览(65)
  • 关于stm32f103 PA15,PA12,PB3 io配置过程中遇见的大坑

    1.四种输入 浮空输入 GPIO_Mode_IN_FLOATING 浮空输入使用过程中,io口的电平由输入端决定 模拟输入 GPIO_Mode_AIN 上拉输入 GPIO_Mode_IPU 上拉输入过程中,io口会接一个上拉电阻,默认电平为高电平。 下拉输入 GPIO_Mode_IPD 下拉输入过程中,io口会接一个下拉电阻,默认电平为低电平 2

    2024年02月14日
    浏览(38)
  • stm32f103VET6和stm32f103c8t6有什么区别?

    我来终结下这个问题。 这两款单片机我都用过,其中无际单片机特训营其中一款wifi报警主机项目就是用了stm32f103c8t6。  stm32f103VET6和stm32f103c8t6都是STMicroelectronics公司推出基于ARM Cortex-M3内核的单片机。 它们在硬件规格和性能上存在一些差异,下面我详细讲解下它们的差异之处

    2024年02月15日
    浏览(58)
  • STM32F103RC

    ·多参考手册 ·协议USART、I2C、SPI 嵌入式系统跟ARM处理器 嵌入式系统: 专用计算机系统,以应用为中心,软硬件可裁减 组成: 硬件:(MPU)微处理器、存储器、I/O接口、输入输出设备。 软件:Embedded RTOS、应用软件。 最小系统:微控制器(MCU)、微处理器(MPU)、电源模块、

    2024年02月12日
    浏览(49)
  • STM32F103的中断

    CM3 内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有 256级的可编程中断设置。 CM3中每个中断通道都具备自己的8位中断优先级控制字节, 但STM32 并没有使用 CM3 内核的全部东西,STM32F103中只使用4位,高4位有效。 用于表达优先级的高4位又被分为组成

    2024年02月08日
    浏览(45)
  • STM32F103学习笔记 | 4.STM32F103芯片介绍

    STM32F1入门学习将使用STM32F103C8T6开发板最小系统板。小R为什么选择它来入门呢?咳咳~首先,ST官方提供强大且易用的标准库函数,使得开发过程方便快捷;其次,网上的教程资料多也十分详细。所以呢,它对高校学生和广大初学者入门都是一个非常好的选择。 开发板的实物图

    2024年04月25日
    浏览(42)
  • STM32F103制作FlashDriver

    在汽车行业控制器软件刷新流程中,一般会将Flash驱动单独进行刷写,目的是防止程序中一直存在Flash驱动的话,可能会造成对APP软件的异常操作,导致应用程序无法执行。本文介绍STM32F103使用KEIL生成指定FlashDriver地址的hex文件,然后使用HexView命令行提取FlashDriver及Remapping f

    2024年02月14日
    浏览(39)
  • STM32F103学习(ADC)

    1、定义 ADC(Analog-to-Digital Converter  模数转换器 )。是指将连续变化的模拟信号转换为离散的数字信号的器件。 2、原理 stm32上的ADC外设采用逐次比较的方式。 逐次比较型ADC工作原理可以类比天平称物体。比如我们假定要称一个21g的物体,我们有16g、8g、4g、2g、1g的砝码。一开

    2024年02月10日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包