【雅特力AT-START-F435】基于DSP库实现DAC波形->FFT->RFFT回显
前言
本项目为课程设计:DAC+ADC+FFT。DAC使用示波器管观察波形,并连接到本机ADC使用fft还原信号,串口打印信息到电脑上。
- DAC和ADC采样都使用定时器触发的方式
- DAC只要开始后就不会停止,作为信号源从PA4输出
- ADC采样使能 DMA_CH1 通道,当DMA搬移了足够多 (这里设置为了1024) 个采样点之后,停止ADC触发定时器计时,ADC采样结束。
- 采样完成后,使用 FFT 进行快速傅里叶正变换,得到幅频响应,串口输出幅频响应。
- 通过 RFFT 快速傅里叶逆变换,将幅频曲线逆变换为信号,通过串口调试助手显示还原后的波形。
一、DAC波形
void DAC_Config(void)
{
gpio_init_type gpio_init_struct = {0};
dma_init_type dma_init_struct;
crm_clocks_freq_type crm_clocks_freq_struct = {0};
crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_DAC_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
//获取DAC电压波形
GetWave(0);
/* once the dac is enabled, the corresponding gpio pin is automatically
connected to the dac converter. in order to avoid parasitic consumption,
the gpio pin should be configured in analog */
gpio_init_struct.gpio_pins = GPIO_PINS_4;
gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
/* get system clock */
crm_clocks_freq_get(&crm_clocks_freq_struct);
/* (systemclock/(systemclock/1000000))/1000 = 1KHz */
tmr_base_init(TMR2, DACDUTY-1, (crm_clocks_freq_struct.sclk_freq/1000000 - 1));
tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);
/* primary tmr2 output selection */
tmr_primary_mode_select(TMR2, TMR_PRIMARY_SEL_OVERFLOW);
/* dac1 configuration */
dac_trigger_select(DAC1_SELECT, DAC_TMR2_TRGOUT_EVENT);
dac_trigger_enable(DAC1_SELECT, TRUE);
dac_wave_generate(DAC1_SELECT, DAC_WAVE_GENERATE_NONE);
dac_output_buffer_enable(DAC1_SELECT, TRUE);
dac_dma_enable(DAC1_SELECT, TRUE);
/* dma1 channel2 configuration */
dma_reset(DMA1_CHANNEL2);
dma_init_struct.buffer_size = TEST_LENGTH_SAMPLES;
dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
dma_init_struct.memory_base_addr = (uint32_t)dactestInput_q15;
dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
dma_init_struct.memory_inc_enable = TRUE;
dma_init_struct.peripheral_base_addr = (uint32_t)(DAC_BASE+0x008);//0x40007410
dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
dma_init_struct.peripheral_inc_enable = FALSE;
dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
dma_init_struct.loop_mode_enable = TRUE;
dma_init(DMA1_CHANNEL2, &dma_init_struct);
/* enable dmamux function */
dmamux_enable(DMA1, TRUE);
dmamux_init(DMA1MUX_CHANNEL2, DMAMUX_DMAREQ_ID_DAC1);
dma_channel_enable(DMA1_CHANNEL2, TRUE);
/* enable dac1: once the dac1 is enabled, pa.04 is
automatically connected to the dac converter. */
dac_enable(DAC1_SELECT, TRUE);
/* enable tmr2 */
tmr_counter_enable(TMR2, TRUE);
}
- 初始化GPIO PA4 为DAC的输出口
- 使能定时器 TMR2 。设置分频后的频率为1Mhz,然后根据period选择触发Duty 。例如,设置触发Duty为10,那么就是10us触发一次,100kHz触发频率
- 产生波形函数,产生固定频率的周期波,这里设置为
/* 波形是由直流分量、50Hz 正弦波、25Hz余弦波组成,波形采样率 1024 ,初始相位 0 */
testInput_f32[i] = 1 +
0.5*arm_sin_f32( 2*3.1415926f*50*i/TEST_LENGTH_SAMPLES ) +
1.0*arm_cos_f32( 2*3.1415926f*25*i/1024 );
- 波形产出的是 float32_t 的类型,要进行波形放大,并且转化为 12bit 位的数据格式
/* 波形极值,确定放大倍数 */
arm_min_f32(testInput_f32, TEST_LENGTH_SAMPLES, &minData, NULL);
arm_max_f32(testInput_f32, TEST_LENGTH_SAMPLES, &maxData, NULL);
mulScale = (0x0FFF)*1.0 / (maxData-minData);
/* 上移波形,放大 */
for(i=0; i<TEST_LENGTH_SAMPLES; ++i) {
dactestInput_q15[i] = ( testInput_f32[i]-minData ) * mulScale;
}
- 使能DMA,开启DAC输出。
二、ADC采样
adc采样可以参考一下这两边文章:
【新提醒】【雅特力AT-START-F435】ADC软触发always、DACTmr2触发、DMA,驱动LED被钳位1.54V问题 - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)
【新提醒】【雅特力AT-START-F435】ADC采样速率测试5.33MSPS - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)
需要修改的有:
- 使用 TMR1 触发ADC开始采集,值得注意的是,普通通道只能使用上升沿触发
- 根据采样定理,采样频率最好大于2倍信号最高频率,即ADCDuty应该最好小于DACDuty
三、FFT转换和RFFT转换
因为采用了按键触发采样的方式,即按下按键的上升沿,开始采样1024个采样点。
所以,
- 在按键中断服务函数中,开启ADC触发定时器;
tmr_counter_enable(TMR1, TRUE);
- 在ADC的DMA通道全部搬移完成中断中,关闭ADC触发定时器
tmr_counter_enable(TMR1, FALSE);
- 转换的FFT幅频曲线存放到 testOutputMag_f32 数组中
- 逆变换的函数图像存放到 testRfft_f32 数组中
四、转换结果查看
使用下面的信号进行DAC输出采样,
/* 波形是由直流分量、50Hz 正弦波、25Hz余弦波组成,波形采样率 1024 ,初始相位 0 */
testInput_f32[i] = 1 +
0.5*arm_sin_f32( 2*3.1415926f*50*i/TEST_LENGTH_SAMPLES ) +
1.0*arm_cos_f32( 2*3.1415926f*25*i/1024 );
FFT变换的幅频响应如下:
(图 串口打印的幅频响应频率和幅值百分比)
(图 幅频响应曲线)
(图 原信号.下 和 RFFT还原的信号.上)