找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3|回复: 0
收起左侧

DAB学习心得(G474_TX)

[复制链接]
ID:1175534 发表于 2026-7-31 21:49 | 显示全部楼层 |阅读模式
/* 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 */
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表