[AT32F435] AT32F435/437 ADC电压监测

[复制链接]
 楼主| 我想看大海 发表于 2024-11-16 18:23 | 显示全部楼层 |阅读模式
功能简介  ADC支持电压监测功能,在需要监测通道电压时,可参考本例进行设计。
本例将固定监控普通通道组的Channel5,监控阈值为0~Vref+/3。

硬件环境: 对应产品型号的AT-START BOARD
PA4——3.3V
PA5——0V
PA6——1.5V左右

配置流程

 配置ADC使用的GPIO
 配置用于普通通道数据传输的DMA
 ADC相关配置及电压监测设定
 普通通道软触发
 获取转换数据

2) 代码介绍
GPIO配置函数代码
  1. static void gpio_config(void)
  2. {
  3. gpio_init_type gpio_initstructure;
  4. crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  5. gpio_default_para_init(&gpio_initstructure);
  6. /* config adc pin as analog input mode */
  7. gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
  8. gpio_initstructure.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5 | GPIO_PINS_6;
  9. gpio_init(GPIOA, &gpio_initstructure);
  10. }   
DMA配置函数代码
  1. static void dma_config(void)
  2. {
  3. dma_init_type dma_init_struct;
  4. crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  5. nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
  6. dma_reset(DMA1_CHANNEL1);
  7.   dma_default_para_init(&dma_init_struct);
  8.   dma_init_struct.buffer_size = 3;
  9.   dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  10.   dma_init_struct.memory_base_addr = (uint32_t)adc1_ordinary_valuetab;
  11.   dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  12.   dma_init_struct.memory_inc_enable = TRUE;
  13.   dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
  14.   dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  15.   dma_init_struct.peripheral_inc_enable = FALSE;
  16.   dma_init_struct.priority = DMA_PRIORITY_HIGH;
  17.   dma_init_struct.loop_mode_enable = TRUE;
  18.   dma_init(DMA1_CHANNEL1, &dma_init_struct);
  19.    
  20.   dmamux_enable(DMA1, TRUE);
  21.   dmamux_init(DMA1MUX_CHANNEL1, DMAMUX_DMAREQ_ID_ADC1);
  22.    
  23.   /* enable dma transfer complete interrupt */
  24.   dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, FALSE);
  25.   dma_channel_enable(DMA1_CHANNEL1, TRUE);
  26. }   
ADC配置函数代码
  1. static void adc_config(void)
  2. {
  3.   adc_common_config_type adc_common_struct;
  4.   adc_base_config_type adc_base_struct;
  5.   crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
  6.   nvic_irq_enable(ADC1_2_3_IRQn, 0, 0);
  7.    
  8.   adc_common_default_para_init(&adc_common_struct);
  9.    
  10.   /* config combine mode */
  11.   adc_common_struct.combine_mode = ADC_INDEPENDENT_MODE;
  12.    
  13.   /* config division,adcclk is division by hclk */
  14.   adc_common_struct.div = ADC_HCLK_DIV_4;
  15.    
  16.   /* config common dma mode,it's not useful in independent mode */
  17.   adc_common_struct.common_dma_mode = ADC_COMMON_DMAMODE_DISABLE;
  18.    
  19.   /* config common dma request repeat */
  20.   adc_common_struct.common_dma_request_repeat_state = FALSE;
  21.    
  22.   /* config adjacent adc sampling interval,it's useful for ordinary shifting mode */
  23. adc_common_struct.sampling_interval = ADC_SAMPLING_INTERVAL_5CYCLES;
  24.    
  25.   /* config inner temperature sensor and vintrv */
  26.   adc_common_struct.tempervintrv_state = FALSE;
  27.    
  28.   /* config voltage battery */
  29.   adc_common_struct.vbat_state = FALSE;
  30.   adc_common_config(&adc_common_struct);
  31.    
  32.   adc_base_default_para_init(&adc_base_struct);
  33.    
  34.   adc_base_struct.sequence_mode = TRUE;
  35.   adc_base_struct.repeat_mode = FALSE;
  36.   adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
  37.   adc_base_struct.ordinary_channel_length = 3;
  38.   adc_base_config(ADC1, &adc_base_struct);
  39.   adc_resolution_set(ADC1, ADC_RESOLUTION_12B);
  40.    
  41.   /* config ordinary channel */
  42.   adc_ordinary_channel_set(ADC1, ADC_CHANNEL_4, 1, ADC_SAMPLETIME_47_5);
  43.   adc_ordinary_channel_set(ADC1, ADC_CHANNEL_5, 2, ADC_SAMPLETIME_47_5);
  44.   adc_ordinary_channel_set(ADC1, ADC_CHANNEL_6, 3, ADC_SAMPLETIME_47_5);
  45.    
  46.   /* config ordinary trigger source and trigger edge */
  47.   adc_ordinary_conversion_trigger_set(ADC1, ADC_ORDINARY_TRIG_TMR1CH1,
  48. ADC_ORDINARY_TRIG_EDGE_NONE);
  49.    
  50.   /* config dma mode,it's not useful when common dma mode is use */
  51.   adc_dma_mode_enable(ADC1, TRUE);
  52.    
  53.   /* config dma request repeat,it's not useful when common dma mode is use */
  54.   adc_dma_request_repeat_enable(ADC1, TRUE);
  55.    
  56.   /* config voltage_monitoring */
  57.   adc_voltage_monitor_threshold_value_set(ADC1, 0x100, 0x000);
  58.   adc_voltage_monitor_single_channel_select(ADC1, ADC_CHANNEL_5);
  59.   adc_voltage_monitor_enable(ADC1, ADC_VMONITOR_SINGLE_ORDINARY);
  60.    
  61.   /* enable adc overflow interrupt */
  62.   adc_interrupt_enable(ADC1, ADC_OCCO_INT, TRUE);
  63.    
  64.   /* enable voltage monitoring out of range interrupt */
  65.   adc_interrupt_enable(ADC1, ADC_VMOR_INT, TRUE);
  66.    
  67.   /* adc enable */
  68.   adc_enable(ADC1, TRUE);
  69.   while(adc_flag_get(ADC1, ADC_RDY_FLAG) == RESET);
  70.    
  71.   /* adc calibration */
  72.   adc_calibration_init(ADC1);
  73.   while(adc_calibration_init_status_get(ADC1));
  74.   adc_calibration_start(ADC1);
  75.   while(adc_calibration_status_get(ADC1));
  76. }   
