很早就关注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性能是比较稳定的,符合我这个项目的选型要求,后续会在此基础上做进一步的算法开发。
|
|