ADC.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  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. #include "math.h"
  25. /*********************************************************************************************************
  26. * 宏定义
  27. *********************************************************************************************************/
  28. /*********************************************************************************************************
  29. * 枚举结构体
  30. *********************************************************************************************************/
  31. /*********************************************************************************************************
  32. * 内部变量定义
  33. *********************************************************************************************************/
  34. bool adc_data_ok_flag = false;
  35. uint8_t adc_sample_n;//采样次数
  36. #if SUPPORT_2_V_GA_CHN
  37. uint16_t adc_original_value[ADC_CH_N+ADC_V_CHN]={0};//存放各通道原始值
  38. uint16_t adc_calc_value[ADC_Avg_N][ADC_CH_N+ADC_V_CHN];//各通道中间过程计算值
  39. uint32_t adc_Avg_value[ADC_CH_N+ADC_V_CHN];//存放各通道平均值
  40. extern uint16_t adc_data_zero[ADC_CH_N+ADC_V_CHN];
  41. #else
  42. uint16_t adc_original_value[ADC_CH_N]={0};//存放各通道原始值
  43. uint16_t adc_calc_value[ADC_Avg_N][ADC_CH_N];//各通道中间过程计算值
  44. uint32_t adc_Avg_value[ADC_CH_N];//存放各通道平均值
  45. extern uint16_t adc_data_zero[ADC_CH_N];
  46. #endif
  47. /*********************************************************************************************************
  48. * 内部函数声明
  49. *********************************************************************************************************/
  50. /*********************************************************************************************************
  51. * 函数名称:Init_ADC
  52. * 函数功能:初始化ADC模块
  53. * 输入参数:void
  54. * 输出参数:void
  55. * 返 回 值:void
  56. * 创建日期:2024年04月06日
  57. * 注 意:
  58. *********************************************************************************************************/
  59. void Init_ADC(void)
  60. {
  61. adc_sample_n = 0;
  62. ConfigADCGPIO();
  63. }
  64. /*********************************************************************************************************
  65. * 函数名称:ConfigADCGPIO
  66. * 函数功能:配置ADC的GPIO ,ADC通道3和4用于串口通信,所以扩展用了ADC通道9和10
  67. * 输入参数:void
  68. * 输出参数:void
  69. * 返 回 值:void
  70. * 创建日期:2024年04月06日
  71. * 注 意:
  72. *********************************************************************************************************/
  73. void ConfigADCGPIO(void)
  74. {
  75. //使能RCU相关时钟
  76. rcu_periph_clock_enable(ADC_0_5_RCU);//使能GPIOA的时钟
  77. rcu_periph_clock_enable(ADC_67_RCU);//使能GPIOB的时钟
  78. //使能ADC时钟
  79. rcu_periph_clock_enable(RCU_ADC);
  80. //使能DMA的时钟
  81. rcu_periph_clock_enable(RCU_DMA);
  82. //配置ADC时钟
  83. rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
  84. //设置GPIO为ADC接口
  85. #if SUPPORT_2_V_GA_CHN
  86. 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_Vol_ch1|ADC_Vol_ch2);
  87. #else
  88. 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
  89. #endif
  90. gpio_mode_set(ADC_67_IO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_ch6|ADC_ch7);
  91. //复位ADC外设
  92. adc_deinit();
  93. //配置DMA
  94. ADC_dma_config();
  95. //内部ADC配置
  96. adc_special_function_config(ADC_SCAN_MODE,ENABLE);//配置ADC扫描转换模式
  97. adc_special_function_config(ADC_CONTINUOUS_MODE,ENABLE);//配置ADC连续转换模式
  98. adc_external_trigger_source_config(ADC_REGULAR_CHANNEL,ADC_EXTTRIG_REGULAR_NONE);//配置ADC外部触发是软件触发
  99. adc_data_alignment_config(ADC_DATAALIGN_RIGHT);//配置ADC数据对齐方式是右对齐
  100. adc_resolution_config(ADC_RESOLUTION_12B);//配置ADC为12位
  101. #if SUPPORT_2_V_GA_CHN
  102. adc_channel_length_config(ADC_REGULAR_CHANNEL, ADC_CH_N+ADC_V_CHN);
  103. adc_regular_channel_config(8U, ADC_CHANNEL_3, ADC_SAMPLETIME_55POINT5);
  104. adc_regular_channel_config(9U, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
  105. #else
  106. adc_channel_length_config(ADC_REGULAR_CHANNEL, ADC_CH_N);//配置ADC规则通道组成或注入通道组的长度,因为用到8个通道,所以是8
  107. #endif
  108. adc_regular_channel_config(0U, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);//配置ADC通道组
  109. adc_regular_channel_config(1U, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
  110. adc_regular_channel_config(2U, ADC_CHANNEL_4, ADC_SAMPLETIME_55POINT5);
  111. adc_regular_channel_config(3U, ADC_CHANNEL_5, ADC_SAMPLETIME_55POINT5);
  112. adc_regular_channel_config(4U, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5);
  113. adc_regular_channel_config(5U, ADC_CHANNEL_7, ADC_SAMPLETIME_55POINT5);
  114. adc_regular_channel_config(6U, ADC_CHANNEL_8, ADC_SAMPLETIME_55POINT5);
  115. adc_regular_channel_config(7U, ADC_CHANNEL_9, ADC_SAMPLETIME_55POINT5);
  116. adc_enable();//使能
  117. adc_enable();//使能
  118. //delay_ms(2);
  119. adc_calibration_enable();//校准复位
  120. adc_dma_mode_enable();//使能DMA
  121. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);//软件触发
  122. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
  123. //dma_interrupt_enable(DMA_CH0,DMA_INT_FTF);
  124. }
  125. /*********************************************************************************************************
  126. * 函数名称:ADC_dma_config
  127. * 函数功能:配置ADC采用DMA方式
  128. * 输入参数:void
  129. * 输出参数:void
  130. * 返 回 值:void
  131. * 创建日期:2024年04月06日
  132. * 注 意:
  133. *********************************************************************************************************/
  134. void ADC_dma_config(void)
  135. {
  136. //通道参数配置
  137. dma_parameter_struct dma_data_parameter;
  138. //使能ADC时钟
  139. rcu_periph_clock_enable(RCU_ADC);
  140. //使能DMA的时钟
  141. rcu_periph_clock_enable(RCU_DMA);
  142. //复位DMA通道
  143. dma_deinit(DMA_CH0);
  144. //初始化DMA为单数据模式
  145. dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA);//设置DMA外设地址,也是DMA数据传输的源地址,ADC单次采样转换结束后,会将数据存入ADC_RDATA地址中
  146. dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//设置DMA数据传输的源地址自增算法取消,ADC每次转换后数据存入地址不变
  147. dma_data_parameter.memory_addr = (uint32_t)(adc_original_value);//设置DMA存储器地址,也是DMA数据传输的目标地址
  148. dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//设置DMA数据传输目标地址自增算法使能,因为DMA每个周期需要传送八个数据,所以在一个周期内,目标地址要自增
  149. dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//设置DMA从外设中读出数据的位数,因为ADC转换后的数值是12位,用16位数值表示,所以这里设置为1字
  150. dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; //设置DMA存入存储器的数据位数
  151. dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;//设置DMA的数据传输方向
  152. #if SUPPORT_2_V_GA_CHN
  153. dma_data_parameter.number = ADC_CH_N + ADC_V_CHN;
  154. #else
  155. dma_data_parameter.number = ADC_CH_N;//设置DMA一个周期要传输的数据个数,用了8个通道的ADC,所以在一个周期内要传输8个数据
  156. #endif
  157. dma_data_parameter.priority = DMA_PRIORITY_HIGH;//设置DMA数据传输高优先级
  158. dma_circulation_enable(DMA_CH0);//DMA循环模式使能,这样DMA在传输8个数据后,存储地址复位,自动开启下一轮传输
  159. dma_init(DMA_CH0, &dma_data_parameter);//初始化DMA
  160. dma_memory_to_memory_disable(DMA_CH0);//这里用不上,所以存储器到存储器DMA传输取消
  161. dma_channel_enable(DMA_CH0);//使能DMA通道
  162. }
  163. /*********************************************************************************************************
  164. * 函数名称:DC_I_calfunction
  165. * 函数功能:直流电流计算公式函数
  166. * 输入参数:uint16_t 电流的ADC值
  167. * 输出参数:uint32_t 浮点电流值(mA)
  168. * 返 回 值:uint32_t 浮点电流值(mA)
  169. * 创建日期:2024年04月06日
  170. * 注 意:12位ADC转换公式:实际电压值V = (ADC参考电压Vref * 采样数值N) / 2^12
  171. * 电流传感器转换公式:实际电流值I(A) = 实际电压值V / 灵敏度参数(V/A)
  172. * 实际计算时,让小数变成整数,最终结果扩大1000倍
  173. *********************************************************************************************************/
  174. uint32_t DC_I_calfunction(uint16_t da,uint8_t channel)
  175. {
  176. uint32_t temp_i = 0;
  177. uint32_t temp_v = 0;
  178. if(da > 0)
  179. {
  180. #if SUPPORT_STM32_ADC
  181. switch(channel)
  182. {
  183. case 0:
  184. case 1:
  185. case 4:
  186. case 5:
  187. {
  188. temp_v = da;
  189. if(da < 0xA)
  190. {
  191. temp_v = 0;
  192. }
  193. temp_v *= ADC_Vref;
  194. temp_v *= 1000;
  195. temp_v = temp_v >> 12;
  196. temp_v *= 2.5;
  197. temp_i = temp_v;
  198. temp_i /= 10;//去掉第3位小数
  199. temp_i *= 10;
  200. //temp_i += 200;
  201. if(temp_i <= 80)
  202. temp_i = 0;
  203. }
  204. break;
  205. default:
  206. {
  207. temp_v = da;
  208. temp_v *= ADC_Vref;
  209. temp_v *= 1000;
  210. temp_v = temp_v >> 12;//temp_v /= ADC_Fulscale;
  211. temp_v /= A_gain;
  212. temp_i = temp_v / I_sens;
  213. temp_i /= 10;//去掉第3位小数
  214. temp_i *= 10;
  215. temp_i += 70;
  216. if(temp_i <= 80)
  217. temp_i = 0;
  218. }
  219. }
  220. #else
  221. temp_v = da;
  222. temp_v *= ADC_Vref;
  223. temp_v *= 1000;
  224. temp_v = temp_v >> 12;//temp_v /= ADC_Fulscale;
  225. temp_v /= A_gain;
  226. temp_i = temp_v / I_sens;
  227. temp_i /= 10;//去掉第3位小数
  228. temp_i *= 10;
  229. if(temp_i < 20)
  230. temp_i = 0;
  231. #endif
  232. return temp_i;
  233. }
  234. else
  235. {
  236. return 0;
  237. }
  238. }
  239. #if SUPPORT_2_V_GA_CHN
  240. uint32_t DC_V_calfunction(uint16_t va)
  241. {
  242. uint32_t temp_i = 0;
  243. uint32_t temp_v = 0;
  244. if(va)
  245. {
  246. temp_v = va;
  247. temp_v *= ADC_Vref;
  248. temp_v *= 1000;
  249. temp_v = temp_v >> 12;
  250. temp_v *= ADC_V_Gain;
  251. temp_i = temp_v;
  252. temp_i /= 10;
  253. temp_i /= 10;
  254. return temp_i;
  255. }
  256. return 0;
  257. }
  258. //void read_voltage_val(void)
  259. //{
  260. // if(adc_sample_n < ADC_Avg_N)
  261. // {
  262. // adc_Avg_value[ADC_VOL] += adc_original_value[ADC_VOL];
  263. // adc_sample_n++;
  264. // }else
  265. // {
  266. // adc_sample_n = 0;
  267. // adc_Avg_value[ADC_VOL] = adc_Avg_value[ADC_VOL] / ADC_Avg_N;
  268. // if(adc_Avg_value[ADC_VOL] > adc_data_zero[ADC_VOL])
  269. // {
  270. // adc_Avg_value[ADC_VOL] -= adc_data_zero[ADC_VOL];
  271. // }
  272. // else
  273. // {
  274. // adc_Avg_value[ADC_VOL] = 0;
  275. // }
  276. // }
  277. //}
  278. #endif
  279. /*********************************************************************************************************
  280. * 函数名称:read_adc_val
  281. * 函数功能:读取ADC各通道的数据,并将原始值存储到缓冲区,采样ADC_Avg_N次后才计算均值
  282. * 输入参数:void
  283. * 输出参数:void
  284. * 返 回 值:void
  285. * 创建日期:2024年04月06日
  286. * 注 意:
  287. *********************************************************************************************************/
  288. #if SUPPORT_2_V_GA_CHN
  289. static uint16_t sort_buff[ADC_CH_N+ADC_V_CHN][ADC_Avg_N] = {0};
  290. #else
  291. static uint16_t sort_buff[ADC_CH_N][ADC_Avg_N] = {0};
  292. #endif
  293. static void buff_sort(uint16_t *arr,int num)
  294. {
  295. int i,j;
  296. uint16_t tmp;
  297. for(j=0; j < num;j++)
  298. {
  299. for(i =0; i < (num -j-1);i++)
  300. {
  301. if(arr[i+1] > arr[i])
  302. {
  303. tmp = arr[i+1];
  304. arr[i+1] = arr[i];
  305. arr[i] = tmp;
  306. }
  307. }
  308. }
  309. }
  310. static uint32_t calculate_all(uint16_t *arr,int num)
  311. {
  312. uint32_t temp;
  313. for(int i= 0; i < num;i++)
  314. {
  315. temp+=arr[i];
  316. }
  317. temp = (temp /num);
  318. return temp;
  319. }
  320. void read_adc_val(void)
  321. {
  322. int8_t i = 0;
  323. if(adc_sample_n < ADC_Avg_N)
  324. {
  325. for(i = 0;i < ADC_CH_N ;i++)
  326. {
  327. sort_buff[i][adc_sample_n] = adc_original_value[i];
  328. //adc_Avg_value[i] += adc_original_value[i];
  329. }
  330. #if SUPPORT_2_V_GA_CHN
  331. adc_Avg_value[ADC_VOL] += (uint16_t)(abs(adc_original_value[ADC_VOL] - adc_original_value[ADC_VOL+1]));
  332. #endif
  333. adc_sample_n++;
  334. }
  335. else
  336. {
  337. adc_sample_n = 0;
  338. for(i = 0;i < ADC_CH_N ;i++)
  339. {
  340. uint16_t *arr = &sort_buff[i][0];
  341. buff_sort(arr,ADC_Avg_N);
  342. //arr = &sort_buff[i][2];
  343. //adc_Avg_value[i] = calculate_all(arr,ADC_Avg_N);
  344. adc_Avg_value[i] = sort_buff[i][6];
  345. //adc_Avg_value[i] = adc_Avg_value[i] / ADC_Avg_N;
  346. if(adc_Avg_value[i] > adc_data_zero[i])
  347. {
  348. adc_Avg_value[i] -= adc_data_zero[i];
  349. }
  350. else
  351. {
  352. adc_Avg_value[i] = 0;
  353. }
  354. }
  355. #if SUPPORT_2_V_GA_CHN
  356. //adc_Avg_value[ADC_VOL] = adc_Avg_value[ADC_VOL] / ADC_Avg_N;
  357. uint16_t *arr = &sort_buff[ADC_VOL][0];
  358. buff_sort(arr,ADC_Avg_N);
  359. arr = &sort_buff[ADC_VOL][1];
  360. //adc_Avg_value[ADC_VOL] = calculate_all(arr,ADC_Avg_N-3);
  361. adc_Avg_value[ADC_VOL] = sort_buff[ADC_VOL][6];
  362. if(adc_Avg_value[ADC_VOL] > adc_data_zero[ADC_VOL])
  363. {
  364. adc_Avg_value[ADC_VOL] -= adc_data_zero[ADC_VOL];
  365. }
  366. else
  367. {
  368. adc_Avg_value[ADC_VOL] = 0;
  369. }
  370. #endif
  371. adc_data_ok_flag = true;
  372. }
  373. }
  374. #if NO_USE_IM1253E
  375. #endif