亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 601|回復: 4
打印 上一主題 下一主題
收起左側

哪位能幫忙解釋下AI寫數字正交解調是否正確?

[復制鏈接]
跳轉到指定樓層
樓主
ID:1066092 發表于 2026-3-12 15:38 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
我讓deepseek寫了個基于N32G031的數字正交解調,它呼啦啦寫了一堆如下:
  1. /**
  2.   ******************************************************************************
  3.   * @file    main.c
  4.   * @author  User
  5.   * @version V1.0.0
  6.   * @date    2026-03-12
  7.   * @brief   N32G031 數字正交解調示例程序
  8.   *          功能:1. 系統時鐘配置(HSE 8MHz -> PLL -> 48MHz,失敗則轉HSI 48MHz)
  9.   *                2. 內存RAM讀寫正確性檢查
  10.   *                3. ADC+DMA連續采樣
  11.   *                4. 數字正交解調處理
  12.   *                5. 串口輸出解調結果
  13.   ******************************************************************************
  14.   */

  15. #include "n32g031.h"
  16. #include "rcc.h"
  17. #include "gpio.h"
  18. #include "adc.h"
  19. #include "dma.h"
  20. #include "usart.h"

  21. /* 引腳功能定義 ****************************************************************/
  22. /*
  23.    ADC輸入引腳:PA0 - 模擬輸入,接收待解調的模擬信號
  24.    USART1:    PA9(TX) - 串口輸出解調結果
  25.                 PA10(RX) - 未使用,但保留配置
  26.    LED指示:    PB8 - 可選,用于指示系統狀態
  27. */

  28. /* 常量定義 ********************************************************************/
  29. #define ADC_BUFFER_SIZE         256                 /* ADC采樣緩沖區大小 */
  30. #define SAMPLE_RATE             48000               /* 采樣率 48Ksps */
  31. #define CARRIER_FREQ            4000                /* 載波頻率 4KHz */
  32. #define PI                      3.14159265358979f

  33. /* 全局變量 ********************************************************************/
  34. /* ADC采樣緩沖區 - 需DMA傳輸,注意內存對齊 */
  35. __align(4) uint16_t g_adcBuffer[ADC_BUFFER_SIZE] __attribute__((at(0x20000000)));

  36. /* 解調結果緩沖區 */
  37. int32_t g_iDemod[ADC_BUFFER_SIZE/2];    /* I路解調結果 */
  38. int32_t g_qDemod[ADC_BUFFER_SIZE/2];    /* Q路解調結果 */

  39. /* 正交解調系數表 - 避免實時計算sin/cos */
  40. __align(4) int16_t g_sinTable[ADC_BUFFER_SIZE];
  41. __align(4) int16_t g_cosTable[ADC_BUFFER_SIZE];

  42. volatile uint8_t g_adcCompleteFlag = 0;  /* ADC采樣完成標志 */
  43. volatile uint8_t g_sysErrorFlag = 0;     /* 系統錯誤標志 */

  44. /* 函數聲明 ********************************************************************/
  45. uint8_t SystemClock_Config(void);
  46. uint8_t Memory_Check(void);
  47. void GPIO_Config(void);
  48. void ADC_DMA_Config(void);
  49. void DemodTable_Init(void);
  50. void Demod_Process(void);
  51. void Serial_Init(uint32_t baudrate);
  52. void Serial_SendByte(uint8_t ucCh);
  53. void Serial_SendString(uint8_t *str);
  54. void Serial_SendNum(int32_t num);

  55. /**
  56.   * @brief  系統時鐘配置函數
  57.   * @param  無
  58.   * @retval 錯誤代碼:0=成功(HSE+PLL),1=HSE啟動失敗(已轉HSI),2=PLL鎖定失敗(已轉HSI)
  59.   * @note   優先使用HSE+PLL到48MHz,若失敗則自動切換到HSI+PLL到48MHz
  60.   */
  61. uint8_t SystemClock_Config(void)
  62. {
  63.     ErrorStatus HSEStartUpStatus;
  64.     uint32_t pllStartupCounter = 0;
  65.     uint8_t retVal = 0;
  66.    
  67.     /* 1. 復位RCC配置 */
  68.     RCC_DeInit();
  69.    
  70.     /* 2. 嘗試使能外部高速晶振(HSE)*/
  71.     RCC_HSEConfig(RCC_HSE_ON);
  72.    
  73.     /* 3. 等待HSE就緒,設置超時檢測 */
  74.     HSEStartUpStatus = RCC_WaitForHSEStartUp();
  75.    
  76.     if (HSEStartUpStatus == ERROR) {
  77.         /* HSE啟動失敗,切換到HSI */
  78.         retVal = 1;
  79.         
  80.         /* 配置HSI作為PLL輸入 */
  81.         RCC_HSICmd(ENABLE);
  82.         while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
  83.         
  84.         /* 配置FLASH等待周期 */
  85.         FLASH->ACR = FLASH_ACR_LATENCY_1;
  86.         FLASH->ACR |= FLASH_ACR_PRFTBE;
  87.         
  88.         /* PLL配置:HSI/1*6 = 48MHz */
  89.         RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_6);
  90.         
  91.         /* 使能PLL */
  92.         RCC_PLLCmd(ENABLE);
  93.         
  94.         /* 等待PLL就緒,帶超時檢測 */
  95.         pllStartupCounter = 0;
  96.         while (!RCC_GetFlagStatus(RCC_FLAG_PLLRDY) && (pllStartupCounter < 0x1000)) {
  97.             pllStartupCounter++;
  98.         }
  99.         
  100.         if (!RCC_GetFlagStatus(RCC_FLAG_PLLRDY)) {
  101.             retVal = 2;  /* PLL鎖定失敗,但HSI可用 */
  102.             /* 直接使用HSI作為系統時鐘 */
  103.             RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
  104.         } else {
  105.             /* 選擇PLL作為系統時鐘 */
  106.             RCC_SYSCLKConfig(RCC_SYSCLKSource_PLL);
  107.         }
  108.     } else {
  109.         /* HSE啟動成功,使用HSE+PLL */
  110.         /* 配置FLASH預取指及等待周期 */
  111.         FLASH->ACR = FLASH_ACR_LATENCY_1;
  112.         FLASH->ACR |= FLASH_ACR_PRFTBE;
  113.         
  114.         /* 配置PLL:HSE/1*6 = 48MHz */
  115.         RCC_PLLConfig(RCC_PLLSource_HSE, RCC_PLLMul_6);
  116.         
  117.         /* 使能PLL */
  118.         RCC_PLLCmd(ENABLE);
  119.         
  120.         /* 等待PLL就緒,帶超時檢測 */
  121.         pllStartupCounter = 0;
  122.         while (!RCC_GetFlagStatus(RCC_FLAG_PLLRDY) && (pllStartupCounter < 0x1000)) {
  123.             pllStartupCounter++;
  124.         }
  125.         
  126.         if (!RCC_GetFlagStatus(RCC_FLAG_PLLRDY)) {
  127.             retVal = 2;  /* PLL鎖定失敗,回退到HSI */
  128.             
  129.             RCC_HSICmd(ENABLE);
  130.             while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
  131.             RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
  132.         } else {
  133.             /* 選擇PLL作為系統時鐘 */
  134.             RCC_SYSCLKConfig(RCC_SYSCLKSource_PLL);
  135.             /* 等待PLL被確認為系統時鐘 */
  136.             while (RCC_GetSYSCLKSource() != RCC_CFG_SCLKSTS_PLL);
  137.         }
  138.     }
  139.    
  140.     /* 更新系統時鐘變量 */
  141.     SystemCoreClockUpdate();
  142.    
  143.     return retVal;
  144. }

  145. /**
  146.   * @brief  內存RAM讀寫檢查函數
  147.   * @param  無
  148.   * @retval 0: 內存檢查通過; 非0: 內存檢查失敗
  149.   * @note   本函數只做檢查并返回結果,錯誤處理由上層函數決定
  150.   *         若需要錯誤處理,可在此處添加回調函數接口
  151.   */
  152. uint8_t Memory_Check(void)
  153. {
  154.     volatile uint32_t *pMem;
  155.     volatile uint32_t testPattern;
  156.     uint32_t i;
  157.     uint8_t errorCount = 0;
  158.    
  159.     /* 測試地址范圍:SRAM起始地址到結束地址,步進4字節 */
  160.     /* N32G031 SRAM地址范圍:0x20000000 - 0x20001FFF (8KB) */
  161.    
  162.     /* 測試模式1:0xAAAAAAAA (1010交替) */
  163.     testPattern = 0xAAAAAAAA;
  164.     for (i = 0; i < 0x2000; i += 4) {
  165.         pMem = (volatile uint32_t *)(0x20000000 + i);
  166.         *pMem = testPattern;
  167.         if (*pMem != testPattern) {
  168.             errorCount++;
  169.         }
  170.     }
  171.    
  172.     /* 測試模式2:0x55555555 (0101交替) */
  173.     testPattern = 0x55555555;
  174.     for (i = 0; i < 0x2000; i += 4) {
  175.         pMem = (volatile uint32_t *)(0x20000000 + i);
  176.         *pMem = testPattern;
  177.         if (*pMem != testPattern) {
  178.             errorCount++;
  179.         }
  180.     }
  181.    
  182.     /* 測試模式3:遞增模式 */
  183.     for (i = 0; i < 0x2000; i += 4) {
  184.         pMem = (volatile uint32_t *)(0x20000000 + i);
  185.         *pMem = i;
  186.         if (*pMem != i) {
  187.             errorCount++;
  188.         }
  189.     }
  190.    
  191.     /*
  192.      * 錯誤處理接口說明:
  193.      * 若需要添加內存錯誤處理,可在errorCount > 0時調用以下函數:
  194.      * void MemoryError_Handler(uint8_t errCount) - 用戶自定義錯誤處理函數
  195.      * 當前版本僅返回錯誤計數,不進行具體處理
  196.      */
  197.    
  198.     return errorCount;
  199. }

  200. /**
  201.   * @brief  GPIO初始化函數
  202.   * @param  無
  203.   * @retval 無
  204.   */
  205. void GPIO_Config(void)
  206. {
  207.     GPIO_InitType GPIO_InitStructure;
  208.    
  209.     /* 使能GPIO時鐘 */
  210.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
  211.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
  212.    
  213.     /* 配置PA0為模擬輸入 - ADC輸入通道 */
  214.     GPIO_InitStructure.Pin        = GPIO_PIN_0;
  215.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN;      /* 模擬輸入模式 */
  216.     GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
  217.    
  218.     /* 配置PA9為復用推挽輸出 - USART1 TX */
  219.     GPIO_InitStructure.Pin        = GPIO_PIN_9;
  220.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;    /* 復用推挽輸出 */
  221.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  222.     GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
  223.    
  224.     /* 配置PA10為浮空輸入 - USART1 RX */
  225.     GPIO_InitStructure.Pin        = GPIO_PIN_10;
  226.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
  227.     GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
  228.    
  229.     /* 可選:配置PB8為推挽輸出 - LED指示 */
  230.     GPIO_InitStructure.Pin        = GPIO_PIN_8;
  231.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  232.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  233.     GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
  234.    
  235.     /* 初始狀態LED滅 */
  236.     GPIO_SetBits(GPIOB, GPIO_PIN_8);
  237. }

  238. /**
  239.   * @brief  ADC和DMA初始化函數
  240.   * @param  無
  241.   * @retval 無
  242.   * @note   配置ADC1連續采樣,DMA循環模式傳輸數據
  243.   */
  244. void ADC_DMA_Config(void)
  245. {
  246.     ADC_InitType ADC_InitStructure;
  247.     DMA_InitType DMA_InitStructure;
  248.    
  249.     /* 使能ADC和DMA時鐘 */
  250.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_ADC1, ENABLE);
  251.     RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
  252.    
  253.     /* ADC配置 [citation:1][citation:2] */
  254.     ADC_InitStructure.MultiChEn       = DISABLE;                /* 單通道模式 */
  255.     ADC_InitStructure.ContinueConvEn  = ENABLE;                 /* 連續轉換使能 */
  256.     ADC_InitStructure.ExtTrigSelect   = ADC_EXT_TRIGCONV_NONE;  /* 軟件觸發 */
  257.     ADC_InitStructure.DatAlign        = ADC_DAT_ALIGN_R;        /* 數據右對齊 */
  258.     ADC_InitStructure.ChsNumber       = 1;                      /* 1個通道 */
  259.     ADC_Init(ADC1, &ADC_InitStructure);
  260.    
  261.     /* 配置ADC規則通道:通道0,采樣時間 55.5周期 */
  262.     ADC_ConfigRegularChannel(ADC1, ADC_CH_SELECT_CH0, 1, ADC_SAMPLE_TIME_55CYCLES5);
  263.    
  264.     /* DMA配置 */
  265.     DMA_DeInit(DMA1_Channel1);
  266.    
  267.     /* 配置DMA傳輸參數 [citation:1] */
  268.     DMA_InitStructure.PeriphAddr      = (uint32_t)&ADC1->DAT;   /* 外設地址:ADC數據寄存器 */
  269.     DMA_InitStructure.MemAddr         = (uint32_t)g_adcBuffer;  /* 內存地址:采樣緩沖區 */
  270.     DMA_InitStructure.Direction       = DMA_DIR_PERIPH_SRC;     /* 方向:外設到內存 */
  271.     DMA_InitStructure.BufSize         = ADC_BUFFER_SIZE;        /* 傳輸數據大小 */
  272.     DMA_InitStructure.PeriphInc       = DMA_PERIPH_INC_DISABLE; /* 外設地址不遞增 */
  273.     DMA_InitStructure.DMA_MemoryInc   = DMA_MEM_INC_ENABLE;     /* 內存地址遞增 */
  274.     DMA_InitStructure.PeriphDataSize  = DMA_PERIPH_DATA_SIZE_HALFWORD; /* 外設數據寬度16位 */
  275.     DMA_InitStructure.MemDataSize     = DMA_MEM_DATA_SIZE_HALFWORD;    /* 內存數據寬度16位 */
  276.     DMA_InitStructure.CircularMode    = DMA_MODE_CIRCULAR;      /* 循環模式使能 */
  277.     DMA_InitStructure.Priority        = DMA_PRIORITY_HIGH;      /* 高優先級 */
  278.     DMA_InitStructure.Mem2Mem         = DMA_M2M_DISABLE;        /* 非內存到內存 */
  279.     DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  280.    
  281.     /* 配置DMA半傳輸和傳輸完成中斷 */
  282.     DMA_ConfigInterrupt(DMA1_Channel1, DMA_INT_HT | DMA_INT_TC, ENABLE);
  283.    
  284.     /* 使能DMA通道 */
  285.     DMA_EnableChannel(DMA1_Channel1, ENABLE);
  286.    
  287.     /* 使能ADC DMA請求 [citation:4] */
  288.     ADC_ConfigDMA(ADC1, ENABLE);
  289.    
  290.     /* 校準ADC */
  291.     ADC_StartCalibration(ADC1);
  292.     while (ADC_GetCalibrationStatus(ADC1));
  293.    
  294.     /* 使能ADC */
  295.     ADC_Enable(ADC1, ENABLE);
  296.    
  297.     /* 等待ADC就緒 */
  298.     while (ADC_GetFlagStatusNew(ADC1, ADC_FLAG_RDY) == RESET);
  299.    
  300.     /* 軟件觸發第一次ADC轉換 */
  301.     ADC_StartSoftwareConv(ADC1);
  302. }

  303. /**
  304.   * @brief  正交解調系數表初始化
  305.   * @param  無
  306.   * @retval 無
  307.   * @note   預計算正弦和余弦值,避免實時計算
  308.   */
  309. void DemodTable_Init(void)
  310. {
  311.     uint16_t i;
  312.     float phase;
  313.     float step = 2 * PI * CARRIER_FREQ / SAMPLE_RATE;
  314.    
  315.     for (i = 0; i < ADC_BUFFER_SIZE; i++) {
  316.         phase = step * i;
  317.         /* 縮放系數:將浮點數轉換為16位整數,縮放因子16384 */
  318.         g_sinTable[i] = (int16_t)(sinf(phase) * 16384);
  319.         g_cosTable[i] = (int16_t)(cosf(phase) * 16384);
  320.     }
  321. }

  322. /**
  323.   * @brief  DMA中斷處理函數
  324.   * @param  無
  325.   * @retval 無
  326.   */
  327. void DMA1_Channel1_IRQHandler(void)
  328. {
  329.     if (DMA_GetIntStatus(DMA1_Channel1, DMA_INT_TC) == SET) {
  330.         /* 傳輸完成中斷 */
  331.         g_adcCompleteFlag = 1;
  332.         DMA_ClearIntPending(DMA1_Channel1, DMA_INT_TC);
  333.         
  334.         /* 翻轉LED指示狀態 */
  335.         GPIOB->POD ^= GPIO_PIN_8;
  336.     }
  337.    
  338.     if (DMA_GetIntStatus(DMA1_Channel1, DMA_INT_HT) == SET) {
  339.         /* 半傳輸中斷 - 可在此處理前一半數據 */
  340.         DMA_ClearIntPending(DMA1_Channel1, DMA_INT_HT);
  341.     }
  342. }

  343. /**
  344.   * @brief  數字正交解調處理函數
  345.   * @param  無
  346.   * @retval 無
  347.   * @note   對ADC采樣數據進行正交解調,提取I/Q分量
  348.   */
  349. void Demod_Process(void)
  350. {
  351.     uint16_t i;
  352.     int32_t sumI, sumQ;
  353.     uint16_t sampleIndex;
  354.    
  355.     sumI = 0;
  356.     sumQ = 0;
  357.    
  358.     /* 對每個載波周期進行積分 */
  359.     for (i = 0; i < (ADC_BUFFER_SIZE / 2); i++) {
  360.         /* 每個解調點使用兩個采樣點進行相關運算 */
  361.         sampleIndex = i * 2;
  362.         
  363.         /* I路:乘以cos */
  364.         g_iDemod[i] = ((int32_t)g_adcBuffer[sampleIndex] * g_cosTable[sampleIndex] +
  365.                        (int32_t)g_adcBuffer[sampleIndex + 1] * g_cosTable[sampleIndex + 1]) >> 14;
  366.         
  367.         /* Q路:乘以sin */
  368.         g_qDemod[i] = ((int32_t)g_adcBuffer[sampleIndex] * g_sinTable[sampleIndex] +
  369.                        (int32_t)g_adcBuffer[sampleIndex + 1] * g_sinTable[sampleIndex + 1]) >> 14;
  370.         
  371.         sumI += g_iDemod[i];
  372.         sumQ += g_qDemod[i];
  373.     }
  374.    
  375.     /* 可通過串口輸出累積和或每個解調點 */
  376.     /* 此處輸出累積和作為示例 */
  377.     Serial_SendString((uint8_t*)"I: ");
  378.     Serial_SendNum(sumI);
  379.     Serial_SendString((uint8_t*)"  Q: ");
  380.     Serial_SendNum(sumQ);
  381.     Serial_SendString((uint8_t*)"\r\n");
  382. }

  383. /**
  384.   * @brief  串口初始化函數
  385.   * @param  baudrate: 波特率
  386.   * @retval 無
  387.   */
  388. void Serial_Init(uint32_t baudrate)
  389. {
  390.     USART_InitType USART_InitStructure;
  391.    
  392.     /* USART1時鐘已在GPIO配置中使能 */
  393.    
  394.     /* USART1 配置 */
  395.     USART_InitStructure.BaudRate            = baudrate;
  396.     USART_InitStructure.WordLength          = USART_WL_8B;
  397.     USART_InitStructure.StopBits            = USART_STPB_1;
  398.     USART_InitStructure.Parity              = USART_PE_NO;
  399.     USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
  400.     USART_InitStructure.Mode                = USART_MODE_TX | USART_MODE_RX;
  401.     USART_Init(USART1, &USART_InitStructure);
  402.    
  403.     /* 使能USART1 */
  404.     USART_Enable(USART1, ENABLE);
  405. }

  406. /**
  407.   * @brief  串口發送一個字節
  408.   * @param  ucCh: 要發送的字節
  409.   * @retval 無
  410.   */
  411. void Serial_SendByte(uint8_t ucCh)
  412. {
  413.     while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  414.     USART_SendData(USART1, ucCh);
  415. }

  416. /**
  417.   * @brief  串口發送字符串
  418.   * @param  str: 要發送的字符串指針
  419.   * @retval 無
  420.   */
  421. void Serial_SendString(uint8_t *str)
  422. {
  423.     while (*str != '\0') {
  424.         Serial_SendByte(*str++);
  425.     }
  426. }

  427. /**
  428.   * @brief  串口發送數字(簡化版,實際應用中可優化)
  429.   * @param  num: 要發送的32位整數
  430.   * @retval 無
  431.   */
  432. void Serial_SendNum(int32_t num)
  433. {
  434.     char buf[16];
  435.     char *p = buf;
  436.     uint32_t temp;
  437.     uint8_t i = 0;
  438.    
  439.     if (num < 0) {
  440.         Serial_SendByte('-');
  441.         temp = -num;
  442.     } else {
  443.         temp = num;
  444.     }
  445.    
  446.     /* 簡單的數字轉字符串 */
  447.     do {
  448.         buf[i++] = (temp % 10) + '0';
  449.         temp /= 10;
  450.     } while (temp > 0);
  451.    
  452.     /* 反向輸出 */
  453.     while (i > 0) {
  454.         Serial_SendByte(buf[--i]);
  455.     }
  456. }

  457. /**
  458.   * @brief  主函數
  459.   * @param  無
  460.   * @retval 無
  461.   */
  462. int main(void)
  463. {
  464.     uint8_t clockStatus;
  465.     uint8_t memStatus;
  466.    
  467.     /* 1. 配置系統時鐘并檢測是否成功 */
  468.     clockStatus = SystemClock_Config();
  469.    
  470.     /* 2. 內存RAM讀寫檢查 */
  471.     memStatus = Memory_Check();
  472.    
  473.     /* 3. 初始化各模塊 */
  474.     GPIO_Config();
  475.     Serial_Init(9600);
  476.    
  477.     /* 4. 輸出系統狀態信息 */
  478.     Serial_SendString((uint8_t*)"System Init Start...\r\n");
  479.    
  480.     if (clockStatus == 0) {
  481.         Serial_SendString((uint8_t*)"Clock: HSE+PLL 48MHz OK\r\n");
  482.     } else if (clockStatus == 1) {
  483.         Serial_SendString((uint8_t*)"Clock: HSE fail, use HSI 48MHz\r\n");
  484.     } else {
  485.         Serial_SendString((uint8_t*)"Clock: PLL fail, use HSI 48MHz\r\n");
  486.     }
  487.    
  488.     if (memStatus == 0) {
  489.         Serial_SendString((uint8_t*)"Memory Check: PASS\r\n");
  490.     } else {
  491.         Serial_SendString((uint8_t*)"Memory Check: FAIL\r\n");
  492.         /* 內存錯誤處理接口 - 可在此添加用戶自定義錯誤處理 */
  493.         /* while(1); 內存嚴重錯誤時停機 */
  494.     }
  495.    
  496.     /* 5. 初始化正交解調系數表 */
  497.     DemodTable_Init();
  498.     Serial_SendString((uint8_t*)"Demod Table Init OK\r\n");
  499.    
  500.     /* 6. 配置ADC和DMA */
  501.     ADC_DMA_Config();
  502.     Serial_SendString((uint8_t*)"ADC DMA Init OK\r\n");
  503.    
  504.     /* 7. 配置并使能DMA中斷 */
  505.     NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  506.     NVIC_SetPriority(DMA1_Channel1_IRQn, 1);
  507.    
  508.     Serial_SendString((uint8_t*)"System Init Complete\r\n");
  509.     Serial_SendString((uint8_t*)"Start Demodulation...\r\n");
  510.    
  511.     /* 8. 主循環 */
  512.     while (1) {
  513.         /* 等待DMA傳輸完成中斷標志 */
  514.         if (g_adcCompleteFlag) {
  515.             g_adcCompleteFlag = 0;
  516.             
  517.             /* 進行數字正交解調 */
  518.             Demod_Process();
  519.         }
  520.         
  521.         /* 可添加其他低優先級任務 */
  522.     }
  523. }

  524. /* 錯誤處理函數 - 留出接口供用戶自定義實現 */
  525. void MemoryError_Handler(uint8_t errCount)
  526. {
  527.     /* 用戶可在此實現內存錯誤處理邏輯 */
  528.     /* 例如:記錄錯誤信息、重啟系統等 */
  529. }
