RISC-V技术论坛
直播中

张曙旻

11年用户 106经验值
私信 关注
[经验]

【兆易创新GD32VF103R-START开发板试用体验】电量检测小装置

VID_20220715_165745

1、 前言
电池在使用过程中,需要检测电量,以免出现过放等损坏电池的现象。
1.1检测方法
使用的电池为3s标称11.1V锂电池,通过电阻分压的方法,配置合适的电阻比,检测接地电阻的电压,通过AD转换将采集的电压值转换为数字量,一旦检测到电压低,报警灯亮。
1.2AD转换原理
模拟信号经过采样、量化和编码,形成离散的、能被二进制描述的数字信号的过程,称为AD转换。大家都懂哈,就不赘述了。
2、电池电量检测原理
2.1电路设计
图片1.png
2.2gd32引脚配置
PA1用于AD采集
PA7PA8PA10PC13分别用于电量的指示。
3、代码编写
附录中有全部源码。
  1. /*!
  2.     file    main.c
  3.     brief   running led demo
  4.     version 2019-06-05, V1.0.0, demo for GD32VF103
  5.     version 2020-12-18, V1.1.0, demo for GD32VF103
  6. */
  7. /*
  8.     Copyright (c) 2020, GigaDevice Semiconductor Inc.
  9.     Redistribution and use in source and binary forms, with or without modification,
  10. are permitted provided that the following conditions are met:
  11.     1. Redistributions of source code must retain the above copyright notice, this
  12.        list of conditions and the following disclaimer.
  13.     2. Redistributions in binary form must reproduce the above copyright notice,
  14.        this list of conditions and the following disclaimer in the documentation
  15.        and/or other materials provided with the distribution.
  16.     3. Neither the name of the copyright holder nor the names of its contributors
  17.        may be used to endorse or promote products derived from this software without
  18.        specific prior written permission.
  19.    
  20. */
  21. #include "gd32vf103.h"
  22. #include "gd32vf103r_start.h"
  23. #include "systick.h"
  24. void led_init(void);
  25. void timer_pwm_config(void);
  26. void timer0_config(void);
  27. void AG_ADC0_init(void);
  28. /*!
  29.     brief      main function
  30.     param[in]  none
  31.     param[out] none
  32.     retval     none
  33. */
  34. uint32_t interrupt_counter = 0;
  35. uint16_t T=0;
  36. uint16_t adc_value;
  37. float Vbat;
  38. void TIMER0_UP_IRQHandler(void)
  39. {
  40.   if(timer_interrupt_flag_get(TIMER0, TIMER_INT_FLAG_UP)!=RESET)
  41.   {
  42.       timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_UP);
  43.       //gpio_bit_write(GPIOA, GPIO_PIN_7, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_7)));
  44. //      T+=50;
  45. //      if(T>999)
  46. //      {
  47. //          T=0;
  48. //      }
  49.   }
  50. }
  51. void ADC0_1_IRQHandler(void)
  52. {
  53.     if(adc_interrupt_flag_get(ADC0, ADC_INT_FLAG_EOC) != RESET)
  54.     {
  55.         adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
  56.         adc_value = adc_regular_data_read(ADC0);
  57.     }
  58. }
  59. int main(void)
  60. {  
  61.     led_init();
  62.     eclic_global_interrupt_enable();//使能全局中断
  63.     eclic_set_nlbits(ECLIC_GROUP_LEVEL3_PRIO1);//分组
  64.     eclic_irq_enable(TIMER0_UP_IRQn, 1, 0);//使能中断请求--设置优先级
  65.     //timer_pwm_config();
  66.     timer0_config();
  67.     AG_ADC0_init();
  68.     while(1)
  69.     {
  70. //        /* turn on LED1 */
  71. //        gpio_bit_set(GPIOA, GPIO_PIN_7);
  72. //        /* insert 200 ms delay */
  73. //        delay_1ms(100);
  74. //
  75. //        /* turn on LED2 */
  76. //        gpio_bit_set(GPIOA, GPIO_PIN_8);
  77. //        /* insert 200 ms delay */
  78. //        delay_1ms(200);
  79. //
  80. //        /* turn on LED3 */
  81. //        gpio_bit_set(GPIOA, GPIO_PIN_10);
  82. //        /* insert 200 ms delay */
  83. //        delay_1ms(300);
  84. //
  85. //        /* turn on LED4 */
  86. //        gpio_bit_set(GPIOC, GPIO_PIN_13);
  87. //        /* insert 200 ms delay */
  88. //        delay_1ms(400);
  89. ////        gpio_bit_write(GPIOA, GPIO_PIN_7, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_7)));
  90. //
  91. //
  92. //        /* turn off LEDs */
  93. //        gpio_bit_reset(GPIOA, GPIO_PIN_7| GPIO_PIN_8 | GPIO_PIN_10);
  94. //        gpio_bit_reset(GPIOC, GPIO_PIN_13);
  95.         
  96.         adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); //ADC软件触发使能
  97.         adc_value = adc_regular_data_read(ADC0);
  98.         Vbat=((float)adc_value/4096)*3.3f*11.1;
  99.         if(Vbat>12.5)
  100.             {
  101.               gpio_bit_set(GPIOA, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_10);
  102.               gpio_bit_set(GPIOC, GPIO_PIN_13);
  103.             }
  104.        else if((Vbat>11)&&(Vbat<=12.5))
  105.             {
  106.               gpio_bit_reset(GPIOA, GPIO_PIN_7);
  107.               gpio_bit_set(GPIOA, GPIO_PIN_8|GPIO_PIN_10);
  108.               gpio_bit_set(GPIOC, GPIO_PIN_13);
  109.             }
  110.        else if((Vbat>10)&&(Vbat<=11))
  111.         {
  112.              gpio_bit_reset(GPIOA, GPIO_PIN_7|GPIO_PIN_8);
  113.              gpio_bit_set(GPIOA, GPIO_PIN_10);
  114.              gpio_bit_set(GPIOC, GPIO_PIN_13);
  115.          }
  116.        else if((Vbat>9.5)&&(Vbat<=10))
  117.          {
  118.              gpio_bit_reset(GPIOA, GPIO_PIN_7|GPIO_PIN_8| GPIO_PIN_10);
  119.              gpio_bit_set(GPIOC, GPIO_PIN_13);
  120.           }
  121.        else if(Vbat<=9.5)
  122.                 {
  123.                     gpio_bit_reset(GPIOA, GPIO_PIN_7|GPIO_PIN_8| GPIO_PIN_10);
  124.                     gpio_bit_reset(GPIOC, GPIO_PIN_13);
  125.                  }
  126.         delay_1ms(100);
  127.     }
  128. }
  129. /*!
  130.     brief      initialize the LEDs
  131.     param[in]  none
  132.     param[out] none
  133.     retval     none
  134. */
  135. void led_init(void)
  136. {
  137.     /* enable the LEDs clock */
  138.    rcu_periph_clock_enable(RCU_GPIOA);
  139.    rcu_periph_clock_enable(RCU_GPIOC);
  140.    /* configure LEDs GPIO port */
  141.    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
  142.    gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_10);
  143.    gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
  144.    /* turn off LEDs */
  145.    gpio_bit_reset(GPIOA, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_10);
  146.    gpio_bit_reset(GPIOC, GPIO_PIN_13);
  147. }
  148. void timer_pwm_config(void)
  149. {
  150.     /* -----------------------------------------------------------------------
  151.     TIMER2CLK is 100KHz
  152.     TIMER2 channel0 duty cycle = (25000/ 50000)* 100  = 50%
  153.     ----------------------------------------------------------------------- */
  154.     timer_oc_parameter_struct timer_ocintpara;
  155.     timer_parameter_struct timer_initpara;
  156.     rcu_periph_clock_enable(RCU_TIMER2);
  157.     timer_deinit(TIMER2);
  158.     /* TIMER configuration */
  159.     timer_initpara.prescaler         = 71;
  160.     timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
  161.     timer_initpara.counterdirection  = TIMER_COUNTER_UP;
  162.     timer_initpara.period            = 49999;
  163.     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
  164.     timer_initpara.repetitioncounter = 0;
  165.     timer_init(TIMER2,&timer_initpara);
  166.     /* configure CH0 in PWM mode0 */
  167.     timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
  168.     timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
  169.     timer_channel_output_config(TIMER2,TIMER_CH_0,&timer_ocintpara);
  170.     timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,2499);
  171.     timer_channel_output_mode_config(TIMER2,TIMER_CH_0,TIMER_OC_MODE_PWM0);
  172.     timer_channel_output_shadow_config(TIMER2,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
  173.     /* auto-reload preload enable */
  174.     timer_auto_reload_shadow_enable(TIMER2);
  175.     /* auto-reload preload enable */
  176.     //timer_enable(TIMER2);
  177. }
  178. void timer0_config(void)
  179. {
  180.     timer_parameter_struct   timer_initpara; //定时器结构体
  181.     rcu_periph_clock_enable(RCU_TIMER0);     //使能TIMER0时钟
  182.     timer_deinit(TIMER0);
  183.     timer_struct_para_init(&timer_initpara); //将结构体参数变为初始值
  184.     timer_initpara.prescaler         = 10799;               //预分频108MH/108=10KHz
  185.     timer_initpara.alignedmode       = TIMER_COUNTER_EDGE; //对齐模式
  186.     timer_initpara.counterdirection  = TIMER_COUNTER_UP;   //计数方向
  187.     timer_initpara.period            = 999;               //周期10KHz/1000=10Hz
  188.     timer_initpara.clockdivision     = TIMER_CKDIV_DIV4;   //时钟分频
  189.     timer_initpara.repetitioncounter = 0;                  //重复计数器
  190.     timer_init(TIMER0, &timer_initpara);
  191.     timer_interrupt_enable(TIMER0,TIMER_INT_UP); //使能更新中断
  192.     //eclic_irq_enable(TIMER0_UP_IRQn,2,0); //使能中断线
  193.     timer_enable(TIMER0);
  194. }
  195. void AG_ADC0_init(void)
  196. {
  197.     rcu_periph_clock_enable(RCU_GPIOA);
  198.     rcu_periph_clock_enable(RCU_ADC0);
  199.     gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
  200.     adc_deinit(ADC0);
  201.     adc_mode_config(ADC_MODE_FREE);  //配置ADC同步模式
  202.     adc_mode_config(ADC_DAUL_REGULAL_FOLLOWUP_FAST);  //配置ADC同步模式
  203.     adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); //ADC0特殊功能开启
  204.     adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); //配置ADC数据对齐方式
  205.     adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);//配置规则通道组或注入通道组的长度 ,1个规则组
  206.     adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);//规则组选择
  207.     adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE); //软件触发
  208.     adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); //配置ADC外部触发
  209.     adc_discontinuous_mode_config(ADC0, ADC_REGULAR_CHANNEL, 1); //配置ADC间断模式
  210.     adc_enable(ADC0);
  211.     delay_1ms(1);
  212.     adc_calibration_enable(ADC0);  //ADC0校准复位
  213. }

4、参考文档
GD32VF103-START-V1.0
GD32VF103_Datasheet_Rev1.5

更多回帖

发帖
×
20
完善资料,
赚取积分