中断服务函数代码
  1. /* 溢出及电压超出范围监测 */
  2. void ADC1_2_3_IRQHandler(void)
  3. {
  4.   if(adc_flag_get(ADC1, ADC_OCCO_FLAG) != RESET)
  5.   {
  6.     adc_flag_clear(ADC1, ADC_OCCO_FLAG);
  7.     adc1_overflow_flag++;
  8.   }
  9.   if(adc_flag_get(ADC1, ADC_VMOR_FLAG) != RESET)
  10.   {
  11.     adc_flag_clear(ADC1, ADC_VMOR_FLAG);
  12.     vmor_flag_index++;
  13.   }
  14. }

main函数代码

  1. int main(void)
  2. {
  3.   __IO uint32_t index = 0;
  4.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  5.    
  6.   /* config the system clock */
  7.   system_clock_config();
  8.    
  9.   /* init at start board */
  10.   at32_board_init();
  11.   at32_led_off(LED2);
  12.   at32_led_off(LED3);
  13.   at32_led_off(LED4);
  14.   usart1_config(115200);
  15.   gpio_config();
  16.   dma_config();
  17.   adc_config();
  18.   printf("voltage_monitoring \r\n");
  19.   while(1)
  20.   {
  21.     at32_led_toggle(LED2);
  22. delay_sec(1);
  23.     if((adc1_overflow_flag != 0) || (vmor_flag_index != 0))
  24.     {
  25.       /* printf flag when error occur */
  26.       at32_led_on(LED3);
  27.       at32_led_on(LED4);
  28.       printf("error occur\r\n");
  29.       printf("vmor_flag_index = %d\r\n",vmor_flag_index);
  30.       printf("adc1_overflow_flag = %d\r\n",adc1_overflow_flag);
  31.       printf("out of range:adc1_channel_5 value is = 0x%x!\r\n", adc1_ordinary_valuetab[1]);
  32.     }
  33.     adc_ordinary_software_trigger_enable(ADC1, TRUE);
  34.   }
  35. }   
实验效果
可通过串口打印查看实现效果,测试过程中随机将Channel5外接1.5V,最终串口打印信息如下。
通过打印信息可以看到:有实际监测到Channel5超过监控阈值,且记录到的实际监控值为1.5V。
串口配置
Baud rate:115200
Stop bits:1
Data bits:8
Parity:None
ADC电压监测实验结果
401246738729defe8f.png
菜鸟的第一步 发表于 2024-11-16 20:14 | 显示全部楼层
读出来的ADC值怎么转换为电压
 楼主| 我想看大海 发表于 2024-11-20 20:38 | 显示全部楼层
菜鸟的第一步 发表于 2024-11-16 20:14
读出来的ADC值怎么转换为电压

电压 = ADC值 * (参考电压 / (2^N - 1))。N是ADC的位数
菜鸟的第一步 发表于 2024-11-24 19:00 | 显示全部楼层
我想看大海 发表于 2024-11-20 20:38
电压 = ADC值 * (参考电压 / (2^N - 1))。N是ADC的位数

好的,谢谢,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

282

帖子

0

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