硬汉嵌入式论坛

 找回密码
 立即注册
查看: 293|回复: 8
收起左侧

[有问必答] STM32F407ADC采样波形

[复制链接]

1

主题

5

回帖

8

积分

新手上路

积分
8
发表于 2025-5-25 22:57:29 | 显示全部楼层 |阅读模式
大佬们为什么ADC采样波形会不连续啊,我降低采样率波形就不好看,我要采载波50k基波1k的AM波,IQ解调,我发现只要采集的波形断开一下,那解调出来的波形就会大幅变化一次
ADC代码如下#include "adc.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_dma.h"
#include "misc.h"

#define ADC_DMA_BUFFER_SIZE  500   // ?????????4096

// ?????:???????????
__align(32) volatile uint16_t adc_dma_buffer0[ADC_DMA_BUFFER_SIZE]; // 32??????Cache
__align(32) volatile uint16_t adc_dma_buffer1[ADC_DMA_BUFFER_SIZE];
volatile uint8_t adc_dma_ready = 0;                     // ??????
uint8_t current_buffer = 0;                    // ?????????(0?1)


void ADC_DMA_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 1. ????
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    // 2. ??GPIO(????)
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 3. ??DMA(?????)
    DMA_DeInit(DMA2_Stream0);
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);  // ADC???????
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)adc_dma_buffer0; // ??????
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;            // ?????
    DMA_InitStructure.DMA_BufferSize = ADC_DMA_BUFFER_SIZE;            // ?????
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   // ???????
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;             // ??????
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;         // ????
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // ??(16?)
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         // ??(16?)
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                        // ????(???)
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                 // ????
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  // ????
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;               // ??FIFO
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;    // FIFO??(??,?FIFO??)
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);

    // ???????(????)
    DMA_DoubleBufferModeConfig(DMA2_Stream0, (uint32_t)adc_dma_buffer1,DMA_Memory_0);              // ?????Memory0
    DMA_DoubleBufferModeCmd(DMA2_Stream0, ENABLE);       // ???????
                DMA_Cmd(DMA2_Stream0, ENABLE);
    // ??DMA??(??????)
           // ????????

    // ??NVIC?????
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
                DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

    // 4. ??ADC????
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;          // ????
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; // ????
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;      // ??DMA????
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;       // ADC????(21MHz)
    ADC_CommonInit(&ADC_CommonInitStructure);

    // 5. ??ADC??
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;            // 12????
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;                     // ??????(???)
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                // ??????(????)
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; // ?????
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;       // ???3??
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;             // ???
    ADC_InitStructure.ADC_NbrOfConversion = 1;                        // ????(???????)
    ADC_Init(ADC1, &ADC_InitStructure);

    // 6. ??ADC????
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);

    // 7. ??ADC?DMA
    ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);  // ?????????DMA
    ADC_DMACmd(ADC1, ENABLE);                         // ??ADC DMA??
    ADC_Cmd(ADC1, ENABLE);                             // ??ADC
                        // ??DMA
}

void TIM_ADC_Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // ?????3??

    TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_InitStructure.TIM_Prescaler = 42 - 1;              // ???(84MHz / 7 = 12MHz)
    TIM_InitStructure.TIM_Period = 4- 1;                // ??(12MHz / 10 = 1.2MHz,???)
    TIM_InitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_InitStructure);

    // ?????????(TRGO)
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);  // ??????????
    TIM_Cmd(TIM2, ENABLE);                                 // ?????3

    // ???????(???,????)
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// DMA2 Stream0 ??????(??????)
void DMA2_Stream0_IRQHandler(void)
{
    if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
    {
        DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
        current_buffer = (DMA_GetCurrentMemoryTarget(DMA2_Stream0) == 0) ? 1 : 0; // ???????
        adc_dma_ready = 1; // ??????
    }
}
主函数如下

