亚洲春色中文字幕久久久-三上亚,91精品国产亚一区二区三区,久久久九色综合亚洲成色777,涩涩视频下载,国产午夜亚洲精品午夜鲁丝片,国产精品A一区二区三区腾讯导航,影音先锋色情AV在线看片,蜜臀国产在线视频,极品少妇高潮啪啪无码吴梦梦 ,精品人妻无码一区二区三区手机版

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 136|回復(fù): 0
收起左側(cè)

DAB學(xué)習(xí)心得(G474_RX)

[復(fù)制鏈接]
ID:1175534 發(fā)表于 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                  //頻率信號發(fā)送數(shù)量,發(fā)送位數(shù)➗️2
int Period = 64000000;                //MCU主頻率
int tx_count = 0;                          //發(fā)送數(shù)據(jù)計數(shù)
int time_count = 0;                  //發(fā)送時間數(shù)據(jù)計數(shù)
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;        //單次發(fā)送數(shù)據(jù)
uint8_t tx_flag=0;          //發(fā)送判定符號
void caculate_data_code(uint32_t single_data);

uint8_t rx_flag=0;          // 接收判定符號
int rx_count=0;                          // 發(fā)送數(shù)據(jù)計數(shù)
#define Fs 64000                    // 采樣率 100kHz
#define N 640                         // 數(shù)據(jù)塊大小
uint16_t adc_buffer[N];         // ADC數(shù)據(jù)存放的數(shù)組
float energy[4];
int max_idx = 0;
int second_idx = 0;
int time_count_rx=0;                // 接收時間數(shù)據(jù)計數(shù)
uint32_t receive_data=0x00;        // 單次發(fā)送數(shù)據(jù)

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 以適應(yīng) 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;
    // 循環(huán)展開 (手動展開可進一步加速)
    for (int i = 0; i < N; i++)
    {
        // 將采樣值轉(zhuǎn)為 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 (縮放調(diào)整)
    int64_t real2 = (int64_t)real * real;
    int64_t imag2 = (int64_t)imag * imag;
    return (int32_t)((real2 + imag2) >> 15); // 右移 15 調(diào)整量級
}

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;  //調(diào)用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  //持續(xù)時間
//#define LFM_N         1280U
//#define PI_F          3.14159265358979323846f
//static float lc[4];
//static uint32_t pe = 0;       /* 當(dāng)前處理窗口終點 */
//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低頻段檢測狀態(tài) */
//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));
//    }
//}

///* 檢測結(jié)果 */
//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檢測計數(shù)
//    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相關(guān) =================*/
//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;                                                                   // 已經(jīng)采樣點數(shù)
//    uint32_t old = now > RING_N ? now - RING_N : 0U;   // old 表示環(huán)形緩沖區(qū)中當(dāng)前仍然有效的最早采樣點。
//    uint32_t best = a;                                 // 迭代最優(yōu)解
//    uint64_t max = 0, v;                                                           // v:當(dāng)前候選位置的相關(guān)能量  max:目前找到的最大相關(guān)能量。
//    int32_t p;                                         // p 是當(dāng)前正在測試的候選起點。
//
//    /* 粗搜索:±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;
//}
//
///*================ 狀態(tài)處理 =================*/
//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: /* 等待足夠數(shù)據(jù)并精定位 */
//            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;     /* 正在解調(diào) */
//static uint8_t fsk_step = 0;     /* 當(dāng)前計算第幾個頻率 */
//static uint8_t fsk_base = 0;     /* 當(dāng)前跳頻基頻編號 */
//static uint32_t fsk_pos = 0;     /* 當(dāng)前碼元起點 */
//
//static int32_t fsk_e[4];         /* 四個頻率能量 */
//volatile uint8_t fsk_done = 0;
//
///*
// * 當(dāng)前ADC_Save()把原始ADC值直接存入ring[],
// * 所以這里不加MID,直接復(fù)制。
// */
//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解調(diào) */
//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;
//    /* 暫停繼續(xù)搜索LFM */
//    state = 2;
//    lfm_ok = 0;
//
//    /* 防止原TIM2解調(diào)邏輯同時運行 */
//    rx_flag = 0;
//}
//
///*
// * 每次調(diào)用最多運行一次GTZL_energy_fixed()。
// * 單次最長阻塞時間約等于一個Goertzel的執(zhí)行時間。
// */
//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已經(jīng)啟動 */
////    }
//
//    if (lfm_ok == 1)
//    {
//        fsk_pos = lfm_pos + LFM_N + FSK_GAP_N;
//        fsk_age = (uint32_t)(wr - fsk_pos);
//        /* 3:當(dāng)前碼元的640點還未采完 */
//        if (fsk_age < N)
//        {
//            fsk_dbg = 3;
//            return;
//        }
//
//        /* 4:當(dāng)前碼元已經(jīng)被環(huán)形緩存覆蓋 */
//        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* 直接繼續(xù)計算第一個頻率。 */
//    }
//
//    /* 5:正在執(zhí)行第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();
//    }
//}