復制代碼
然后我讓gemini檢查deepseek寫的是否正確,它回答說基本正確,有兩個小地方需要注意下。然后我又讓gemini給我寫一個,gemini嘩啦啦給縮成只下面這么一點,這個數字正交解調我理論看不懂程序也不明白個所以,我問gemini只這么一點就完成了計算濾波功能?gemini說大道至簡,理論很長計算很短,搞的我都懷疑是不是這倆貨都在懵我?gemini還說在2.6ms就能刷新一次,因為DMA 緩沖區大小是 256 個點,它吐出來數據隨后就能算出來。哪位能解釋下這個確定是完整了解調計算嗎?gemini寫的如下:
  1. /**
  2. * @file    metal_det_dsp.c
  3. * @brief   高壓振蕩數字正交解調 - 定點數優化版
  4. * @note    引腳分配: PA0(ADC), PA9(TX), PB8(Status LED)
  5. */

  6. #include "n32g031.h"
  7. #include <math.h>

  8. /* --- 常量與宏定義 --- */
  9. #define ADC_BUF_SIZE     256       // 必須是2的冪
  10. #define SIN_TAB_SIZE     256       // 正弦表長度
  11. #define DECIMATION_RATIO 64        // CIC抽取倍數

  12. /* --- 全局變量 --- */
  13. __align(4) uint16_t g_adcBuffer[ADC_BUF_SIZE]; // DMA直接映射區
  14. __align(4) uint32_t g_ramTestBuffer[32];       // 專門用于開機RAM自檢的區域

  15. // 定點數查找表 (Q14格式: 1.0 = 16384)
  16. int16_t g_sinTable[SIN_TAB_SIZE];
  17. int16_t g_cosTable[SIN_TAB_SIZE];

  18. // 解調輸出 (阻抗I, 感抗Q)
  19. volatile int32_t g_finalI, g_finalQ;
  20. volatile uint8_t g_dataReady = 0;

  21. /* --- 函數聲明 --- */
  22. void RCC_Config(void);
  23. uint8_t Safe_Memory_Check(void);
  24. void ADC_DMA_Init(void);
  25. void DSP_Table_Init(void);
  26. void Digital_Demod_Process(uint16_t* pRawData, uint16_t len);

  27. /* --- 1. 系統時鐘配置 (帶容錯機制) --- */
  28. void RCC_Config(void) {
  29.     uint32_t timeout = 0;
  30.    
  31.     RCC_DeInit();
  32.     RCC_HSEConfig(RCC_HSE_ON); // 開啟外部8M
  33.    
  34.     while (RCC_WaitHSEStartUp() == ERROR && timeout < 500) timeout++;
  35.    
  36.     if (timeout >= 500) {
  37.         // HSE失敗,切換HSI并倍頻
  38.         RCC_PLLConfig(RCC_PLL_Source_HSI, RCC_PLLMul_6);
  39.     } else {
  40.         // HSE成功,8M * 6 = 48MHz
  41.         RCC_PLLConfig(RCC_PLL_Source_HSE, RCC_PLLMul_6);
  42.     }
  43.    
  44.     RCC_PLLCmd(ENABLE);
  45.     while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
  46.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLL);
  47.     while (RCC_GetSYSCLKSource() != 0x08); // 等待PLL穩定
  48.    
  49.     SystemCoreClockUpdate();
  50. }

  51. /* --- 2. 安全內存檢查 (只檢查特定區域以免破壞堆棧) --- */
  52. uint8_t Safe_Memory_Check(void) {
  53.     uint32_t i;
  54.     // 寫入交替碼測試位線干擾
  55.     for(i=0; i<32; i++) {
  56.         g_ramTestBuffer[i] = (i % 2 == 0) ? 0xAAAAAAAA : 0x55555555;
  57.     }
  58.     for(i=0; i<32; i++) {
  59.         if(g_ramTestBuffer[i] != ((i % 2 == 0) ? 0xAAAAAAAA : 0x55555555)) return 1; // 錯誤
  60.     }
  61.     return 0; // OK
  62. }

  63. /* --- 3. 正交解調核心邏輯 (定點數優化) --- */
  64. // 輸入: ADC原始數據指針,長度
  65. // 功能: 執行 S * sin 和 S * cos,并進行CIC積分
  66. void Digital_Demod_Process(uint16_t* pRawData, uint16_t len) {
  67.     static uint32_t phase_acc = 0;
  68.     static uint32_t phase_step = (uint32_t)(4280.0f / 48000.0f * 65536.0f); // 初始步長
  69.    
  70.     int64_t sumI = 0, sumQ = 0;
  71.    
  72.     for (uint16_t i = 0; i < len; i++) {
  73.         uint16_t idx = (phase_acc >> 8) & 0xFF; // 取高8位作為查表索引
  74.         
  75.         // 核心乘累加 (Q14格式)
  76.         sumI += (int32_t)pRawData[i] * g_cosTable[idx];
  77.         sumQ += (int32_t)pRawData[i] * g_sinTable[idx];
  78.         
  79.         phase_acc += phase_step; // 頻率跟蹤累加
  80.     }
  81.    
  82.     // 抽取與結果輸出 (等效CIC濾波)
  83.     g_finalI = (int32_t)(sumI >> 14);
  84.     g_finalQ = (int32_t)(sumQ >> 14);
  85.     g_dataReady = 1;
  86. }

  87. /* --- 4. ADC + DMA 配置 --- */
  88. void ADC_DMA_Init(void) {
  89.     // 開啟GPIOA, ADC, DMA1時鐘
  90.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_ADC1, ENABLE);
  91.     RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);

  92.     // ADC配置為連續轉換模式
  93.     ADC_InitType ADC_InitStruct;
  94.     ADC_InitStruct.ContinueConvEn = ENABLE;
  95.     ADC_InitStruct.DatAlign = ADC_DAT_ALIGN_R;
  96.     ADC_InitStruct.ChsNumber = 1;
  97.     ADC_Init(ADC1, &ADC_InitStruct);
  98.    
  99.     ADC_ConfigRegularChannel(ADC1, ADC_CH_SELECT_CH0, 1, ADC_SAMPLE_TIME_13CYCLES5);

  100.     // DMA配置: 循環模式
  101.     DMA_InitType DMA_InitStruct;
  102.     DMA_DeInit(DMA1_Channel1);
  103.     DMA_InitStruct.PeriphAddr = (uint32_t)&ADC1->DAT;
  104.     DMA_InitStruct.MemAddr = (uint32_t)g_adcBuffer;
  105.     DMA_InitStruct.Direction = DMA_DIR_PERIPH_SRC;
  106.     DMA_InitStruct.BufSize = ADC_BUF_SIZE;
  107.     DMA_InitStruct.CircularMode = DMA_MODE_CIRCULAR;
  108.     DMA_InitStruct.MemDataSize = DMA_MEM_DATA_SIZE_HALFWORD;
  109.     DMA_InitStruct.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
  110.     DMA_InitStruct.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
  111.     DMA_Init(DMA1_Channel1, &DMA_InitStruct);
  112.    
  113.     DMA_ConfigInterrupt(DMA1_Channel1, DMA_INT_TC | DMA_INT_HT, ENABLE); // 半滿和全滿中斷
  114.     DMA_EnableChannel(DMA1_Channel1, ENABLE);
  115.    
  116.     ADC_ConfigDMA(ADC1, ENABLE);
  117.     ADC_Enable(ADC1, ENABLE);
  118.     while(ADC_GetFlagStatusNew(ADC1, ADC_FLAG_RDY) == RESET);
  119.     ADC_StartSoftwareConv(ADC1);
  120. }

  121. /* --- 5. 查表初始化 --- */
  122. void DSP_Table_Init(void) {
  123.     for(int i=0; i<256; i++) {
  124.         g_sinTable[i] = (int16_t)(sin(2.0 * 3.14159 * i / 256.0) * 16384);
  125.         g_cosTable[i] = (int16_t)(cos(2.0 * 3.14159 * i / 256.0) * 16384);
  126.     }
  127. }

  128. /* --- 6. 中斷服務函數 --- */
  129. void DMA1_Channel1_IRQHandler(void) {
  130.     if (DMA_GetIntStatus(DMA1_Channel1, DMA_INT_HT)) {
  131.         DMA_ClearIntPending(DMA1_Channel1, DMA_INT_HT);
  132.         // 處理前半段數據
  133.         Digital_Demod_Process(&g_adcBuffer[0], ADC_BUF_SIZE/2);
  134.     }
  135.     if (DMA_GetIntStatus(DMA1_Channel1, DMA_INT_TC)) {
  136.         DMA_ClearIntPending(DMA1_Channel1, DMA_INT_TC);
  137.         // 處理后半段數據
  138.         Digital_Demod_Process(&g_adcBuffer[ADC_BUF_SIZE/2], ADC_BUF_SIZE/2);
  139.     }
  140. }

  141. int main(void) {
  142.     RCC_Config();
  143.    
  144.     if (Safe_Memory_Check() != 0) {
  145.         // RAM錯誤處理接口
  146.         while(1);
  147.     }
  148.    
  149.     DSP_Table_Init();
  150.     ADC_DMA_Init();
  151.    
  152.     NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  153.    
  154.     while(1) {
  155.         if (g_dataReady) {
  156.             g_dataReady = 0;
  157.             // 此處 g_finalI 和 g_finalQ 就是解調出的阻抗和感抗
  158.             // 主循環可以根據這兩個值的變化率來觸發傳送帶報警
  159.         }
  160.     }
  161. }