int main(void)
{
        float32_t DAC_OUT[BUFFER_SIZE];
       
        uint16_t i = 0;
        static float32_t adc[500];
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é2
        delay_init(168);    //³õʼ»¯ÑÓʱº¯Êý
        delay_ms(500);
        uart_init(115200);        //³õʼ»¯´®¿Ú²¨ÌØÂÊΪ115200
////         LCD_Init();
        NCO_Init(50000,500000);        //³õʼ»¯LCD½Ó¿Ú
        ADC_DMA_Init();//³õʼ»¯ADC
        TIM_ADC_Init();
        FIR_Init();
//        ADit();
//        FI9959_Init();
//        KEY_Init();
        DA1_Init();   
//  TIM_Cmd(TIM3 , DISABLE);
//        DMA_Cmd(DMA2_Stream0, DISABLE);   
        OLED_Init();
        OLED_ShowString(1,1,"HAFS",OLED_6X8);
        OLED_Update();
       
//        AD9959_Set_Fre(CH1, freq_ch1);        //ÉèÖÃͨµÀ0ƵÂÊ100000Hz
//        AD9959_Set_Fre(CH0, freq_ch0);
//        AD9959_Set_Amp(CH0, 1023);
//        AD9959_Set_Amp(CH1, 1023);
//        AD9959_Set_Phase(CH0, 0);
//        AD9959_Set_Phase(CH1, 0);

//        IO_Update();
//        Counter_TIM1_Init();
//        Timer_TIM4_Init();


        while(1)
        {       
                if(adc_dma_ready)
                {       
                        if(current_buffer == 1)
                        {
                                for(i = 0; i < 500; i++)
                                {
                                        adc[i] =((float32_t)adc_dma_buffer0[i]);
                                }
                        }
                        else
                        {
                                for(i = 0; i < 500; i++)
                                {
                                        adc[i] =((float32_t)adc_dma_buffer1[i]);
                                }
                        }       
                        adc_dma_ready = 0;
                        AM_Demod_Process(adc, DAC_OUT, BUFFER_SIZE);
                }
                for(i = 0; i<BUFFER_SIZE;i++)
                {                       
                        DAC_actual[i]= (uint16_t)DAC_OUT[i];
                }
        }
//                //AD9959_Freq();
}

上面是采样波形,下面是解调后的波形

上面是采样波形,下面是解调后的波形

main.c

2.31 KB, 下载次数: 0

adc.c

5.81 KB, 下载次数: 0

adc.h

462 Bytes, 下载次数: 0

IQ.c

2.32 KB, 下载次数: 0

IQ.h

376 Bytes, 下载次数: 0

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116197
QQ
发表于 2025-5-26 08:37:21 | 显示全部楼层
当前是500k采样率,双缓冲模式,每每轮dms是500点。

这样的话,每次处理就是有1ms.的间隙,这个有必要看下你每次的处理可以在1ms内处理完毕不
回复

使用道具 举报

1

主题

5

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 2025-5-27 21:17:49 | 显示全部楼层
eric2013 发表于 2025-5-26 08:37
当前是500k采样率,双缓冲模式,每每轮dms是500点。

这样的话,每次处理就是有1ms.的间隙,这个有必要看 ...

谢谢佬,我降低过采样率,然后把对这个数组的操作改得时间短了点,但是感觉很难连贯,最后用硬件滤波稍微平滑了,我想知道这个的原因有哪些呢,方便后面处理的时候注意点
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116197
QQ
发表于 2025-5-28 11:05:19 | 显示全部楼层
梧桐风 发表于 2025-5-27 21:17
谢谢佬,我降低过采样率,然后把对这个数组的操作改得时间短了点,但是感觉很难连贯,最后用硬件滤波稍微 ...

确定一个问题,看看不连贯的地方是不是固定在缓冲交接的地方。
回复

使用道具 举报

1

主题

5

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 2025-5-29 07:46:05 | 显示全部楼层
#include "stm32f4xx.h"                  // Device header
#include "IQ.h"
#include "fir.h"
#include "FM_FIR.h"
#include "usart.h"

//#define NCO_TABLE_SIZE 256
#define BUFFER_SIZE 500
#define PI 3.14159265358979323846f
#define NCO_TABLE_SIZE 256
#define PHASE_UNWRAP_THRESHOLD  3.1415926f  // ??????(p)
#define SAMPLE_RATE           500000.0f  // ???500kHz
#define MAX_DEVIATION_HZ    50000.0f     // ????50kHz
#define DEEMPH_TIME_CONST   75e-6f       // ???????75&#181;s
#define OUTPUT_GAIN         (SAMPLE_RATE / (2 * PI * MAX_DEVIATION_HZ))
//#define BUFFER_SIZE 256
typedef struct {
    float32_t cos_table[NCO_TABLE_SIZE];  // ?????
    float32_t sin_table[NCO_TABLE_SIZE];  // ?????
    uint32_t phase_accum;    // ?????(32?)
    uint32_t phase_inc;       // ????
} NCO_State;

