打印
[活动专区]

【AT-START-F435测评】AD高速采样实现实时FT计算

[复制链接]
1006|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hanter|  楼主 | 2023-1-4 16:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
很早就关注AT系列的单片机,对它的高主频和大容量RAM非常感兴趣。最近有幸收到F435的开发板,立即利用手上的资源搭建了一个简单的测试平台,来测试一下它的性能。




我的项目要求实现每周波512点的采样频率,并且每个采样一次需要实现一次FT计算,因此对于RAM和计算能力要求高一些。在此测试中,暂时按照64点采样频率调试完成,以下是AD初始化部分代码,使用DMA直接读取。
void AT32_ADC_GPIOCFG(void)
{
        gpio_init_type gpio_init_struct;

        /* enable GPIO clock */
        crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
        crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
        crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);

        /* set default parameter */
        gpio_default_para_init(&gpio_init_struct);

        /* Configure GPIO as analog inputs */
        gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
        gpio_init_struct.gpio_pins = GPIO_PINS_5 | GPIO_PINS_6 | GPIO_PINS_7;
        gpio_init(GPIOA, &gpio_init_struct);
        gpio_init_struct.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1;
        gpio_init(GPIOB, &gpio_init_struct);
        gpio_init_struct.gpio_pins = GPIO_PINS_4| GPIO_PINS_5;
        gpio_init(GPIOC, &gpio_init_struct);
}

// ============================================================================
// adc模块相关的DMA部分的配置       
// ============================================================================
void AT32_ADC_DMACFG(void)
{
        dma_init_type dma_init_struct;

        /* Enable DMA1 and DMA2 clocks */
        crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

        /* Enable the dma  Interrupt */
        nvic_irq_enable(DMA1_Channel1_IRQn, USERPRI_DMA2_PRE, USERPRI_DMA2_SUB);

        /* DMA init config with its default value        */
        dma_reset(DMA1_CHANNEL1);
        dma_default_para_init(&dma_init_struct);

        /* DMA1 channel1 configuration */
        dma_init_struct.buffer_size = 7;
        dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
        dma_init_struct.memory_base_addr = (uint32_t)g_sSamplbuf;
        dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_WORD;//要读取ADC1、2,因此用word
        dma_init_struct.memory_inc_enable = TRUE;
        dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
        dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_WORD;
        dma_init_struct.peripheral_inc_enable = FALSE;
        dma_init_struct.priority = DMA_PRIORITY_HIGH;
        dma_init_struct.loop_mode_enable = TRUE;
        dma_init(DMA1_CHANNEL1, &dma_init_struct);

        /* Trigger interrupt enable */
        dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);

        /* Enable DMA channel */
        dma_channel_enable(DMA1_CHANNEL1, TRUE);
}

// ============================================================================
// adc模块相关的ADC本身部分的配置       
// ============================================================================
void AT32_ADC_ADCCFG(void)
{
#define ADC_SAMPLETIME ADC_SAMPLETIME_13_5
        adc_base_config_type adc_base_struct;
        /* ADC clock enable */
        crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
        crm_periph_clock_enable(CRM_ADC2_PERIPH_CLOCK, TRUE);
        crm_adc_clock_div_set(CRM_ADC_DIV_12);//ADC时钟最大频率为20M   APB2=120MHz

        /* ADC1 configuration  */
        adc_combine_mode_select(ADC_ORDINARY_SMLT_ONLY_MODE);
        adc_base_default_para_init(&adc_base_struct);
        adc_base_struct.sequence_mode = TRUE;  //转换设定的多个通道
        adc_base_struct.repeat_mode = FALSE;
        adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
        adc_base_struct.ordinary_channel_length = 7;

        adc_base_config(ADC1, &adc_base_struct);

        /* ADC1 regular channel configuration */        //实际转换时间:(ADC_SAMPLETIME+12.5)* ADCCLK
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_5, 1, ADC_SAMPLETIME);//Ia
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_6, 2, ADC_SAMPLETIME);//Ib
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_7, 3, ADC_SAMPLETIME);//Ic
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_15, 4, ADC_SAMPLETIME);//I0
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_5, 5, ADC_SAMPLETIME);//Ia
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_6, 6, ADC_SAMPLETIME);//Ib
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_7, 7, ADC_SAMPLETIME);//Ic

        /* Enable ADC1 external trigger */
        adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_TMR2CH2, TRUE);
        adc_ordinary_conversion_trigger_set(ADC2, ADC12_ORDINARY_TRIG_TMR2CH2, TRUE);

        /* Enable ADC1 DMA */
        adc_dma_mode_enable(ADC1, TRUE);

        /* ADC2 configuration  */
        adc_base_config(ADC2, &adc_base_struct);

        /* ADC2 regular channel configuration */
        adc_ordinary_channel_set(ADC2, ADC_CHANNEL_15, 1, ADC_SAMPLETIME);//I0
        adc_ordinary_channel_set(ADC2, ADC_CHANNEL_14, 2, ADC_SAMPLETIME);//Ua
        adc_ordinary_channel_set(ADC2, ADC_CHANNEL_8, 3, ADC_SAMPLETIME);//Ub
        adc_ordinary_channel_set(ADC2, ADC_CHANNEL_9, 4, ADC_SAMPLETIME);//Uc
        adc_ordinary_channel_set(ADC2, ADC_CHANNEL_14, 5, ADC_SAMPLETIME);//Ua
        adc_ordinary_channel_set(ADC2, ADC_CHANNEL_8, 6, ADC_SAMPLETIME);//Ub
        adc_ordinary_channel_set(ADC2, ADC_CHANNEL_9, 7, ADC_SAMPLETIME);//Uc
        /* Enable ADC2 external trigger */
        //adc_ordinary_conversion_trigger_set(ADC2, ADC12_ORDINARY_TRIG_TMR2CH2, TRUE);

        /* Enable ADC1 */
        adc_enable(ADC1, TRUE);
        /* Enable ADC2 */
        adc_enable(ADC2, TRUE);

        /* Enable ADC1 reset calibration register */
        adc_calibration_init(ADC1);
        /* Check the end of ADC1 reset calibration register */
        while (adc_calibration_init_status_get(ADC1));
        /* Start ADC1 calibration */
        adc_calibration_start(ADC1);
        /* Check the end of ADC1 calibration */
        while (adc_calibration_status_get(ADC1));

        /* Enable ADC2 reset calibration register */
        adc_calibration_init(ADC2);
        /* Check the end of ADC2 reset calibration register */
        while (adc_calibration_init_status_get(ADC2));
        /* Start ADC2 calibration */
        adc_calibration_start(ADC2);
        /* Check the end of ADC2 calibration */
        while (adc_calibration_status_get(ADC2));
}

利用DMA传输完成中断来读取数据,并进行计算。
void DMA1_Channel1_IRQHandler(void)
{
        static uint32_t ADCounter = 0;

        if (dma_flag_get(DMA1_FDT1_FLAG) != RESET)
        {
                dma_flag_clear(DMA1_FDT1_FLAG);
                Get_Sample();
        }
}

以下是存储下来的录波数据,从波形上可以看出,采样虽然每次都要对7个采样通道各计算一次FT,但是计算时间是小于采样间隔的,采样点完整连续,没有任何问题。对比了原始波形与装置AD采样下来的波形,波形一致,没有突变点,由此可以看出F435的AD性能是比较稳定的,符合我这个项目的选型要求,后续会在此基础上做进一步的算法开发。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

22

帖子

0

粉丝