找回密码
 立即注册

QQ登录

只需一步,快速开始

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

DAB学习心得(G474_RX)

[复制链接]
ID:1175534 发表于 2026-7-31 21:50 | 显示全部楼层 |阅读模式
/* 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 "adc.h"
#include "dma.h"
#include "i2c.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "math.h"
#include <stdio.h>
#include <string.h>
#include "ssd1306.h"
#include "ssd1306_tests.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 */

/* 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                    // 采样率 100kHz
#define N 640                         // 数据块大小
uint16_t adc_buffer[N];         // ADC数据存放的数组
float energy[4];
int max_idx = 0;
int second_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);
}

//#define FS       64000U
//#define LFM_N     1280U
//#define PI        3.14159265358979323846f
///* LFM粗检测频率 */
//static const float lf[4] = { 25500.0f, 26500.0f, 28500.0f, 29500.0f};

///* LFM正交模板存放在Flash */
//static int16_t lfm_cos_q15[LFM_N];
//static int16_t lfm_sin_q15[LFM_N];
//#define LFM_FS       64000.0f
//#define LFM_F0       25000.0f
//#define LFM_F1       30000.0f
//#define LFM_T        0.020f  //持续时间
//#define LFM_N         1280U
//#define PI_F          3.14159265358979323846f
//static float lc[4];
//static uint32_t pe = 0;       /* 当前处理窗口终点 */
//static uint32_t first = 0;    /* 第一次低频窗口终点 */
//static uint32_t approx = 0;   /* LFM近似起点 */
//static uint8_t state = 0;     /* 0搜索,1精定位,2完成 */
//static uint8_t stage = 0;     /* LFM低频段检测状态 */
//void LFM_Template_Init(void)
//{
//    const float mu = (LFM_F1 - LFM_F0) / LFM_T;
//    uint32_t n;
//    for (n = 0; n < LFM_N; n++)
//    {
//        float t = (float)n / LFM_FS;
//        float phase = 2.0f * PI_F * (LFM_F0 * t + 0.5f * mu * t * t);
//        lfm_cos_q15[n] = (int16_t)(32767.0f * cosf(phase));
//        lfm_sin_q15[n] = (int16_t)(32767.0f * sinf(phase));
//    }
//}

///* 检测结果 */
//volatile uint8_t lfm_ok = 0;
//volatile uint32_t lfm_pos = 0;
//static float Coef(float f)
//{
//    return 2.0f * cosf(2.0f * PI * f / FS);
//}

