以nRF52832 为例子,接收天线IQ信号采样,计算相位差ψ

  • Post author:
  • Post category:其他


以下是使用Nordic芯片对接收到的IQ信号进行相位差计算的参考代码。这里我们使用nRF52832 SoC为例,使用nRF SDK提供的API函数进行数据采集和处理。

首先,需要在初始化代码中对GPIO和ADC模块进行初始化。在本例中,我们使用P0.05和P0.04分别连接I和Q分量的信号,ADC模块的采样率为500kHz,采样精度为12位。

#include "nrf_gpio.h"
#include "nrf_adc.h"
#include "nrf_delay.h"

#define I_PIN 5 // GPIO pin for I component
#define Q_PIN 4 // GPIO pin for Q component
#define SAMPLES 1024 // number of samples to collect
#define PI 3.14159265358979323846

static nrf_adc_value_t m_buffer[SAMPLES*2];

void adc_configure()
{
    nrf_adc_config_t adc_config = NRF_ADC_CONFIG_DEFAULT;
    adc_config.resolution = NRF_ADC_CONFIG_RES_12BIT;
    nrf_adc_configure(&adc_config);
}

void gpio_configure()
{
    nrf_gpio_cfg_input(I_PIN, NRF_GPIO_PIN_PULLDOWN);
    nrf_gpio_cfg_input(Q_PIN, NRF_GPIO_PIN_PULLDOWN);
}

void adc_sampling()
{
    nrf_adc_int_enable(NRF_ADC_INT_END);
    nrf_adc_int_enable(NRF_ADC_INT_STARTED);
    nrf_adc_int_enable(NRF_ADC_INT_END);
    nrf_adc_start();

    uint32_t event;
    do {
        __WFE();
        event = __SEV();
        __WFE();
    } while (event != NRF_ADC_EVENT_END);

    nrf_adc_buffer_convert(m_buffer, SAMPLES*2);
}

接下来,需要将采样到的数据进行FFT变换以获取频域信息。这里我们使用Nordic SDK提供的nrf_fft库进行FFT变换,同时使用arm_cmplx_mag函数计算信号的模值。

#include "nrf_fft.h"
#include "arm_math.h"

#define FFT_SIZE 1024 // FFT size

void fft_sampling()
{
    static nrf_fft_instance_t fft_inst;
    static float32_t fft_input[FFT_SIZE*2];
    static float32_t fft_output[FFT_SIZE];

    nrf_fft_init(&fft_inst, NRF_FFT_INSTANCE_ID_SD);
    nrf_fft_window(&fft_inst, fft_input, NRF_FFT_WINDOW_HANNING);
    nrf_fft_transform(&fft_inst, fft_input, fft_output);
    arm_cmplx_mag_f32(fft_input, fft_output, FFT_SIZE);

    for (int i = 0; i < FFT_SIZE; i++) {
        float mag = fft_output[i];
        // process magnitude data
    }
}

最后,根据接收到的I和Q分量的信号进行相位差计算。这里我们假设接收到的IQ信号为x[n] = I[n] + jQ[n],相邻两个采样点的时间间隔为T。则相位差可以表示为:

ψ = arg(x[n] * x[n-1]^*)

其中,^*表示复共轭。根据欧拉公式,可以将x[n]表示为:

x[n] = I[n]cos(wnT) - Q[n]sin(wnT) + j*(I[n]sin(wn*T)

其中,w为角频率,w = 2pif,f为信号的频率。则x[n-1]^*可以表示为:

x[n-1]^* = I[n-1]cos(w(n-1)*T) + Q[n-1]sin(w(n-1)T) - j(I[n-1]sin(w(n-1)*T) - Q[n-1]cos(w(n-1)*T))

将其代入相位差公式中,可以得到:

ψ = arg((I[n]cos(wnT) - Q[n]sin(wnT) + j*(I[n]sin(wnT) + Q[n]cos(wnT))) * (I[n-1]cos(w(n-1)*T) + Q[n-1]sin(w(n-1)T) + j(I[n-1]sin(w(n-1)*T) - Q[n-1]cos(w(n-1)*T))))

通过展开和化简,可以得到:

ψ = atan2(I[n]*Q[n-1] - Q[n]*I[n-1], I[n]*I[n-1] + Q[n]*Q[n-1])

在代码中,可以使用arm_cmplx_mult_real函数计算两个复数的乘积,并使用arm_atan2函数计算相位角度。最后,将角度转换为弧度即可得到相位差。

void calculate_phase_diff()
{
    float32_t I[SAMPLES], Q[SAMPLES];
    for (int i = 0; i < SAMPLES; i++) {
        I[i] = (float)m_buffer[i*2]/2048.0f;
        Q[i] = (float)m_buffer[i*2+1]/2048.0f;
    }

    float32_t phase_diff = 0.0f;
    for (int i = 1; i < SAMPLES; i++) {
        float32_t i1 = I[i], q1 = Q[i];
        float32_t i2 = I[i-1], q2 = Q[i-1];

        float32_t prod_real = i1*i2 + q1*q2;
        float32_t prod_imag = i1*q2 - i2*q1;
        float32_t phase = arm_atan2(prod_imag, prod_real);
        phase_diff += phase;
    }

    phase_diff /= (float)(SAMPLES-1);
    phase_diff = phase_diff / PI * 180.0f;
    // phase_diff is the phase difference in degrees
}



版权声明:本文为m0_54706625原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。