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 电压越高,采到的温度越高,猜测可能和通道切换过程有关。不过,内部参考电压不受这些影响。
|