///*================ LFM粗搜索 =================*/
//float e[4];
//float lo, hi;
//static uint8_t LFM_Search(uint32_t end, uint32_t *pos)  //窗口终点,LFM初步判定起点  双能量判定LFM粗边界
//{
//    uint32_t d;
//    if (end < 640U)
//        return 0;
//    Get640(end - 640U);
//
//    e[0]=GTZL_energy_fixed(win, &g_params[2][0]);  //能量计算
//    e[1]=GTZL_energy_fixed(win, &g_params[0][0]);
//    e[2]=GTZL_energy_fixed(win, &g_params[3][0]);
//    e[3]=GTZL_energy_fixed(win, &g_params[1][0]);
//    lo = e[0] + e[1];   //低频能量
//    hi = e[2] + e[3];   //高频能量
//
//    if (!stage)
//    {
//        if (lo > hi * 1.5f  &&  lo>10000) //低频能量>高频能量
//        {
//            stage = 1;
//            first = end;   //记录低频扫描点终点窗口坐标
//        }
//        return 0;
//    }
//    d = end - first;  //下一次LFM检测计数
//    if (d >= 320U && d <= 960U && hi > lo * 1.5f && end >= LFM_N  &&  hi>10000) //高频能量>低频能量
//    {
//        *pos = end - LFM_N;     //记录粗略LFM终止点
//        stage = 0;
//        return 1;
//    }
//    if (d > 960U)                                //误判跳出记录粗略LFM终止点
//        stage = 0;
//    return 0;
//}
//
///*================ LFM相关 =================*/
//static uint64_t LFM_Corr(uint32_t start, uint8_t step)
//{
//    int64_t i = 0, q = 0;
//    uint32_t n;
//
//    for (n = 0; n < LFM_N; n += step)
//    {
//        int32_t x = RG(start + n);
//
//        i += (int64_t)x * lfm_cos_q15[n];
//        q += (int64_t)x * lfm_sin_q15[n];
//    }
//    i >>= 15;
//    q >>= 15;
//    return (uint64_t)(i * i) + (uint64_t)(q * q);
//}
//
///* 在近似位置附近寻找LFM准确起点 */
//static uint32_t LFM_Find(uint32_t a)
//{
//    uint32_t now = wr;                                                                   // 已经采样点数
//    uint32_t old = now > RING_N ? now - RING_N : 0U;   // old 表示环形缓冲区中当前仍然有效的最早采样点。
//    uint32_t best = a;                                 // 迭代最优解
//    uint64_t max = 0, v;                                                           // v:当前候选位置的相关能量  max:目前找到的最大相关能量。
//    int32_t p;                                         // p 是当前正在测试的候选起点。
//
//    /* 粗搜索:±320点,每32点检测一次 */
//    for (p = (int32_t)a - 320; p <= (int32_t)a + 320;   p += 32)
//    {
//        if (p < 0 ||(uint32_t)p < old ||  (uint32_t)p + LFM_N > now)
//            continue;
//
//        v = LFM_Corr((uint32_t)p, 8);
//        if (v > max)
//        {
//            max = v;
//            best = (uint32_t)p;
//        }
//    }
//
//    /* 精搜索:最佳位置附近±8点 */
//    max = 0;
//    for (p = (int32_t)best - 8; p <= (int32_t)best + 8;  p++)
//    {
//        if (p < 0 ||(uint32_t)p < old || (uint32_t)p + LFM_N > now)
//            continue;
//        v = LFM_Corr((uint32_t)p, 1);
//        if (v > max)
//        {
//            max = v;
//            best = (uint32_t)p;
//        }
//    }
//    return best;
//}
//
///*================ 状态处理 =================*/
//static void LFM_Process(uint32_t end)
//{
//    switch (state)
//    {
//        case 0: /* 搜索LFM */
//        {
//                HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
//            if (LFM_Search(end, &lfm_pos))//approx
//            {
//                lfm_ok = 1;
//                state = 2;
//            }
//            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
//        }
//            break;
//        case 1: /* 等待足够数据并精定位 */
//            if (wr >= approx + LFM_N + 320U)
//            {
//                lfm_pos = LFM_Find(approx);
//                lfm_ok = 1;
//                state = 2;
//            }
//            break;
//        default: /* 已检测完成 */
//            break;
//    }
//}

///* 重新搜索下一帧LFM */
//void LFM_Reset(void)
//{
//    lfm_ok = 0;
//    stage = 0;
//    state = 0;
//}
///*================ 4FSK检测 =================*/
//#define FSK_GAP_N 640U
//
//static uint8_t fsk_run  = 0;     /* 正在解调 */
//static uint8_t fsk_step = 0;     /* 当前计算第几个频率 */
//static uint8_t fsk_base = 0;     /* 当前跳频基频编号 */
//static uint32_t fsk_pos = 0;     /* 当前码元起点 */
//
//static int32_t fsk_e[4];         /* 四个频率能量 */
//volatile uint8_t fsk_done = 0;
//
///*
// * 当前ADC_Save()把原始ADC值直接存入ring[],
// * 所以这里不加MID,直接复制。
// */
//static void FSK_Load640(uint32_t start)
//{
//    uint16_t i;
//    for (i = 0; i < N; i++)
//        win[i] = (uint16_t)RG(start + i);
//}
//
///* 找到头LFM后启动4FSK解调 */
//static void FSK_RT_Start(void)
//{
//    /* 20ms LFM + 10ms间隔 */
//    fsk_pos = lfm_pos + LFM_N + FSK_GAP_N;
//    receive_data = 0;
//    rx_count = 0;
//    fsk_step = 0;
//    fsk_run = 1;
//    fsk_done = 0;
//    /* 暂停继续搜索LFM */
//    state = 2;
//    lfm_ok = 0;
//
//    /* 防止原TIM2解调逻辑同时运行 */
//    rx_flag = 0;
//}
//
///*
// * 每次调用最多运行一次GTZL_energy_fixed()。
// * 单次最长阻塞时间约等于一个Goertzel的执行时间。
// */
//volatile uint8_t fsk_dbg = 0;
//volatile uint32_t fsk_age = 0;
//void FSK_RT_Task(void)
//{
//    uint8_t i, max;
//
//    /* 1:等待LFM检测成功 */
////    if (!fsk_run)
////    {
////        if (!lfm_ok)
////        {
////            fsk_dbg = 1;
////            return;
////        }
////        FSK_RT_Start();
////        fsk_dbg = 2;                /* FSK已经启动 */
////    }
//
//    if (lfm_ok == 1)
//    {
//        fsk_pos = lfm_pos + LFM_N + FSK_GAP_N;
//        fsk_age = (uint32_t)(wr - fsk_pos);
//        /* 3:当前码元的640点还未采完 */
//        if (fsk_age < N)
//        {
//            fsk_dbg = 3;
//            return;
//        }
//
//        /* 4:当前码元已经被环形缓存覆盖 */
//        if (fsk_age > RING_N)
//        {
//            fsk_dbg = 4;
//            fsk_run = 0U;
//            LFM_Reset();
//            return;
//        }
//
//        FSK_Load640(fsk_pos);
//        fsk_base = (uint8_t)(rx_count % NUM_FREQ);
//        fsk_step = 1U;
//        /* * 此处不能return* 直接继续计算第一个频率。 */
//    }
//
//    /* 5:正在执行第1~4路Goertzel */
//    fsk_dbg = 5;
//    i = fsk_step - 1U;
//    fsk_e[i] = GTZL_energy_fixed(win,  &g_params[fsk_base][i]);
//    fsk_step++;
//
//    /* 还没有计算完四个频率 */
//    if (fsk_step <= NUM_BIAS)
//        return;
//
//    /* 四路计算完成,选择能量最大者 */
//    max = 0U;
//
//    for (i = 1U; i < NUM_BIAS; i++)
//    {
//        if (fsk_e[i] > fsk_e[max])
//            max = i;
//    }
//
//    receive_data |=
//        (uint32_t)max << (rx_count * 2U);
//
//    rx_count++;
//    fsk_pos += N;
//    fsk_step = 0U;
//
//    fsk_dbg = 6;                    /* 一个码元完成 */
//
//    if (rx_count >= data_count)
//    {
//        fsk_run = 0U;
//        fsk_done = 1U;
//        LFM_Reset();
//    }
//}

