【AT-START-F423测评】+ ADC 过采样+DMA

本文介绍了如何在AT32F423微控制器上使用ADC的过采样功能配合DMA进行周期性采样,获取ADC_IN0、温度传感器和内部参考电压的平均值,同时讨论了在DMA使用中的注意事项和测试中遇到的问题。
摘要由CSDN通过智能技术生成

AT32F423 的 ADC 支持过采样,可以对1个通道连续采样多次,直接输出连续采样的平均值。这样可以省去软件做平均。
配合 DMA,周期触发采样,就可以得到对应通道的周期采样的平均值。

本测评采集3个通道,ADC_IN0、内部温度传感器、内部参考电压。
步骤:
1、配置过程
 

 

 

 



2、代码编写
main.c

复制

int main(void)

{

  /* add user code begin 1 */

    uint32_t start_tick;

  /* add user code end 1 */



  /* add a necessary delay to ensure that Vdd is higher than the operating

     voltage of battery powered domain (2.57V) when the battery powered 

     domain is powered on for the first time and being operated. */

  wk_wait_for_power_stable();

  

  /* system clock config. */

  wk_system_clock_config();



  /* config periph clock. */

  wk_periph_clock_config();



  /* nvic config. */

  wk_nvic_config();



  /* init dma1 channel1 */

  wk_dma1_channel1_init();

  /* config dma channel transfer parameter */

  /* user need to modify parameters memory_base_addr and buffer_size */

  wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&ADC1->odt, (uint32_t)adc_val, 3);

  dma_channel_enable(DMA1_CHANNEL1, TRUE);



  /* init usart1 function. */

  wk_usart1_init();



  /* init adc1 function. */

  wk_adc1_init();



  /* add user code begin 2 */

    sys_init();



    printf("The demo is started!\n");

    start_tick = sys_get_tick();



    dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);

    adc_interrupt_enable(ADC1, ADC_OCCO_INT, TRUE);

    adc_interrupt_enable(ADC1, ADC_OCCE_INT, TRUE);

    adc_ordinary_software_trigger_enable(ADC1, TRUE);

  /* add user code end 2 */



  while(1)

  {

    /* add user code begin 3 */

    if (adc_val_update) {

        adc_val_update = 0;



        #define calculate_volt(val)   (val * 3.3 / 4095)

        #define calculate_temperature(val) \

                    ((calculate_volt(val) - 1.29f) * 1000 / 4.26f + 25)

        

        printf("temperature sensor value = %f ℃\n",

               calculate_temperature(adc_val[0]));

        printf("vintrv value = %f V\n", calculate_volt(adc_val[1]));

        printf("ADC_IN0 value = %f V\n\n", calculate_volt(adc_val[2]));

    }

    

    if (sys_get_tick() - start_tick >= 1000) {

        start_tick = sys_get_tick();

        

        dma_flag_clear(DMA1_FDT1_FLAG);

        dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);

        wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&ADC1->odt, (uint32_t)adc_val, 3);

        dma_channel_enable(DMA1_CHANNEL1, TRUE);

        adc_dma_mode_enable(ADC1, TRUE);



        adc_ordinary_software_trigger_enable(ADC1, TRUE);

        

        printf("ADC overflow count = %d\n\n", adc_overflow_cnt);

    }

    /* add user code end 3 */

  }

}

中断函数

复制

void DMA1_Channel1_IRQHandler(void)

{

  /* add user code begin DMA1_Channel1_IRQ 0 */

    if(dma_flag_get(DMA1_FDT1_FLAG)) {

        adc_val_update = 1;

        

        adc_dma_mode_enable(ADC1, FALSE);

        dma_channel_enable(DMA1_CHANNEL1, FALSE);

        dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, FALSE);

    }

  /* add user code end DMA1_Channel1_IRQ 0 */

  /* add user code begin DMA1_Channel1_IRQ 1 */



  /* add user code end DMA1_Channel1_IRQ 1 */

}



void ADC1_IRQHandler(void)

{

  /* add user code begin ADC1_IRQ 0 */

    if(adc_flag_get(ADC1, ADC_OCCO_FLAG) != RESET)

    {

        adc_flag_clear(ADC1, ADC_OCCO_FLAG);

        adc_overflow_cnt++;

    }

    if(adc_flag_get(ADC1, ADC_OCCE_FLAG) != RESET)

    {

        adc_flag_clear(ADC1, ADC_OCCE_FLAG);

    }

  /* add user code end ADC1_IRQ 0 */

  /* add user code begin ADC1_IRQ 1 */



  /* add user code end ADC1_IRQ 1 */

}



3、测试
 



测试中遇到的问题:
1、DMA 使用过程中有开关通道和中断操作,当关必 DMA 通道后,再打开 DMA 通道时,必须要重新使能 ADC 的 DMA,

复制

adc_dma_mode_enable(ADC1, TRUE);

否则,不会触发 DMA 传输。2、内部温度传感器采到的温度值,和 ADC_IN0 的电压相关,ADC_IN0 电压越高,采到的温度越高,猜测可能和通道切换过程有关。不过,内部参考电压不受这些影响。

adc.zip

5.52 MB。
---------------------
作者:cuyebiren
链接:https://bbs.21ic.com/icview-3339152-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 `String.format` 方法来控制每个字段的宽度和对齐方式,如下所示: ``` System.out.println("+---------------+------------------------+------------------------+------------------------+------------------------+------------------+----------------------+"); System.out.println("| Subnet Mask | Subnet Address | Start Address | End Address | Broadcast Address | 借位数 | Subnet Size |"); System.out.println("+---------------+------------------------+------------------------+------------------------+------------------------+------------------+----------------------+"); System.out.printf("| %14d | %22s | %22s | %22s | %22s | %16d | %20s |\n", subnetMaskLengthRequired, subnet, startAddress, endAddress, broadcastAddress, subnetMaskLengthRequired - subnetMaskLength, subnetSize); System.out.println("+---------------+------------------------+------------------------+------------------------+------------------------+------------------+----------------------+"); ``` 输出结果会按照每个字段的宽度对齐,效果如下: ``` +---------------+------------------------+------------------------+------------------------+------------------------+------------------+----------------------+ | Subnet Mask | Subnet Address | Start Address | End Address | Broadcast Address | 借位数 | Subnet Size | +---------------+------------------------+------------------------+------------------------+------------------------+------------------+----------------------+ | 24 | 192.168.1.0 | 192.168.1.1 | 192.168.1.254 | 192.168.1.255 | 8 | 256 | +---------------+------------------------+------------------------+------------------------+------------------------+------------------+----------------------+ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值