復制代碼



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:584814 發表于 2026-3-13 08:28 | 只看該作者
不能真機測試么 ?
回復

使用道具 舉報

板凳
ID:1066092 發表于 2026-3-13 20:45 | 只看該作者
man1234567 發表于 2026-3-13 08:28
不能真機測試么 ?

我要是知道就不會在這里問了。我以前問過AI很多電子的問題,因為我不懂想讓它們給我講講基礎,試驗的結果都不理想。我就問它們一個哈特萊的接線方式,不管是國內的千問還是deepseek或者kimi,外面的chatgpt還是gemini,它們都不能完成文字接線,無論怎么提醒它們錯誤在哪里都不能正確地描述接線,一直在循環錯誤。我將一個差分LC振蕩電路發給它們,千問一本正經地胡說八道告訴它錯誤后就說自己無法識別圖中的電路拓補結構,deepseek直接說自己不能識別圖中的內容,外面的都能正確識別電路結構并能識別元件作用,但是不會計算工作點和電路分析。如果沒有什么要求AI確實很強,因為你不知道它說的是真還是假,但是一旦有確定的要求后你要是知道點就能看出它們在特定的點上在胡說。這個正交解調我不知道,也不知道它們是不是在胡說而且上面給的也不是完整的當然無法真機測試,就算真機測試我也不知道錯在哪里的。
回復

