STM32Cube配置等精度测频和测相位差

标题STM32Cube配置等精度测频和测相位差

一、测量精度:

1、频率精度

频率测量、周期测量的信号频率范围扩展为1Hz~20MHz(这里由于信号发生器最高产生20MHz频率,所以更高频率未尝试,预计更高可达到50MHz),频率测量、周期测量的测量误差为0.000001.

2、相位差精度

相位差测量,可以达到量程:0~360°;测量准确度:1°;分辨率:0.1°的题目要求

二、项目配置

1、时钟配置

stm32F429最高主频为168MHz
在这里插入图片描述
配置时钟源
在这里插入图片描述

2、定时器配置

  1. Time1配置
    在这里插入图片描述
  2. Time2配置
    在这里插入图片描述
  3. Time3配置
    在这里插入图片描述
    在这里插入图片描述
  4. Time4配置
    在这里插入图片描述
  5. Time5配置
    在这里插入图片描述
  6. Time8配置
    在这里插入图片描述
  7. Time9配置
    在这里插入图片描述
  8. Time12配置
    在这里插入图片描述
  9. 定时器优先级配置

在这里插入图片描述

3、生成工程配置

在这里插入图片描述
在这里插入图片描述

3、串口配置

配置两个串口,一个收一个发,防止数据传输时大彩屏卡死;
在这里插入图片描述
在这里插入图片描述

三、Keil5编写代码

1、main函数代码

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "base.h"       //包含基本按键、灯、位带操作等
#include "stdio.h"
#include "head_define.h"
#include "Algorithm.h"
#include "arm_math.h"
#include "hmi_user_uart.h"
#include "cmd_process.h"
#include "outputdata.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define Period_Num 1 
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/*测频测周变量定义*/
uint8_t     TIM4CH1_CAPTURE_STA=0X80;		//输入捕获状态		    				
uint32_t	TIM5_COUNTER_VAL[Period_Num];	        //定时器1计数组,测系统时钟
uint32_t    TIM2_COUNTER_VAL[Period_Num];          //定时器2计数组,被测信号周期
float	    TIM5_COUNTER_Val;	            //定时器1计数值,测系统时钟
float       TIM2_COUNTER_Val;               //定时器2计数值,被测信号周期
float       TIM_FREQ;                       //频率值
float       TIM_period;                     //周期值
uint8_t     TIM4CH1_CAPTURE_GATE=0;         //预设闸门标志位
uint8_t     TIM4CH1_CAPTURE_STB=0;          //数组存满标志位
static uint8_t     i,j=0;                       //数组用
uint32_t	TIM5_COUNTER_TEMP;	            //定时器1计数滤波
uint32_t    TIM2_COUNTER_TEMP;              //定时器2计数滤波
float       TIM_FREQ2; 
float       TIM_FREQ3; 
float       TIM_FERQ[5];

/*相位变量定义*/
uint32_t capture_period=0,capture_sta=0,capture_period1=0,capture_sta1=0;
float Phase=0,capture_period2=0;
//校准后的频率
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
   
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  MX_TIM5_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_TIM8_Init();
  MX_TIM9_Init();
  MX_TIM12_Init();
  /* USER CODE BEGIN 2 */
  TFT_Init();    
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);  //使能PWM波
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);  //使能PWM波 
  
  HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1); //使能TIM4输入捕获中断
  __HAL_TIM_ENABLE_IT(&htim4, TIM_CHANNEL_1); //使能更新中断
  HAL_TIM_Base_Start_IT(&htim1);             //使能TIM5定时器中断
  HAL_TIM_IC_Start_IT(&htim9,TIM_CHANNEL_1);
  HAL_TIM_IC_Start_IT(&htim12,TIM_CHANNEL_1);
//  HAL_TIM_Base_Start_IT(&htim1);//使能定时器1中断
  
    __HAL_TIM_SET_COUNTER(&htim5,0);      //定时器1清零
    __HAL_TIM_SET_COUNTER(&htim2,0);      //定时器2清零 
  
  TIM4CH1_CAPTURE_GATE = 1;               //开启预设闸门
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	 
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  capture_period2=capture_period/2.0;
	  Phase=((capture_period1-capture_period2)/capture_period1)*360.0+21;
      SetTFTText(0,3,"%.1f度",Phase);
	  SetTFTText(0,5,"%.2f",10.2);
	
	  HAL_Delay(100);
    if(TIM4CH1_CAPTURE_STB)//判断数组是否存满
    {     
		
        TIM5_COUNTER_Val = (float) TIM5_COUNTER_TEMP / Period_Num;    //定时器1计数滤波(100个数组求平均)
        TIM2_COUNTER_Val = (float) TIM2_COUNTER_TEMP / Period_Num;    //定时器2计数滤波 (100个数组求平均)      
        TIM_FREQ = 1000.0*(TIM2_COUNTER_Val*3000.0)/TIM5_COUNTER_Val; //定时器2计数值*定时器1频率/定时器1计数值

		   
			if(TIM_FREQ<=300)
			   {
		      TIM_FREQ2=TIM_FREQ*1.00020;
			  TIM_period=1.0/TIM_FREQ2;
			  SetTFTText(0,1,"%.6fHz",TIM_FREQ2);
			  SetTFTText(0,2,"%.6fs",TIM_period);
			   }else
			   {
		    TIM_FREQ2=TIM_FREQ*0.9999480027038594;
			TIM_period=1.0/TIM_FREQ2;
			  SetTFTText(0,1,"%.6fMHz",TIM_FREQ2/1000000.0);
			  SetTFTText(0,2,"%.6fus",TIM_period*1000000.0);
			   }
			
	
        
        TIM5_COUNTER_TEMP = 0;        //定时器5计数值清零
        TIM2_COUNTER_TEMP = 0;        //定时器2计数值清零
        TIM4CH1_CAPTURE_STB = 0;       //数组存满标志位
        TIM4CH1_CAPTURE_STA |= 0X80;    //输入捕获状态
        HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);//使能TIM4输入捕获中断
		  
    }  
	
    
   
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
//定时器TIM4输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{	 
	