/*================ 对外函数 =================*/
///* 初始化并启动ADC DMA */
//void LFM_Init(void)
//{
//    for (uint8_t i = 0; i < 4U; i++)
//        lc[i] = Coef(lf[i]);
//    wr = pe = 0;
//    pend = stage = state = lfm_ok = 0;
//    HAL_ADCEx_Calibration_Start(&hadc1);  //adc自校准;
//    LFM_Template_Init();
//    HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buffer, DMA_N);
//    HAL_TIM_Base_Start(&htim3);
//}

/*================ DMA数据保存 =================*/
#define DMA_N      640U    //全DMA数据量
#define HALF       320U    //半DMA数据量
#define RING_N    2048U    //
uint16_t adc_buffer[DMA_N];
static int16_t ring[RING_N];
static volatile uint32_t wr = 0;   // ADC总采样点数
static volatile uint8_t pend = 0;  //待处理数据块数量

#define SEG_N     320U  //过零检测范围
#define ZERO_TH    50  //噪声滞环
int LFM_pos=0;
uint32_t LFM_Flag=0;
uint32_t test=0;
static uint16_t win[N];

/*================ 基础函数 =================*/

static void Uint32ToBinary(uint32_t value, char *str)  //打印二进制数
{
    int i = 0;
    do
    {
        str[i++] = (value & 1U) ? '1' : '0';
        value >>= 1U;
    } while (value != 0U);
    str[i] = '\0';
    for (int j = 0; j < i / 2; j++)
    {
        char temp = str[j];
        str[j] = str[i - 1 - j];
        str[i - 1 - j] = temp;
    }
}

static int16_t RG(uint32_t n)
{
    return ring[n & (RING_N - 1U)];
}

static void Get640(uint32_t start)
{
    for (uint32_t i = 0; i < N; i++)
        win[i] = (uint16_t)RG(start + i);
}

static void ADC_Save(const uint16_t *src)
{
    uint32_t i, s = wr;
    for (i = 0; i < HALF; i++)
        ring[(s + i) & (RING_N - 1U)] =(int16_t)src[i];//前面为余除RING_N, - MID可减去偏置
    wr += HALF;                 //更新保留当前位
    if (pend < 6U)
        pend++;                  //待处理半数据块数量增加
}
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)  //DMA半中断
{
    if (hadc->Instance == ADC1)
    {
        ADC_Save(&adc_buffer[0]);
    }
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)          //DMA全中断
{
    if (hadc->Instance == ADC1)
    {
        ADC_Save(&adc_buffer[HALF]);
    }
}

/*================ 过零LFM检测 =================*/
/* 统计320点内的正向过零次数 */
static uint16_t ZeroCnt(uint32_t start)
{
    uint16_t i, cnt = 0;
    int8_t state = 0;
    for (i = 0; i < SEG_N; i++)
    {
        int16_t x = RG(start + i)-1990;        //偏置,需要修改
        if (x > ZERO_TH)
        {
            if (state < 0)
                cnt++;
            state = 1;
        }
        else if (x < -ZERO_TH)
        {
            state = -1;
        }
//        if(x>200 && test==0)
//        {
//                test=1;
//                        //HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);        //频率测试,可注释
//        }
    }
    return cnt;
}

