[AT32F403/403A] at32F403AVGT7的adc采样率达不到1M

[复制链接]
2459|11
lgcae 发表于 2025-11-5 18:06 | 显示全部楼层 |阅读模式
使用的v2库配置的adc,用20M时钟,配置7.5采样周期,定时器tmr3溢出触发,不知道为啥速度不达1M,下面是代码,有没有大佬帮我看看,我的配置哪里的错误,{:cry:}
void tmr3_init(void)
{
        crm_clocks_freq_type crm_clocks_freq_struct = {0};
        crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE);                //开启tmr3时钟       
        /* get system clock */
        crm_clocks_freq_get(&crm_clocks_freq_struct);

        /* (systemclock/(systemclock/10000))/1000 = 10Hz(100ms) */
        tmr_base_init(TMR3, 9, (crm_clocks_freq_struct.sclk_freq/10000000 - 1));
        tmr_cnt_dir_set(TMR3, TMR_COUNT_UP);                                                //向上计数

        tmr_primary_mode_select(TMR3,TMR_PRIMARY_SEL_OVERFLOW);          //设置TMR的主模式,输出溢出触发源

}

void adc_collect_init(void)
{
        tmr3_init();
        gpio_init_type gpio_initstructure;
        adc_base_config_type adc_base_struct;
        dma_init_type dma_init_struct;
       
        crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
        crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
        crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);                //开启dma1时钟
        crm_adc_clock_div_set(CRM_ADC_DIV_6);                                                //ADC时钟6分频
       
        gpio_default_para_init(&gpio_initstructure);
        gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
        gpio_initstructure.gpio_pins = GPIO_PINS_0;
        gpio_init(GPIOB, &gpio_initstructure);
       
        dma_reset(DMA1_CHANNEL1);
        dma_default_para_init(&dma_init_struct);  
    dma_init_struct.buffer_size = 1;                                                               //内存大小为1
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;                   //传输方向为外设到内存
    dma_init_struct.memory_base_addr = (uint32_t)adc1_ordinary_valuetab;        //内存地址
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;         //内存数据的宽度,16位
    dma_init_struct.memory_inc_enable = FALSE;                                  //内存地址递增打开
    dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);              //外设地址为adc数据寄存器地址`
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD; //外设数据的宽度,16位
    dma_init_struct.peripheral_inc_enable = FALSE;                              //外设地址递增关闭
    dma_init_struct.priority = DMA_PRIORITY_MEDIUM;                             //中等优先级
    dma_init_struct.loop_mode_enable = TRUE;                                                                        //循环传输,传输完1个后重新开始
        dma_init(DMA1_CHANNEL1, &dma_init_struct);
       
               
        /* select combine mode */
        adc_combine_mode_select(ADC_INDEPENDENT_MODE);                                                                                //设置adc工作模式,独立模式
        adc_base_default_para_init(&adc_base_struct);       
        adc_base_struct.sequence_mode = FALSE;                                                                                                //关闭序列模式
        adc_base_struct.repeat_mode = TRUE;                                                                                                        //关闭重复模式
        adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;                                                                        //数据右对齐
        adc_base_struct.ordinary_channel_length = 1;                                                                                //通道数为1
        adc_base_config(ADC1, &adc_base_struct);                                                                                        //初始化参数
        adc_ordinary_channel_set(ADC1, ADC_CHANNEL_8, 1, ADC_SAMPLETIME_7_5);                                //ADC1,ADC通道,序列号1,采样时间为7.5周期
        adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_TMR3TRGOUT, TRUE);        //普通通道触发设置为软件触发
       
        adc_dma_mode_enable(ADC1, TRUE);                                //使能adc dma功能
        dma_channel_enable(DMA1_CHANNEL1, TRUE);                  //使能通道1
       
        adc_enable(ADC1, TRUE);                                                        //使能ADC1
        adc_calibration_init(ADC1);                                                //初始化校准
        while(adc_calibration_init_status_get(ADC1));        //初始化校准完毕
        adc_calibration_start(ADC1);                                        //开始校准
        while(adc_calibration_status_get(ADC1));                //校准完毕
       
        tmr_counter_enable(TMR3, FALSE);
}
主频是240M
EchoInSilence 发表于 2025-11-6 09:19 | 显示全部楼层
不能用轮询啊,用DMA方式会好一点
玫瑰凋零日记 发表于 2025-12-7 21:28 | 显示全部楼层
AT32F403AVGT7 ADC 标称支持 1M 采样率,若实测达不到,软件层面大概率是核心诱因:比如未配置最大分频系数、未开启 ADC DMA 连续转换、采样时间参数设得过大,或时钟树配置错误导致 ADC 时钟未达最高频,也可能是未关闭多余中断抢占 ADC 资源。
爱丽丝的梦 发表于 2026-2-16 20:55 | 显示全部楼层
多为 ADC 时钟分频过低、采样周期设长、未开连续 / DMA、触发源配置不当,也可能是输入阻抗不匹配导致采样不充分
duo点 发表于 2026-2-6 16:05 | 显示全部楼层
可能是ADC时钟配置错误
cr315 发表于 2026-2-6 19:06 | 显示全部楼层
AT32F403的ADC时钟最高支持28MHz,而您当前配置为240MHz系统时钟经6分频后得到40MHz ADC时钟,已严重超频。建议将crm_adc_clock_div_set(CRM_ADC_DIV_6)改为CRM_ADC_DIV_8(30MHz)或CRM_ADC_DIV_9(26.67MHz)。
wangshujun 发表于 2026-2-6 16:49 | 显示全部楼层
本帖最后由 wangshujun 于 2026-2-6 17:04 编辑

采样7.5,转换应该是12.5,相加正好20,要想达成1兆的采样率必须减小采样时间或者提高时钟频率
adc时钟/转换率至少要大于采样时间+转换时间,最好能到2的差值
迷雾隐者 发表于 2026-2-9 10:54 | 显示全部楼层
我同意楼上的看法,时钟配置不一致可能是导致采样率达不到预期的原因
WhisperingTrees 发表于 2026-2-10 19:57 | 显示全部楼层
cr315 发表于 2026-2-6 19:06
AT32F403的ADC时钟最高支持28MHz,而您当前配置为240MHz系统时钟经6分频后得到40MHz ADC时钟,已严重超频。 ...

是的要看下手册,你adc的时钟线最高是多少
小岛西岸来信 发表于 2026-3-2 22:17 | 显示全部楼层
多因配置不当:ADCCLK 未达标称、采样时间设长、多通道切换延时、DMA 未启用或软件干预,导致有效采样率低于 1M。
彩虹捕手 发表于 2026-3-9 23:48 | 显示全部楼层
你的代码中,定时器溢出触发ADC采样,但主频是240M,你计算的定时器设置可能不正确
穷得掉渣大侠 发表于 2026-4-2 09:10 | 显示全部楼层
检查一下你的系统时钟配置,确保系统时钟是20M,因为ADC的采样频率与系统时钟有关。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

4

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0