ADC.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*********************************************************************************************************
  2. * 模块名称:ADC.c
  3. * 摘 要:内部ADC应用,采用12bit。
  4. * 当前版本:1.0.0
  5. * 作 者:anycrying
  6. * 完成日期:2024年04月06日
  7. * 内 容:
  8. * 注 意:
  9. **********************************************************************************************************
  10. * 取代版本:
  11. * 作 者:
  12. * 完成日期:
  13. * 修改内容:
  14. * 修改文件:
  15. *********************************************************************************************************/
  16. /*********************************************************************************************************
  17. * 包含头文件
  18. *********************************************************************************************************/
  19. #include <stdbool.h>
  20. #include "ADC.h"
  21. #include "gd32e230x_conf.h"
  22. #include "SysTick.h"
  23. #include "Timer.h"
  24. /*********************************************************************************************************
  25. * 宏定义
  26. *********************************************************************************************************/
  27. /*********************************************************************************************************
  28. * 枚举结构体
  29. *********************************************************************************************************/
  30. /*********************************************************************************************************
  31. * 内部变量定义
  32. *********************************************************************************************************/
  33. bool adc_data_ok_flag = false;
  34. uint8_t adc_sample_n;//采样次数
  35. uint16_t adc_original_value[ADC_CH_N]={0};//存放各通道原始值
  36. uint16_t adc_calc_value[ADC_Avg_N][ADC_CH_N];//各通道中间过程计算值
  37. uint32_t adc_Avg_value[ADC_CH_N];//存放各通道平均值
  38. extern uint16_t adc_data_zero[ADC_CH_N];
  39. /*********************************************************************************************************
  40. * 内部函数声明
  41. *********************************************************************************************************/
  42. /*********************************************************************************************************
  43. * 函数名称:Init_ADC
  44. * 函数功能:初始化ADC模块
  45. * 输入参数:void
  46. * 输出参数:void
  47. * 返 回 值:void
  48. * 创建日期:2024年04月06日
  49. * 注 意:
  50. *********************************************************************************************************/
  51. void Init_ADC(void)
  52. {
  53. adc_sample_n = 0;
  54. ConfigADCGPIO();
  55. }
  56. /*********************************************************************************************************
  57. * 函数名称:ConfigADCGPIO
  58. * 函数功能:配置ADC的GPIO ,ADC通道3和4用于串口通信,所以扩展用了ADC通道9和10
  59. * 输入参数:void
  60. * 输出参数:void
  61. * 返 回 值:void
  62. * 创建日期:2024年04月06日
  63. * 注 意:
  64. *********************************************************************************************************/
  65. void ConfigADCGPIO(void)
  66. {
  67. //使能RCU相关时钟
  68. rcu_periph_clock_enable(ADC_0_5_RCU);//使能GPIOA的时钟
  69. rcu_periph_clock_enable(ADC_67_RCU);//使能GPIOB的时钟
  70. //使能ADC时钟
  71. rcu_periph_clock_enable(RCU_ADC);
  72. //使能DMA的时钟
  73. rcu_periph_clock_enable(RCU_DMA);
  74. //配置ADC时钟
  75. rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
  76. //设置GPIO为ADC接口
  77. gpio_mode_set(ADC_0_5_IO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_ch0|ADC_ch1|ADC_ch2|ADC_ch3|ADC_ch4|ADC_ch5);//ADC通道3和4用于串口通信,所以扩展用了ADC通道9和10
  78. gpio_mode_set(ADC_67_IO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_ch6|ADC_ch7);
  79. //复位ADC外设
  80. adc_deinit();
  81. //配置DMA
  82. ADC_dma_config();
  83. //内部ADC配置
  84. adc_special_function_config(ADC_SCAN_MODE,ENABLE);//配置ADC扫描转换模式
  85. adc_special_function_config(ADC_CONTINUOUS_MODE,ENABLE);//配置ADC连续转换模式
  86. adc_external_trigger_source_config(ADC_REGULAR_CHANNEL,ADC_EXTTRIG_REGULAR_NONE);//配置ADC外部触发是软件触发
  87. adc_data_alignment_config(ADC_DATAALIGN_RIGHT);//配置ADC数据对齐方式是右对齐
  88. adc_resolution_config(ADC_RESOLUTION_12B);//配置ADC为12位
  89. adc_channel_length_config(ADC_REGULAR_CHANNEL, ADC_CH_N);//配置ADC规则通道组成或注入通道组的长度,因为用到8个通道,所以是8
  90. adc_regular_channel_config(0U, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);//配置ADC通道组
  91. adc_regular_channel_config(1U, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
  92. adc_regular_channel_config(2U, ADC_CHANNEL_4, ADC_SAMPLETIME_55POINT5);
  93. adc_regular_channel_config(3U, ADC_CHANNEL_5, ADC_SAMPLETIME_55POINT5);
  94. adc_regular_channel_config(4U, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5);
  95. adc_regular_channel_config(5U, ADC_CHANNEL_7, ADC_SAMPLETIME_55POINT5);
  96. adc_regular_channel_config(6U, ADC_CHANNEL_8, ADC_SAMPLETIME_55POINT5);
  97. adc_regular_channel_config(7U, ADC_CHANNEL_9, ADC_SAMPLETIME_55POINT5);
  98. adc_enable();//使能
  99. adc_enable();//使能
  100. //delay_ms(2);
  101. adc_calibration_enable();//校准复位
  102. adc_dma_mode_enable();//使能DMA
  103. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);//软件触发
  104. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
  105. //dma_interrupt_enable(DMA_CH0,DMA_INT_FTF);
  106. }
  107. /*********************************************************************************************************
  108. * 函数名称:ADC_dma_config
  109. * 函数功能:配置ADC采用DMA方式
  110. * 输入参数:void
  111. * 输出参数:void
  112. * 返 回 值:void
  113. * 创建日期:2024年04月06日
  114. * 注 意:
  115. *********************************************************************************************************/
  116. void ADC_dma_config(void)
  117. {
  118. //通道参数配置
  119. dma_parameter_struct dma_data_parameter;
  120. //使能ADC时钟
  121. rcu_periph_clock_enable(RCU_ADC);
  122. //使能DMA的时钟
  123. rcu_periph_clock_enable(RCU_DMA);
  124. //复位DMA通道
  125. dma_deinit(DMA_CH0);
  126. //初始化DMA为单数据模式
  127. dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA);//设置DMA外设地址,也是DMA数据传输的源地址,ADC单次采样转换结束后,会将数据存入ADC_RDATA地址中
  128. dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//设置DMA数据传输的源地址自增算法取消,ADC每次转换后数据存入地址不变
  129. dma_data_parameter.memory_addr = (uint32_t)(adc_original_value);//设置DMA存储器地址,也是DMA数据传输的目标地址
  130. dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//设置DMA数据传输目标地址自增算法使能,因为DMA每个周期需要传送八个数据,所以在一个周期内,目标地址要自增
  131. dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//设置DMA从外设中读出数据的位数,因为ADC转换后的数值是12位,用16位数值表示,所以这里设置为1字
  132. dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; //设置DMA存入存储器的数据位数
  133. dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;//设置DMA的数据传输方向
  134. dma_data_parameter.number = ADC_CH_N;//设置DMA一个周期要传输的数据个数,用了8个通道的ADC,所以在一个周期内要传输8个数据
  135. dma_data_parameter.priority = DMA_PRIORITY_HIGH;//设置DMA数据传输高优先级
  136. dma_circulation_enable(DMA_CH0);//DMA循环模式使能,这样DMA在传输8个数据后,存储地址复位,自动开启下一轮传输
  137. dma_init(DMA_CH0, &dma_data_parameter);//初始化DMA
  138. dma_memory_to_memory_disable(DMA_CH0);//这里用不上,所以存储器到存储器DMA传输取消
  139. dma_channel_enable(DMA_CH0);//使能DMA通道
  140. }
  141. /*********************************************************************************************************
  142. * 函数名称:DC_I_calfunction
  143. * 函数功能:直流电流计算公式函数
  144. * 输入参数:uint16_t 电流的ADC值
  145. * 输出参数:uint32_t 浮点电流值(mA)
  146. * 返 回 值:uint32_t 浮点电流值(mA)
  147. * 创建日期:2024年04月06日
  148. * 注 意:12位ADC转换公式:实际电压值V = (ADC参考电压Vref * 采样数值N) / 2^12
  149. * 电流传感器转换公式:实际电流值I(A) = 实际电压值V / 灵敏度参数(V/A)
  150. * 实际计算时,让小数变成整数,最终结果扩大1000倍
  151. *********************************************************************************************************/
  152. uint32_t DC_I_calfunction(uint16_t da)
  153. {
  154. uint32_t temp_i = 0;
  155. uint32_t temp_v = 0;
  156. if(da > 0)
  157. {
  158. temp_v = da;
  159. temp_v *= ADC_Vref;
  160. temp_v *= 1000;
  161. temp_v = temp_v >> 12;//temp_v /= ADC_Fulscale;
  162. temp_v /= A_gain;
  163. temp_i = temp_v / I_sens;
  164. temp_i /= 10;//去掉第3位小数
  165. temp_i *= 10;
  166. return temp_i;
  167. }
  168. else
  169. {
  170. return 0;
  171. }
  172. }
  173. /*********************************************************************************************************
  174. * 函数名称:read_adc_val
  175. * 函数功能:读取ADC各通道的数据,并将原始值存储到缓冲区,采样ADC_Avg_N次后才计算均值
  176. * 输入参数:void
  177. * 输出参数:void
  178. * 返 回 值:void
  179. * 创建日期:2024年04月06日
  180. * 注 意:
  181. *********************************************************************************************************/
  182. void read_adc_val(void)
  183. {
  184. int8_t i = 0;
  185. if(adc_sample_n < ADC_Avg_N)
  186. {
  187. for(i = 0;i < ADC_CH_N ;i++)
  188. {
  189. adc_Avg_value[i] += adc_original_value[i];
  190. }
  191. adc_sample_n++;
  192. }
  193. else
  194. {
  195. adc_sample_n = 0;
  196. for(i = 0;i < ADC_CH_N ;i++)
  197. {
  198. adc_Avg_value[i] = adc_Avg_value[i] / ADC_Avg_N;
  199. if(adc_Avg_value[i] > adc_data_zero[i])
  200. {
  201. adc_Avg_value[i] -= adc_data_zero[i];
  202. }
  203. else
  204. {
  205. adc_Avg_value[i] = 0;
  206. }
  207. }
  208. adc_data_ok_flag = true;
  209. }
  210. }