static NCO_State nco;
void NCO_Init(uint32_t freq_hz, uint32_t fs_hz)
{
        double  phase_inc = (double)freq_hz * (1ULL << 32) / fs_hz;
    nco.phase_inc = (uint32_t)(phase_inc + 0.5);

    // ???sin/cos?(?????)
    for (int i = 0; i < NCO_TABLE_SIZE; i++) {
        float32_t theta = 2 * PI * i / NCO_TABLE_SIZE;
        nco.cos_table[i] = arm_cos_f32(theta);
        nco.sin_table[i] = arm_sin_f32(theta);
    }
    nco.phase_accum = 0;
}

void NCO_Generate(float32_t* I_out, float32_t* Q_out, uint32_t len)
{
  for (uint32_t i = 0; i < len; i++)
    {

        uint8_t index = (nco.phase_accum >> 24) & 0xFF;

        I_out[i] = nco.cos_table[index];  // I?(??)
        Q_out[i] = nco.sin_table[index];  // Q?(??)

        nco.phase_accum += nco.phase_inc;
    }
}

void AM_Demod_Process(float32_t* input, float32_t* output, uint32_t len)
{
                uint16_t i =0;
       
  static float32_t I_buf[BUFFER_SIZE], Q_buf[BUFFER_SIZE];
  float32_t mag_sq[BUFFER_SIZE];
        static  float32_t IMAX_buf[BUFFER_SIZE]={0}, QMAX_buf[BUFFER_SIZE]={0};
        float32_t Ifir_buf[BUFFER_SIZE]={0}, Qfir_buf[BUFFER_SIZE]={0};
       
    NCO_Generate(I_buf, Q_buf, len);


        arm_mult_f32(input, Q_buf, QMAX_buf, len);
    arm_mult_f32(input, I_buf, IMAX_buf, len);


    // FIR??(??IIR??)
    arm_fir_f32_lp_I(IMAX_buf, Ifir_buf);
    arm_fir_f32_lp_Q(QMAX_buf, Qfir_buf);


    float32_t sum_sq[BUFFER_SIZE];
    arm_mult_f32(Ifir_buf, Ifir_buf, sum_sq, len);
    arm_mult_f32(Qfir_buf, Qfir_buf, output, len);
    arm_add_f32(sum_sq, output, sum_sq, len);
    for (uint32_t i = 0; i < len; i++)
                {
        arm_sqrt_f32(sum_sq[i], &output[i]);      // output = sqrt(I^2 + Q^2)
    }
//                for(i = 0;i<500;i++ )
//                {
//                        printf("%f,%f,%f\n", sum_sq[i], output[i],input[i]);
//                }
}               


void FM_Demod_Process(float32_t* input, float32_t* output, uint32_t len)
{
        uint16_t i = 0;
        static float32_t FM_I_buf[BUFFER_SIZE], FM_Q_buf[BUFFER_SIZE];
        static float32_t FM_IMAX_buf[BUFFER_SIZE] = {0}, FM_QMAX_buf[BUFFER_SIZE] = {0};
        float32_t FM_Ifir_buf[BUFFER_SIZE] = {0}, FM_Qfir_buf[BUFFER_SIZE] = {0};
        static float32_t prev_phase = 0.0f;  // ??????
        static float32_t prev_unwrapped = 0.0f;  // ??????????
        float32_t current_phase, phase_diff, unwrapped_phase;
        static int32_t phase_jumps = 0; // ??????
        static float32_t prev_deemph = 0.0f;
  NCO_Generate(FM_I_buf, FM_Q_buf, len);


        arm_mult_f32(input, FM_Q_buf, FM_QMAX_buf, len);
  arm_mult_f32(input, FM_I_buf, FM_IMAX_buf, len);
//                for(i = 0;i<500;i++ )
//                {
//                        printf("%f,%f,%f\n",FM_I_buf[i],FM_Q_buf[i],FM_QMAX_buf[i]/800);
//                }

    // FIR??(??IIR??)
  FM_arm_fir_f32_lp_I(FM_IMAX_buf, FM_Ifir_buf);
  FM_arm_fir_f32_lp_Q(FM_QMAX_buf, FM_Qfir_buf);

        const float32_t DEEMPH_ALPHA = 0.9746f;
        for (i = 0; i < len; i++)
        {
                current_phase = cordic_atan2(FM_Qfir_buf[i], FM_Ifir_buf[i]); //·&#180;&#213;&#253;&#199;&#208;
                phase_diff = current_phase - prev_phase;

                if (phase_diff > PI) {
                        phase_jumps--;
                                                phase_diff -= 2 * PI;
        } else if (phase_diff < -PI) {
                                        phase_jumps++;
                                        phase_diff += 2 * PI;
        }
                                unwrapped_phase = current_phase + 2*PI*phase_jumps;
                                output[i] = (unwrapped_phase - prev_unwrapped) * OUTPUT_GAIN;
        output[i] = (1 - DEEMPH_ALPHA) * output[i] + DEEMPH_ALPHA * prev_deemph;
                                prev_deemph = output[i];
        
        prev_phase = current_phase;
        prev_unwrapped = unwrapped_phase;
  }
                for(i = 0;i<500;i++ )
                {
                        printf("%f,%f,%f\n",output[i],input[i]/800,FM_QMAX_buf[i]/800);
                }
       
}