/*================ 對外函數(shù) =================*/
///* 初始化并啟動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數(shù)據(jù)保存 =================*/
#define DMA_N      640U    //全DMA數(shù)據(jù)量
#define HALF       320U    //半DMA數(shù)據(jù)量
#define RING_N    2048U    //
uint16_t adc_buffer[DMA_N];
static int16_t ring[RING_N];
static volatile uint32_t wr = 0;   // ADC總采樣點數(shù)
static volatile uint8_t pend = 0;  //待處理數(shù)據(jù)塊數(shù)量

#define SEG_N     320U  //過零檢測范圍
#define ZERO_TH    50  //噪聲滯環(huán)
int LFM_pos=0;
uint32_t LFM_Flag=0;
uint32_t test=0;
static uint16_t win[N];

/*================ 基礎(chǔ)函數(shù) =================*/

static void Uint32ToBinary(uint32_t value, char *str)  //打印二進制數(shù)
{
    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;                 //更新保留當(dāng)前位
    if (pend < 6U)
        pend++;                  //待處理半數(shù)據(jù)塊數(shù)量增加
}
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檢測 =================*/
/* 統(tǒng)計320點內(nèi)的正向過零次數(shù) */
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; //寫入數(shù)字
                                         snprintf(buff, sizeof(buff), "RX:%d", count); //最多寫入 size - 1 個字符(保留一個位置給字符串結(jié)束符 \0)count = 2026; // 某個值
                        //                snprintf(buff, sizeof(buff), "RX:0x%X", count); // 十六進制大寫

                                        //------------------二進制------------------//
//                                        count=receive_data; //寫入數(shù)字
//                                        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次數(shù)清零,接收時間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);                //設(shè)置 PWM 通道2 占空比
//  __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,1300);                //設(shè)置 PWM 通道3 占空比

//        a=HAL_I2C_IsDeviceReady(&hi2c1,60<<1,10,10000); //I2C connect right
//        ssd1306_TestFPS();
        ssd1306_Init();
//        count=2026; //寫入數(shù)字2026
//        snprintf(buff, sizeof(buff), "%dWelcome", count); //最多寫入 size - 1 個字符(保留一個位置給字符串結(jié)束符 \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();  //關(guān)閉中斷防止沖突
                        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位信號,信號分解數(shù)量
{
        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)  //基礎(chǔ)頻率編號,信號頻率編碼
{
        int ARR,f_tx;
        f_tx = f_base[fr_num] + f_bias[data];
        ARR=Period/f_tx;
        return ARR;
}

//定時器中斷回調(diào)函數(shù)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        if (htim->Instance == TIM2) // TIM2觸發(fā)中斷
        {
                if(rx_flag==1)  //修改則關(guān)閉接收
                {
                        for (int i=0;i<50;i++)
                        {
                                if(adc_buffer[i]>2100) //ADC判定接收閾值
                                {
                                        rx_flag=1;  //啟動接收
                                        receive_data=0x00;
                                        time_count_rx=1;//第一周期半拋棄,存儲新值|------------|---===(提取的數(shù)據(jù))------|
                                        //HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);        //頻率測試,可注釋
                                }
                        }
                }
                /////////////////////* 實時解調(diào) *///////////////////////////////
                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次數(shù)清零,接收時間x次中斷
                }
                /////////////////////* 實時解調(diào) *///////////////////////////////
        }
}


/* 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 */
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表