/* 检验1280点是否为25kHz→30kHz上扫LFM */
int t=0;
static void LFM_Detect(uint32_t start)
{
        if(LFM_Flag==0)
        {
                uint16_t c;
                c = ZeroCnt(start);
                if (c>5 && HAL_GetTick()-t>50)                                 //完毕后间隔50ms检测
                {
                        LFM_pos=start+(1-c/128.f)*SEG_N;
                        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);        //频率测试,可注释
                        LFM_Flag = 1;
                        receive_data=0x00;
                }
        }
}
void FSK_Task(void)
{
        if(LFM_Flag!=0)  //接收判定
                {
                        if(LFM_Flag<=10)
                        {
                                LFM_Flag+=1;
                                return;
                        }
                        if(time_count_rx==0)
                        {
                                if(rx_count==data_count)
                                {
                                        count=receive_data; //写入数字
                                         snprintf(buff, sizeof(buff), "RX:%d", count); //最多写入 size - 1 个字符(保留一个位置给字符串结束符 \0)count = 2026; // 某个值
                        //                snprintf(buff, sizeof(buff), "RX:0x%X", count); // 十六进制大写

                                        //------------------二进制------------------//
//                                        count=receive_data; //写入数字
//                                        char bin[48];
//                                        Uint32ToBinary((uint32_t)count, bin);
//                                        snprintf(buff, sizeof(buff), "Receive:%s", bin);
                                        //------------------二进制------------------//

                                        ssd1306_Fill(White);
                                        ssd1306_SetCursor(2, 18);
                                        ssd1306_WriteString(buff,Font_11x18, Black);
                                        ssd1306_UpdateScreen();
                        //                char *msg = "Hello";               // 可变字符串,可任意修改
                        //                snprintf(buff, sizeof(buff), "%d%s", count, msg);
//                                        ssd1306_Fill(White);
//                                        ssd1306_SetCursor(2, 18);
//                                        ssd1306_WriteString(buff, Font_11x18, Black);
//                                        ssd1306_UpdateScreen();

                                        LFM_Flag=0;
                                        rx_count=0;
                                        time_count_rx=0;
                                        t=HAL_GetTick();
                                        return;
                                }
                                Get640(LFM_pos+640*(rx_count+4));
                                for (int i = 0; i < NUM_BIAS; 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(win,rx_count % NUM_FREQ,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;
                                }
                                
                                second_idx = (max_idx == 0) ? 1 : 0;
                                for (int i = 0; i < NUM_BIAS; i++)
                                {
                                    if ((i != max_idx) && (energy[i] > energy[second_idx]))
                                    {
                                        second_idx = i;
                                    }
                                }
                                if( energy[max_idx]<2*energy[second_idx])  //判决比
                                {
                                        receive_data=0x00;
                                          LFM_Flag=0;
                                        rx_count=0;
                                        time_count_rx=0;
                                        t=HAL_GetTick();
                                        return;
                                }
                                receive_data= (max_idx<<(rx_count*2)) | receive_data;
//                                if(rx_count==2)
//                                        test=1;
                                rx_count+=1;  //固定接收注释
                        }
                        time_count_rx = (time_count_rx + 1) % 2; //x次数清零,接收时间x次中断
                }
}
/* 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_DMA_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
  GTZL_init();
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, N);
//  __HAL_DMA_ENABLE_IT(&hdma_adc1, DMA_IT_HT);  //hdma_spi_rx
//  __HAL_DMA_ENABLE_IT(&hdma_adc1, DMA_IT_TC);
//  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_IT(&htim2);                                                        //启动定时器中断
  HAL_TIM_Base_Start(&htim3);
  HAL_TIM_Base_Start_IT(&htim4);                                                        //启动定时器中断
  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 占空比

//        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();

  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
                while (pend>0)
                {
                        //HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);        //频率测试,可注释
                        __disable_irq();  //关闭中断防止冲突
                        pend--;
                        __enable_irq();
                        LFM_Detect(wr - HALF);
                        FSK_Task();
                }
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {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();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != 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;
}

//定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        if (htim->Instance == TIM2) // TIM2触发中断
        {
                if(rx_flag==1)  //修改则关闭接收
                {
                        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次中断
                }
                /////////////////////* 实时解调 *///////////////////////////////
        }
}


/* 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 单片机教程网

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