float32_t cordic_atan2(float32_t y, float32_t x) {
    float32_t angle = 0.0f;
    int8_t sign = 1;
   
    // ??x=0?????
    if (x == 0.0f) return (y >= 0) ? PI/2 : -PI/2;
   
    // ??????????
    if (x < 0) { x = -x; y = -y; angle = PI; }
    if (y < 0) { y = -y; sign = -1; }
   
    // ???????(????9/10)
    static const float32_t angles[20] = {
    0.7853981634f,   // arctan(1)        (i=0)
    0.4636476090f,   // arctan(1/2^1)   (i=1)
    0.2449786631f,   // arctan(1/2^2)   (i=2)
    0.1243549945f,   // arctan(1/2^3)   (i=3)
    0.0624188097f,   // arctan(1/2^4)   (i=4)
    0.0312398334f,   // arctan(1/2^5)   (i=5)
    0.0156237286f,   // arctan(1/2^6)   (i=6)
    0.0078123411f,   // arctan(1/2^7)   (i=7)
    0.0039062301f,   // arctan(1/2^8)   (i=8)
    0.0019531225f,   // arctan(1/2^9)   (i=9)
    0.0009765622f,   // arctan(1/2^10)  (i=10)
    0.0004882812f,   // arctan(1/2^11)  (i=11)
    0.0002441406f,   // arctan(1/2^12)  (i=12)
    0.0001220703f,   // arctan(1/2^13)  (i=13)
    0.0000610352f,   // arctan(1/2^14)  (i=14)
    0.0000305176f,   // arctan(1/2^15)  (i=15)
    0.0000152588f,   // arctan(1/2^16)  (i=16)
    0.0000076294f,   // arctan(1/2^17)  (i=17)
    0.0000038147f,   // arctan(1/2^18)  (i=18)
    0.0000019073f    // arctan(1/2^19)  (i=19)
    };
    for(int i=0; i<20; i++) {
        float32_t factor = 1.0f/(1 << i);
        if(y > 0) {
            x += y * factor;
            y -= x * factor;
            angle += angles[i];
        } else {
            x -= y * factor;
            y += x * factor;
            angle -= angles[i];
        }
    }
    return sign * angle * 0.607252935f;
}我现在解调FM,一样的参数解不出来了,我发现我这个dsp库里
没有反正切
回复

使用道具 举报

1

主题

5

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 2025-5-29 07:48:08 | 显示全部楼层
本帖最后由 梧桐风 于 2025-5-29 17:02 编辑

111111111111111
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116197
QQ
发表于 2025-5-29 09:22:06 | 显示全部楼层
梧桐风 发表于 2025-5-29 07:48
#include "stm32f4xx.h"                  // Device header
#include "IQ.h"
#include "fir.h"

这部分没太看懂楼主的意思,部分注释成乱码了。
回复

使用道具 举报

1

主题

5

回帖

8

积分

新手上路

积分
8
 楼主| 发表于 2025-6-1 20:38:56 | 显示全部楼层
eric2013 发表于 2025-5-29 09:22
这部分没太看懂楼主的意思,部分注释成乱码了。

void FM_Demod_Process(float32_t* input, float32_t* output, uint32_t len)
{
    float32_t FM_IMAX_buf[BUFFER_SIZE];  // I路滤波前信号
    float32_t FM_QMAX_buf[BUFFER_SIZE];  // Q路滤波前信号
    float32_t FM_Ifir_buf[BUFFER_SIZE];         // I路滤波后信号
    float32_t FM_Qfir_buf[BUFFER_SIZE];
屏幕截图 2025-06-01 192746.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116197
QQ
发表于 7 天前 | 显示全部楼层
梧桐风 发表于 2025-6-1 20:38
void FM_Demod_Process(float32_t* input, float32_t* output, uint32_t len)
{
    float32_t FM_IMA ...

你前面说的那个反正切的函数,只能调用c库的,dsp库里面没有对应的api

然后截图解析出来的效果确实不好
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-6-10 05:24 , Processed in 0.333280 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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