/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#include "ssd1306_tests.h"
#include "PID_Control.h"
//#include "ssd1306.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/* 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 */
#define M_PI 3.14159265358979323846f
int a=1;
uint8_t data=0;
uint8_t data1=0;
uint8_t data2=0;
uint8_t data_spi=0;
uint8_t data_out[2]={0};
uint8_t tx_data = 0xA5;
uint8_t rx_data = 0;
uint32_t spi_error;
uint32_t spi_state;
float target_value,ture_value;
float fs,duty;
int count=0;
uint16_t Z_A=0;
char buff[64];
//FHSS--4FSK
#define NUM_FREQ 5
#define NUM_BIAS 4
#define data_count 16 //频率信号发送数量,发送位数➗️2
int Period = 64000000; //MCU主频率
int tx_count = 0; //发送数据计数
int time_count = 0; //发送时间数据计数
int f_base[NUM_FREQ] = {25500, 26500, 25000, 26000, 27000}; //基频
int f_bias[NUM_BIAS] = {0, 100, 200 ,300}; //信号偏置频率
uint8_t fs_tx_buff[data_count] = {0}; //信号的偏置频率编码
uint32_t single_data=0x35; //单次发送数据
uint8_t tx_flag=0; //发送判定符号
void caculate_data_code(uint32_t single_data);
uint8_t rx_flag=0; // 接收判定符号
int rx_count=0; // 发送数据计数
#define Fs 64000 // 采样率
#define N 640 // 数据块大小
uint16_t adc_buffer[N]; // ADC数据存放的数组
float energy[4];
int max_idx = 0;
int time_count_rx=0; // 接收时间数据计数
uint32_t receive_data=0x00; // 单次发送数据
typedef struct {
int16_t coeff_Q15; // 2*cos(omega) / 2 (范围 [-1,1])
int16_t cos_Q15; // cos(omega)
int16_t sin_Q15; // sin(omega)
} GTZLParam;
static GTZLParam g_params[NUM_FREQ][NUM_BIAS];
void GTZL_init(void)
{
const float Q15_SCALE = 32768.0f;
for (int i = 0; i < NUM_FREQ; i++)
{
for (int j = 0; j < NUM_BIAS; j++)
{
float k = (N * (f_base[i]+f_bias[j])) / Fs;
float omega = (2.0f * 3.141592653589793f * k) / N;
float coeff = 2.0f * cosf(omega);
// 存储 coeff/2 以适应 Q15 范围 [-1, 1)
g_params[i][j].coeff_Q15 = (int16_t)((coeff * 0.5f) * Q15_SCALE + 0.5f);
g_params[i][j].cos_Q15 = (int16_t)(cosf(omega) * Q15_SCALE + 0.5f);
g_params[i][j].sin_Q15 = (int16_t)(sinf(omega) * Q15_SCALE + 0.5f);
}
}
}
int32_t GTZL_energy_fixed(uint16_t *samples, const GTZLParam *param) //定点GTZL
{
int32_t q0 = 0, q1 = 0, q2 = 0;
int16_t coeff_half = param->coeff_Q15;
int16_t cosv = param->cos_Q15;
int16_t sinv = param->sin_Q15;
// 循环展开 (手动展开可进一步加速)
for (int i = 0; i < N; i++)
{
// 将采样值转为 Q15 格式(0~4095 -> 0~32760)
int32_t x = (int32_t)samples[i] << 3; // 乘以 8
// 2 * (coeff_half * q1) >> 15
int32_t mul = (int32_t)((int64_t)coeff_half * q1 >> 15);
q0 = (mul << 1) - q2 + x; // q0 = 2*coeff_half*q1 - q2 + x
q2 = q1;
q1 = q0;
}
// 计算实部与虚部
int32_t real = q1 - (int32_t)((int64_t)q2 * cosv >> 15);
int32_t imag = (int32_t)((int64_t)q2 * sinv >> 15);
// 返回能量:real^2 + imag^2 (缩放调整)
int64_t real2 = (int64_t)real * real;
int64_t imag2 = (int64_t)imag * imag;
return (int32_t)((real2 + imag2) >> 15); // 右移 15 调整量级
}
int compute_energies(uint16_t *samples,int rx_count, int bias)
{
return GTZL_energy_fixed(samples, &g_params[rx_count][bias]);
}
float GTZL_magnitude_squared(uint16_t *samples, int target_freq) // 浮点GTZL
{
float k = (N * target_freq) / Fs;
float omega = (2.0f * M_PI * k) / (float)N; //调用math.h的pi
float coeff = 2.0f * cosf(omega);
float q0 = 0, q1 = 0, q2 = 0;
for (int i = 0; i < N; i++)
{
q0 = coeff * q1 - q2 + samples[i];//4096.f*3.3;
q2 = q1;
q1 = q0;
}
// 计算能量(幅度的平方),用于比较
float real = (q1 - q2 * cosf(omega));
float imag = (q2 * sinf(omega));
return (real * real + imag * imag);
}
/////////////////////* LFM检测 *///////////////////////////////
//#define LFM_FS 100000.0f // ADC采样率:100 kHz
//#define LFM_F0 25000.0f // 起始频率:25 kHz
//#define LFM_F1 30000.0f // 结束频率:30 kHz
//#define LFM_TIME 0.01f // LFM持续时间:10 ms
//#define LFM_SAMPLE_NUM 1000U // 100 kHz × 10 ms
//#define ADC_MID_VALUE 2048.0f // 12位ADC中点
///*
// * 理想匹配时归一化相关值约为0.5。
// * 实际可在0.15~0.35之间调整。
// */
//#define LFM_THRESHOLD 0.20f
//#define PI_F 3.14159265358979323846f
///**
// * @brief 在ADC数据中查找25 kHz->30 kHz的LFM信号
// * @param adc_data ADC采样数组
// * @param adc_length ADC数组长度,必须大于1000
// * @param peak_score 输出最大相关值,可以传NULL
// * @return >=0:LFM起始采样点
// * -1 :未检测到LFM
// * 例如返回500:
// * 表示LFM从adc_data[500]开始,
// * LFM结束位置约为adc_data[1499],
// * 后续数据从adc_data[1500]附近开始。
// */
//int32_t LFM_Find25To30k(const uint16_t *adc_data, uint32_t adc_length, float *peak_score)
//{
// static float template_cos[LFM_SAMPLE_NUM];
// static float template_sin[LFM_SAMPLE_NUM];
// static uint8_t template_initialized = 0U;
// float best_score = 0.0f;
// int32_t best_position = -1;
// uint32_t offset;
// uint32_t n;
//
// if ((adc_data == 0) || (adc_length < LFM_SAMPLE_NUM))
// {
// if (peak_score != 0)
// {
// *peak_score = 0.0f;
// }
// return -1;
// }
// /* 本地LFM模板只生成一次。* f(t) = f0 + μt * μ = (f1-f0)/T
// * phase(t) = 2π[f0*t + 0.5*μ*t²]*/
// if (template_initialized == 0U)
// {
// const float sweep_rate =
// (LFM_F1 - LFM_F0) / LFM_TIME;
//
// for (n = 0U; n < LFM_SAMPLE_NUM; n++)
// {
// float t;
// float phase;
// t = (float)n / LFM_FS;
// phase = 2.0f * PI_F * (LFM_F0 * t + 0.5f * sweep_rate * t * t);
// template_cos[n] = cosf(phase);
// template_sin[n] = sinf(phase);
// }
// template_initialized = 1U;
// }
// /*滑动匹配滤波/互相关*/
// for (offset = 0U;offset <= adc_length - LFM_SAMPLE_NUM; offset++)
// {
// float correlation_i = 0.0f;
// float correlation_q = 0.0f;
// float signal_energy = 0.0f;
// float score;
// for (n = 0U; n < LFM_SAMPLE_NUM; n++)
// {
// float x;
// /*将12位无符号ADC转换为以0为中心的信号 */
// x = (float)adc_data[offset + n] - ADC_MID_VALUE;
// correlation_i += x * template_cos[n];
// correlation_q += x * template_sin[n];
// signal_energy += x * x;
// }
//
// /* * 信号过小时不进行判断。
// * 此处相当于要求ADC信号RMS大于约10个码 */
// if (signal_energy < (float)LFM_SAMPLE_NUM * 100.0f)
// {
// continue;
// }
//
// /*归一化非相干相关能量,使用I²+Q²避免未知初始相位造成相关结果下降 */
// score = (correlation_i * correlation_i + correlation_q * correlation_q) / (signal_energy * (float)LFM_SAMPLE_NUM);
// if (score > best_score)
// {
// best_score = score;
// best_position = (int32_t)offset;
// }
// }
// if (peak_score != 0)
// {
// *peak_score = best_score;
// }
// if (best_score >= LFM_THRESHOLD)
// {
// return best_position;
// }
// return -1;
//}
/////////////////////* LFM检测 *///////////////////////////////
/////////////////////* SPI *///////////////////////////////
//void NRF24_GPIO_Init(void)
//{
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); //CSN
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET); //CE
// HAL_Delay(100);
//}
//
//uint8_t NRF24_SPI_ReadWriteByte(uint8_t tx_data)
//{
// uint8_t rx_data = 0;
// HAL_SPI_TransmitReceive(&hspi1, &tx_data, &rx_data, 1, HAL_MAX_DELAY);
//
// //HAL_SPI_Receive(&hspi1, &rx_data, 1, HAL_MAX_DELAY);
// return rx_data;
//}
///**
// * @brief 向NRF24L01的指定寄存器写入一个值
// * @param reg: 寄存器地址
// * @param value: 要写入的值
// */
//void NRF24_Write_Reg(uint8_t reg, uint8_t value)
//{
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // 1. 片选信号拉低CSN,开始SPI事务
// NRF24_SPI_ReadWriteByte(reg); // 2. 发送寄存器地址(写入命令)
// NRF24_SPI_ReadWriteByte(value); // 3. 发送要写入的数据
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // 4. 拉高CSN,结束事务
//}
//
///**
// * @brief 读取NRF24L01的指定寄存器
// * @param reg: 寄存器地址
// * @retval 寄存器的值
// */
//uint8_t NRF24_Read_Reg(uint8_t reg)
//{
// uint8_t value;
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // 1. 拉低CSN,开始SPI事务
// NRF24_SPI_ReadWriteByte(reg); // 发送寄存器地址(读取命令)
// value = NRF24_SPI_ReadWriteByte(0xFF); // 发送0xFF,读取数据
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // 4. 拉高CSN,结束事务
// return value;
//}
//
//// 向指定寄存器写入多字节数据
//void NRF24_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t len)
//{
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // 1. 拉低CSN,开始SPI事务
// NRF24_SPI_ReadWriteByte(reg); // 发送寄存器地址(含指令)
// for (uint8_t i = 0; i < len; i++)
// {
// NRF24_SPI_ReadWriteByte(pBuf[i]); // 连续写入数据
// }
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // 4. 拉高CSN,结束事务
//}
//
//// 从指定寄存器读取多字节数据
//void NRF24_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t len)
//{
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // 1. 拉低CSN,开始SPI事务
// NRF24_SPI_ReadWriteByte(reg); // 发送寄存器地址(读指令)
// for (uint8_t i = 0; i < len; i++)
// {
// pBuf[i] = NRF24_SPI_ReadWriteByte(0xFF); // 发送0xFF读数据
// }
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // 4. 拉高CSN,结束事务
//}
//
///**
// * @brief 检查NRF24L01是否存活(通信是否建立)
// * @retval 1: 通信正常, 0: 通信失败
// */
//uint8_t NRF24_Check(void)
//{
// uint8_t tx_buf[5] = {0x01, 0x02, 0x03, 0x04, 0x05};
// uint8_t rx_buf[5] = {0};
// uint8_t i;
// uint8_t NRF24_WRITE_REG=0x20; //0010 0000
// uint8_t TX_ADDR=0x10;
// // 向TX_ADDR寄存器写入5字节数据
//// NRF24_Write_Buf(NRF24_WRITE_REG + 0x00, tx_d, 1); //写指令:001A AAAA
//// NRF24_Read_Buf(0x00, rx_buf, 5); //读指令:000A AAAA
// HAL_Delay(1000);
// NRF24_Write_Buf(NRF24_WRITE_REG + TX_ADDR, tx_buf, 5); //写指令:001A AAAA
// // 从TX_ADDR寄存器读取5字节数据
// NRF24_Read_Buf(TX_ADDR, rx_buf, 5); //读指令:000A AAAA
// for(i = 0; i < 5; i++)
// {
// if(rx_buf[i] != tx_buf[i])
// return 0; // 数据不一致,通信失败,231 = 0xE7常是SPI总线空闲状态或模块处于复位/掉电模式时读出的默认数据。
// }
// return 1; // 通信正常
//}
/////////////////////* SPI *///////////////////////////////
/////////////////////模拟boost测试////////////////////////////////
//float Vin = 12.0f; /* 假设固定输入电压 12V */
//float Vout = 0.f;
//float duty = 0.f;
//void boost_simulate(float duty,float Vin)
//{
// int r = (rand() % 7) - 3;
// if (duty >= 1.0f) duty = 0.99f; /* 防止分母为零 */
// if (duty < 0.0f) duty = 0.0f;
// Vout = Vin / (1.0f - duty)+r;
//}
/////////////////////模拟boost////////////////////////////////
/* 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_USART1_UART_Init();
/* USER CODE BEGIN 2 */
GTZL_init();
// HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, N);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2); //启动 PWM 通道2信号输出
// HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3信号输出
// HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3互补信号输出
HAL_TIM_Base_Start(&htim1);
// HAL_TIM_Base_Start(&htim3);
HAL_TIM_Base_Start_IT(&htim2); //启动定时器中断
HAL_Delay(100);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,1300); //设置 PWM 通道2 占空比
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,1300); //设置 PWM 通道3 占空比
/////////////////////* PID *///////////////////////////////
// PID_Init();
// PID_Control_Caculate(&PID_Voltage, target_value, ture_value);
/////////////////////* PID *///////////////////////////////
/////////////////////* 陀螺仪操作 *///////////////////////////
// a=HAL_I2C_IsDeviceReady(&hi2c1,104<<1,10,10000); //I2C connect right
// data=0b10000000; //Init zero
// HAL_I2C_Mem_Write(&hi2c1,104<<1,0x6b,1,&data,1,10000);//
// HAL_Delay(10);
// data=0b00000000; //Wake up
// HAL_I2C_Mem_Write(&hi2c1,104<<1,0x6b,1,&data,1,10000);//
// HAL_Delay(10);
// data=0b00011000; //Precision
// HAL_I2C_Mem_Write(&hi2c1,104<<1,0x1b,1,&data,1,10000);//
// HAL_Delay(10);
// HAL_I2C_Mem_Read(&hi2c1,104<<1,0x3F,1,data_out,2,10000);//前:实际寄存器地址大小,后:读取数据量
// Z_A=data_out[0]<<8|data_out[1]; //合并高8位和低8位
// HAL_I2C_Mem_Read(&hi2c1,104<<1,0x3F,1,&data1,1,10000);//
// HAL_I2C_Mem_Read(&hi2c1,104<<1,0x40,1,&data2,1,10000);//
/////////////////////* 陀螺仪操作 *///////////////////////////
/////////////////////* OLED操作 *///////////////////////////
// a=HAL_I2C_IsDeviceReady(&hi2c1,60<<1,10,10000); //I2C connect right
// ssd1306_TestFPS();
// ssd1306_Init();
// count=2026; //写入数字2026
// snprintf(buff, sizeof(buff), "%dWelcome", count); //最多写入 size - 1 个字符(保留一个位置给字符串结束符 \0)
// ssd1306_Fill(White);
// ssd1306_SetCursor(2, 18);
// ssd1306_WriteString(buff, Font_11x18, Black);
// ssd1306_UpdateScreen();
/////////////////////* OLED操作 *///////////////////////////
/////////////////////* SPI操作 *///////////////////////////
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); //CSN
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET); //CE
// NRF24_GPIO_Init();
// a=NRF24_Check();
// spi_state=HAL_SPI_GetState(&hspi1); //0:外设未初始化 1:外设已初始化并可使用
// spi_error=HAL_SPI_GetError(&hspi1); //0x00:函数执行成功。 0x01:发生错误。 0x02:SPI外设正在忙。 0x03:操作超时
// HAL_SPI_Transmit(&hspi1, &data_spi, 1, 10000);
// HAL_SPI_TransmitReceive(&hspi1, &tx_data, &rx_data, 1, HAL_MAX_DELAY);
// if (tx_data == rx_data)
// {
// a=0; // 回环测试通过
// } else
// {
// a=1; // 回环测试失败
// }
/////////////////////* SPI操作 *///////////////////////////
/////////////////////* GPIO操作 *///////////////////////////
// HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);
// HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8);
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
/////////////////////* GPIO操作 *///////////////////////////
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//printf("Hello, STM32F4!\r\n");
caculate_data_code(single_data); //编码
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==1)
{
tx_flag=1;
HAL_Delay(1000);
}
HAL_Delay(100);
////////////////* 位操作 *///////////////////////////
// buf[0] = test_data & 0xFF; // 提取低8位
// buf[1] = (test_data >> 8) & 0xFF; // 提取高8位
// a &= ~(0b00000100); //第三位置0 a |= (1<<2);
// a ^= 0b00000100; //第三位异或操作取反 a ^=(1<<2);
// a |= 0b00000100; //第三位置1 a |=(1<<2);
// if((a >> n) & 0b00000001); //n位判定
// (a & ~(0x01 << n)) | (x << n); //修改n位为x a |=(1<<2);
////////////////* 位操作 *///////////////////////////
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses 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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void caculate_data_code(uint32_t single_data) //8位信号,信号分解数量
{
for (int i=0;i<data_count;i++)
{
fs_tx_buff[i]= (single_data>>(i*2)) & 0x03; // 提取低2位,从低位到高位写入buff
//fs_tx_buff[i]= ((single_data<<(i*2)) & 0b11000000)>>6; // 提取高2位,从高位到低位写入buff
}
}
int caculate_data_ARR(uint8_t fr_num, uint8_t data) //基础频率编号,信号频率编码
{
int ARR,f_tx;
f_tx = f_base[fr_num] + f_bias[data];
ARR=Period/f_tx;
return ARR;
}
#define START_FREQ 25000.0f // 起始频率
#define END_FREQ 30000.0f // 终止频率
#define STEP_COUNT 20-1 // 步数(20ms / 1ms)-1
#define FREQ_STEP ((END_FREQ - START_FREQ) / STEP_COUNT) // 每步变频
uint32_t newARR = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器中断回调函数
{
if (htim->Instance == TIM2) // TIM2触发中断
{
if(tx_flag!=0) //发送判定
{
if(time_count<20) //LFM起始帧--20ms
{
fs=START_FREQ + time_count*FREQ_STEP;
newARR=Period/fs;
__HAL_TIM_SET_AUTORELOAD(&htim1, newARR); // 1. 修改自动重装载值 (改变频率)
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, (newARR + 1) / 2); // 2. 同时修改比较值,保持 50% 占空比 (针对通道1)
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3信号输出
HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3互补信号输出
}
if(time_count==20) //LFM起始帧--20ms
{
HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_3); //关闭PWM通道3信号输出
HAL_TIMEx_PWMN_Stop(&htim1,TIM_CHANNEL_3); //关闭启动PWM通道3互补信号输出
}
if(time_count>=40 && time_count<=200) //数据帧--x ms
{
if(time_count % 10==0)
{
if(tx_count==data_count)
{
tx_flag=2; //数据发送完毕
tx_count=0;
HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_3); //关闭PWM通道3信号输出
HAL_TIMEx_PWMN_Stop(&htim1,TIM_CHANNEL_3); //关闭启动PWM通道3互补信号输出
//return; //搭配下面if使用
}
if(tx_flag!=2)
{
newARR=caculate_data_ARR(tx_count % NUM_FREQ,fs_tx_buff[tx_count]); // 计算频率
__HAL_TIM_SET_AUTORELOAD(&htim1, newARR); // 1. 修改自动重装载值 (改变频率)
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, (newARR + 1) / 2); // 2. 同时修改比较值,保持 50% 占空比 (针对通道1)
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3信号输出
HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3互补信号输出
tx_count+=1; //发送数据编号+1 关闭则定频发送
}
}
}
if(time_count>=220 && time_count<240) //数据帧--x ms
{
fs=START_FREQ + (time_count-220)*FREQ_STEP;
newARR=Period/fs;
__HAL_TIM_SET_AUTORELOAD(&htim1, newARR); // 1. 修改自动重装载值 (改变频率)
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, (newARR + 1) / 2); // 2. 同时修改比较值,保持 50% 占空比 (针对通道1)
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3信号输出
HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); //启动 PWM 通道3互补信号输出
}
if(time_count==240) //数据帧--x ms
{
tx_flag=0;
HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_3); //关闭PWM通道3信号输出
HAL_TIMEx_PWMN_Stop(&htim1,TIM_CHANNEL_3); //关闭启动PWM通道3互补信号输出
}
time_count += 1; //x次数清零,发波时间x次中断
}
else
time_count=0;
// if(rx_flag==0) //修改则关闭接收
// {
// for (int i=0;i<50;i++)
// {
// if(adc_buffer[i]>2100) //ADC判定接收阈值
// {
// rx_flag=1; //启动接收
// receive_data=0x00;
// time_count_rx=1;//第一周期半抛弃,存储新值|------------|---===(提取的数据)------|
// HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8); //频率测试,可注释
// }
// }
// }
// /////////////////////* 实时解调 *///////////////////////////////
// if(rx_flag!=0) //接收判定
// {
// if(time_count_rx==0)
// {
// if(rx_count==data_count)
// {
// rx_flag=0;
// rx_count=0;
// time_count_rx=0;
// return;
// }
// for (int i = 0; i < 4; i++)
// {
// //energy[i] = GTZL_magnitude_squared(adc_buffer, f_base[0]+f_bias[i]);
// //energy[i] = GTZL_magnitude_squared(adc_buffer, f_base[rx_count]+f_bias[i]);
// HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8); //频率测试,可注释
// energy[i]=compute_energies(adc_buffer,rx_count % 4,i) ;
// HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8); //频率测试,可注释
// }
// max_idx=0;
// for (int i = 1; i < 4; i++)
// {
// if (energy[i] > energy[max_idx]) max_idx = i;
// }
// receive_data= (max_idx<<(rx_count*2)) | receive_data;
// rx_count+=1; //固定接收注释
// }
// time_count_rx = (time_count_rx + 1) % 2; //x次数清零,接收时间x次中断
// }
/////////////////////* 实时解调 *///////////////////////////////
/////////////////////* 延时解调 *///////////////////////////////
// if(rx_flag!=0) //接收判定
// {
// if(time_count_rx==0)
// {
// HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);
// if(rx_count==4)
// {
// rx_flag=0;
// rx_count=0;
// time_count_rx=0;
// return;
// }
//
// for (int i = 0; i < 4; i++)
// {
// Demodulation_buffer[i][N]=adc_buffer[N];
// }
// max_idx=0;
// for (int i = 1; i < 4; i++)
// {
// if (energy[i] > energy[max_idx]) max_idx = i;
// }
// receive_data= (max_idx<<(rx_count*2)) | receive_data;
// rx_count+=1;
// }
// time_count_rx = (time_count_rx + 1) % 10; //x次数清零,接收时间x次中断
// }
/////////////////////* 延时解调 *///////////////////////////////
}
}
/////////////////////* CRC-8校验*///////////////////////////
//unsigned char Crc8_Array[] = {
// 0x0, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x57, 0x78, 0x9, 0x26, 0xeb, 0xc4, 0xb5, 0x9a,
// 0xae, 0x81, 0xf0, 0xdf, 0x12, 0x3d, 0x4c, 0x63, 0xf9, 0xd6, 0xa7, 0x88, 0x45, 0x6a, 0x1b, 0x34,
// 0x73, 0x5c, 0x2d, 0x2, 0xcf, 0xe0, 0x91, 0xbe, 0x24, 0xb, 0x7a, 0x55, 0x98, 0xb7, 0xc6, 0xe9,
// 0xdd, 0xf2, 0x83, 0xac, 0x61, 0x4e, 0x3f, 0x10, 0x8a, 0xa5, 0xd4, 0xfb, 0x36, 0x19, 0x68, 0x47,
// 0xe6, 0xc9, 0xb8, 0x97, 0x5a, 0x75, 0x4, 0x2b, 0xb1, 0x9e, 0xef, 0xc0, 0xd, 0x22, 0x53, 0x7c,
// 0x48, 0x67, 0x16, 0x39, 0xf4, 0xdb, 0xaa, 0x85, 0x1f, 0x30, 0x41, 0x6e, 0xa3, 0x8c, 0xfd, 0xd2,
// 0x95, 0xba, 0xcb, 0xe4, 0x29, 0x6, 0x77, 0x58, 0xc2, 0xed, 0x9c, 0xb3, 0x7e, 0x51, 0x20, 0xf,
// 0x3b, 0x14, 0x65, 0x4a, 0x87, 0xa8, 0xd9, 0xf6, 0x6c, 0x43, 0x32, 0x1d, 0xd0, 0xff, 0x8e, 0xa1,
// 0xe3, 0xcc, 0xbd, 0x92, 0x5f, 0x70, 0x1, 0x2e, 0xb4, 0x9b, 0xea, 0xc5, 0x8, 0x27, 0x56, 0x79,
// 0x4d, 0x62, 0x13, 0x3c, 0xf1, 0xde, 0xaf, 0x80, 0x1a, 0x35, 0x44, 0x6b, 0xa6, 0x89, 0xf8, 0xd7,
// 0x90, 0xbf, 0xce, 0xe1, 0x2c, 0x3, 0x72, 0x5d, 0xc7, 0xe8, 0x99, 0xb6, 0x7b, 0x54, 0x25, 0xa,
// 0x3e, 0x11, 0x60, 0x4f, 0x82, 0xad, 0xdc, 0xf3, 0x69, 0x46, 0x37, 0x18, 0xd5, 0xfa, 0x8b, 0xa4,
// 0x5, 0x2a, 0x5b, 0x74, 0xb9, 0x96, 0xe7, 0xc8, 0x52, 0x7d, 0xc, 0x23, 0xee, 0xc1, 0xb0, 0x9f,
// 0xab, 0x84, 0xf5, 0xda, 0x17, 0x38, 0x49, 0x66, 0xfc, 0xd3, 0xa2, 0x8d, 0x40, 0x6f, 0x1e, 0x31,
// 0x76, 0x59, 0x28, 0x7, 0xca, 0xe5, 0x94, 0xbb, 0x21, 0xe, 0x7f, 0x50, 0x9d, 0xb2, 0xc3, 0xec,
// 0xd8, 0xf7, 0x86, 0xa9, 0x64, 0x4b, 0x3a, 0x15, 0x8f, 0xa0, 0xd1, 0xfe, 0x33, 0x1c, 0x6d, 0x42,
//};
//
//unsigned char Cal_Crc_LookupTable(unsigned char *ptr, unsigned char len)
//{
// unsigned char crc = 0x00;
//
// while (len--)
// {
// crc = Crc8_Array[crc ^ *ptr++];
// }
// return (crc);
//}
//
//int main()
//{
// unsigned char crc, data = 0xc5;
// crc = Crc8_Array[data];
// printf("单字节查表:0x%x \n", crc);
// crc = Cal_Crc_LookupTable(&data, sizeof(data));
// printf("多字节查表:0x%x", crc);
// return 0;
//}
/////////////////////* CRC-8校验*///////////////////////////
/* 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 */
__disable_irq();
while (1)
{
}
/* 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,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
|