//***********************************************************************
	//测频率
			if(TIM4CH1_CAPTURE_GATE==0)
			{   
				if(TIM4CH1_CAPTURE_STA&0X40)	//闸门关闭后第二次捕获到一个上升沿 		
				{	                      
					TIM4CH1_CAPTURE_STA = 0X80;		//标记成功捕获到闸门的一次高电平脉宽
					TIM5_COUNTER_VAL[i] = __HAL_TIM_GET_COUNTER(&htim5); //获取定时器1计数值
					TIM2_COUNTER_VAL[i] = __HAL_TIM_GET_COUNTER(&htim2); //获取定时器2计数值
				 
					TIM5_COUNTER_TEMP += TIM5_COUNTER_VAL[i];
					TIM2_COUNTER_TEMP += TIM2_COUNTER_VAL[i];
					

					i++;
							if(i == Period_Num)//100个闸门周期
							{                        
									i = 0;
									TIM4CH1_CAPTURE_STB = 1;//数组存满标志位
									TIM4CH1_CAPTURE_STA = 0;//标记捕获到了上升沿状态位清零
									HAL_TIM_IC_Stop_IT(&htim4,TIM_CHANNEL_1);  //关闭输入捕获
							}					
					HAL_TIM_Base_Stop(&htim5);            //关闭定时器5
					HAL_TIM_Base_Stop(&htim2);            //关闭定时器2   
					__HAL_TIM_SET_COUNTER(&htim5,0);      //定时器5清零
					__HAL_TIM_SET_COUNTER(&htim2,0);      //定时器2清零                

			}
			

}
			if(TIM4CH1_CAPTURE_GATE==1)
			{
					if(TIM4CH1_CAPTURE_STA&0X80)//第一次捕获上升沿
	        {
						TIM4CH1_CAPTURE_STA = 0X40;		//标记捕获到了上升沿开始计数
						HAL_TIM_Base_Start(&htim5);     //使能定时器1,对标准信号一直计数
						HAL_TIM_Base_Start(&htim2);     //使能定时器2,对被测信号一直计数
				}
	        }	

  ***********************************************************************
			//测相位 
		if(htim->Instance==TIM9)
		{
			if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
			{
				if(!capture_sta)
				{
					
					__HAL_TIM_SET_COUNTER(&htim9,0);
				}

			}		
			
		}
		
		if(htim->Instance==TIM12)
		{
			
			if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
			{
					HAL_TIM_IC_Stop_IT(&htim9,TIM_CHANNEL_1);
				   capture_period=__HAL_TIM_GET_COMPARE(&htim9,TIM_CHANNEL_1);	
				if(!capture_sta1)
				{	   

				__HAL_TIM_SET_COUNTER(&htim12,0);				
					capture_sta1=1;			
				}else
				{
					HAL_TIM_IC_Start_IT(&htim9,TIM_CHANNEL_1);
					__HAL_TIM_SET_COUNTER(&htim9,0);
					capture_period1=__HAL_TIM_GET_COMPARE(&htim12,TIM_CHANNEL_1);	
					capture_sta1=0;
				}
			}
			
		}	
			
		
}
 //定时器TIM5溢出中断处理回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(TIM1 == htim->Instance)
    { 
		
		PCout(9)=~PCout(9);
       if(TIM4CH1_CAPTURE_GATE)
       {
		   
            TIM4CH1_CAPTURE_GATE = 0;
       }
       else 
       {
            TIM4CH1_CAPTURE_GATE = 1;
       }
    }
	
	
	
	
}    



/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

2、大彩屏

在这里插入图片描述

3、项目接线连接

需要将Time3的CH3连接到Time4中,否则无法测量。

4、项目工程代码

如需项目工程代码,请关注公众号:漂流小江,在公众号发送“等精度测频”关键字即可获取代码

  • 8
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小江编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值