使用道具 舉報

地板
ID:106977 發表于 2026-3-14 12:28 | 只看該作者
對于行家,利用AI可以開闊思路,提供參考。如果自己沒有鑒別能力,只能實驗驗證!如果實驗無法成功,又找不到問題所在,那就別費勁了!
回復

使用道具 舉報

5#
ID:1066092 發表于 2026-3-15 15:59 | 只看該作者
lgwd 發表于 2026-3-14 12:28
對于行家,利用AI可以開闊思路,提供參考。如果自己沒有鑒別能力,只能實驗驗證!如果實驗無法成功,又找不 ...

因為我只有一路信號需要單片機自己產生同頻參考信號,又只有最多4個周期給單片機進行鎖相生成同頻參考信號做90度延時。AI給的幾種鎖相方式都無法在3個周期內鎖相成功,然后又給了個3個周期參與計算的方法不需要考慮零點也不需要考慮初始頻率這些。AI有個毛病就是好信口開河在遇到難于解決的問題后就開始回答另一種方式才是最正確的解決方法,我沒理論不懂這個提問技巧,想問問行家里手有沒有什么好的提問方式,免得到最后又是推倒重來浪費時間。沒有個相差90度的同頻參考信號后面就沒法做正交解調也解不出來個正確結果的。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表