概述

电压检测是测量电路中电压的一种重要方法,它在许多电气和电子应用中都有广泛的用途。以下是需要电压检测的一些主要原因:

  1. 确保设备安全:电压检测可以确保电气设备在其额定电压范围内运行。如果设备在过高或过低的电压下运行,可能会导致设备损坏、故障甚至火灾。
  2. 保护电子设备:电子设备通常对电压波动非常敏感,电压检测可以及时发现问题,保护设备免受损害。
  3. 提高能源效率:通过电压检测,我们可以监测电气系统的负载、功率和效率,从而优化能源使用,降低能耗。
  4. 故障诊断:电压检测有助于发现电气系统中的故障和异常,便于维修人员迅速定位问题并进行维修。
  5. 确保系统稳定性:对于某些电气设备,如发电厂、变电站等,电压检测是确保供电系统稳定运行的关键。
  6. 设计和研发:在电子产品的设计和研发阶段,电压检测有助于工程师评估电路性能,优化设计。
  7. 满足法规要求:某些行业和地区可能有严格的电压标准和规定,电压检测有助于确保设备符合这些要求。

总之,电压检测在保障设备安全、提高能效、确保系统稳定性以及满足法规要求等方面都具有重要意义。

在我们当前案例中, 18650锂电池是我们重要设备, 而且它很贵重,一旦过充或者过放, 它将无法使用, 所以我们需要监测锂电池的电压.
18650锂离子电池的过充过放电压值因生产厂家和化学组成有所不同,但通常有一个大致的范围。通常,过充电压值在 4.2V 到 4.25V 之间,过放电压值在 2.5V 到 3.0V 之间。过充和过放电可能会导致电池性能下降、循环寿命缩短甚至安全隐患。所以我们可以设定当18650的电压低于3.5V的时候, 设备断电报警, 让用户及时去充电

image.png
image.png
电池电压的变化是模拟信号, 我们需要使用ADC去读取, 在这里我选择使用的是PC5,下面我们就按照常用步骤来开发:

  1. gpio配置
  2. adc配置
  3. adc读取

ADC的两种模式

在模数转换器(ADC, Analog-to-Digital Converter)中,插入模式和普通模式是指两种不同的数据采集和转换方式。它们之间的主要区别在于采样顺序、通道切换方式和优先级。

  1. 插入模式(Injected Mode): 插入模式是一种特殊的数据采集方式,它允许在规律的连续采样过程中临时插入对其他通道的采样。插入模式具有较高的优先级,当有插入请求时,会暂停正在进行的普通模式采样,优先处理插入模式的采样任务。插入模式的采样完成后,普通模式采样会继续进行。插入模式通常用于需要快速响应的应用场景,例如突发事件的监测。
  2. 普通模式(Regular Mode): 普通模式是ADC的一种常规数据采集方式,通常按照预设的通道顺序进行连续或单次采样。在普通模式下,ADC按照设置的采样顺序和频率对各个通道进行采样,将模拟信号转换为数字信号。普通模式适用于大多数数据采集任务,尤其是对实时性要求不高的场景。

总之,插入模式和普通模式是针对不同应用场景的ADC采样方式。插入模式适用于需要快速响应和高优先级处理的场景,而普通模式适用于常规的连续或单次采样任务。

在电压的采样过程中, 我们可以选择插入模式, 也可以选择普通模式.

示例代码

实现步骤:

  1. 思考用哪个GPIO,确定引脚PB1
  2. 要开启什么样的功能,是ADC,TIMER,DMA中的哪一个? 确定ADC0_9
  3. 选择使用ADC的普通模式,还是插入模式
  4. 选好之后:
    1. 如何初始化
    2. 如何获取数据
  5. 数据拿到之后该如何进行换算

这里面的代码有些复杂, 但是很多代码都是固定写法, 我们可以从gd32官方给的例子里面直接拷贝.

  1. #include "bsp_battery.h"
  2. #include <stdio.h>
  3. #define RCU_BATTERY RCU_GPIOB
  4. #define PORT_BATTERY GPIOB
  5. #define PIN_BATTERY GPIO_PIN_1
  6. #define ADC_RCU_BATTERY RCU_ADC0
  7. #define ADC_BATTERY ADC0
  8. #define ADC_CHANNEL_BATTERY ADC_CHANNEL_9
  9. void bsp_battery_gpio_init(){
  10. // 开启时钟
  11. rcu_periph_clock_enable(RCU_BATTERY);
  12. // 设置gpio
  13. gpio_mode_set(PORT_BATTERY, GPIO_MODE_ANALOG,GPIO_PUPD_NONE,PIN_BATTERY);
  14. }
  15. void bsp_battery_adc_init(){
  16. // 开启时钟线
  17. rcu_periph_clock_enable(ADC_RCU_BATTERY);
  18. // 配置时钟倍频
  19. adc_clock_config(ADC_ADCCK_PCLK2_DIV4);
  20. // 通道配置
  21. adc_channel_length_config(ADC_BATTERY,ADC_INSERTED_CHANNEL,1);
  22. // 配置采集哪个通道 0表示的是角标
  23. adc_inserted_channel_config(ADC_BATTERY,0,ADC_CHANNEL_9,ADC_SAMPLETIME_480);
  24. adc_external_trigger_config(ADC_BATTERY,ADC_INSERTED_CHANNEL,DISABLE);
  25. adc_data_alignment_config(ADC_BATTERY,ADC_DATAALIGN_RIGHT);
  26. adc_special_function_config(ADC0,ADC_SCAN_MODE,ENABLE);
  27. adc_enable(ADC_BATTERY);
  28. adc_calibration_enable(ADC_BATTERY);
  29. }
  30. void bsp_battery_init(void){
  31. bsp_battery_gpio_init();
  32. bsp_battery_adc_init();
  33. }
  34. float bsp_battery_get(){
  35. adc_software_trigger_enable(ADC_BATTERY,ADC_INSERTED_CHANNEL);
  36. uint32_t data = ADC_IDATA0(ADC_BATTERY);
  37. float vol = data*1.0/4096 * 3.3 * 4;
  38. return vol;
  39. }
  40. void bsp_battery_test(){
  41. bsp_battery_init();
  42. while(1){
  43. float bat = bsp_battery_get();
  44. printf("battery:%f\r\n",bat);
  45. delay_1ms(500);
  46. }
  47. }