ADC.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include <stdbool.h>
  2. #include "ADC.h"
  3. #include "gd32e23x.h"
  4. #include "SysTick.h"
  5. #include "Timer.h"
  6. #include "math.h"
  7. #include "common.h"
  8. bool adc_data_ok_flag = false;
  9. uint8_t adc_sample_n;//采样次数
  10. uint16_t adc_original_value[ADC_CH_N]={0};//存放各通道原始值
  11. uint16_t adc_calc_value[ADC_Avg_N][ADC_CH_N];//各通道中间过程计算值
  12. uint32_t adc_Avg_value[ADC_CH_N];//存放各通道平均值
  13. uint16_t adc_data_zero[ADC_CH_N];
  14. #define CH442E_GPIO GPIOA
  15. #define CH442E_RCU RCU_GPIOA
  16. #define CH442E_IN_GPIO GPIO_PIN_15
  17. #define CH442E_EN_GPIO GPIO_PIN_12
  18. #define CHOISE_STM32_1 gpio_bit_set(CH442E_GPIO, CH442E_IN_GPIO)
  19. #define CHOISE_STM32_2 gpio_bit_reset(CH442E_GPIO, CH442E_IN_GPIO)
  20. void Init_ADC(void)
  21. {
  22. adc_sample_n = 0;
  23. ConfigADCGPIO();
  24. while(!dma_flag_get(DMA_CH0,DMA_FLAG_FTF));
  25. dma_flag_clear(DMA_CH0,DMA_FLAG_FTF);
  26. for(int i = 0;i < 8;i++)
  27. {
  28. adc_data_zero[i] = 0x149;
  29. }
  30. }
  31. void ConfigADCGPIO(void)
  32. {
  33. //使能RCU相关时钟
  34. rcu_periph_clock_enable(ADC_0_5_RCU);//使能GPIOA的时钟
  35. rcu_periph_clock_enable(ADC_67_RCU);//使能GPIOB的时钟
  36. //使能ADC时钟
  37. rcu_periph_clock_enable(RCU_ADC);
  38. //使能DMA的时钟
  39. rcu_periph_clock_enable(RCU_DMA);
  40. //配置ADC时钟
  41. rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
  42. //设置GPIO为ADC接口
  43. 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
  44. gpio_mode_set(ADC_67_IO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_ch6|ADC_ch7);
  45. //复位ADC外设
  46. adc_deinit();
  47. //配置DMA
  48. ADC_dma_config();
  49. //内部ADC配置
  50. adc_special_function_config(ADC_SCAN_MODE,ENABLE);//配置ADC扫描转换模式
  51. adc_special_function_config(ADC_CONTINUOUS_MODE,ENABLE);//配置ADC连续转换模式
  52. adc_external_trigger_source_config(ADC_REGULAR_CHANNEL,ADC_EXTTRIG_REGULAR_NONE);//配置ADC外部触发是软件触发
  53. adc_data_alignment_config(ADC_DATAALIGN_RIGHT);//配置ADC数据对齐方式是右对齐
  54. adc_resolution_config(ADC_RESOLUTION_12B);//配置ADC为12位
  55. adc_channel_length_config(ADC_REGULAR_CHANNEL, ADC_CH_N);//配置ADC规则通道组成或注入通道组的长度,因为用到8个通道,所以是8
  56. adc_regular_channel_config(0U, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);//配置ADC通道组
  57. adc_regular_channel_config(1U, ADC_CHANNEL_1, ADC_SAMPLETIME_55POINT5);
  58. adc_regular_channel_config(2U, ADC_CHANNEL_4, ADC_SAMPLETIME_55POINT5);
  59. adc_regular_channel_config(3U, ADC_CHANNEL_5, ADC_SAMPLETIME_55POINT5);
  60. adc_regular_channel_config(4U, ADC_CHANNEL_6, ADC_SAMPLETIME_55POINT5);
  61. adc_regular_channel_config(5U, ADC_CHANNEL_7, ADC_SAMPLETIME_55POINT5);
  62. adc_regular_channel_config(6U, ADC_CHANNEL_8, ADC_SAMPLETIME_55POINT5);
  63. adc_regular_channel_config(7U, ADC_CHANNEL_9, ADC_SAMPLETIME_55POINT5);
  64. adc_enable();//使能
  65. adc_enable();//使能
  66. //delay_ms(2);
  67. adc_calibration_enable();//校准复位
  68. adc_dma_mode_enable();//使能DMA
  69. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);//软件触发
  70. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
  71. //dma_interrupt_enable(DMA_CH0,DMA_INT_FTF);
  72. }
  73. void ADC_dma_config(void)
  74. {
  75. //通道参数配置
  76. dma_parameter_struct dma_data_parameter;
  77. //使能ADC时钟
  78. rcu_periph_clock_enable(RCU_ADC);
  79. //使能DMA的时钟
  80. rcu_periph_clock_enable(RCU_DMA);
  81. //复位DMA通道
  82. dma_deinit(DMA_CH0);
  83. //初始化DMA为单数据模式
  84. dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA);//设置DMA外设地址,也是DMA数据传输的源地址,ADC单次采样转换结束后,会将数据存入ADC_RDATA地址中
  85. dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//设置DMA数据传输的源地址自增算法取消,ADC每次转换后数据存入地址不变
  86. dma_data_parameter.memory_addr = (uint32_t)(adc_original_value);//设置DMA存储器地址,也是DMA数据传输的目标地址
  87. dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//设置DMA数据传输目标地址自增算法使能,因为DMA每个周期需要传送八个数据,所以在一个周期内,目标地址要自增
  88. dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//设置DMA从外设中读出数据的位数,因为ADC转换后的数值是12位,用16位数值表示,所以这里设置为1字
  89. dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; //设置DMA存入存储器的数据位数
  90. dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;//设置DMA的数据传输方向
  91. dma_data_parameter.number = ADC_CH_N;//设置DMA一个周期要传输的数据个数,用了8个通道的ADC,所以在一个周期内要传输8个数据
  92. dma_data_parameter.priority = DMA_PRIORITY_HIGH;//设置DMA数据传输高优先级
  93. dma_circulation_enable(DMA_CH0);//DMA循环模式使能,这样DMA在传输8个数据后,存储地址复位,自动开启下一轮传输
  94. dma_init(DMA_CH0, &dma_data_parameter);//初始化DMA
  95. dma_memory_to_memory_disable(DMA_CH0);//这里用不上,所以存储器到存储器DMA传输取消
  96. dma_channel_enable(DMA_CH0);//使能DMA通道
  97. }
  98. /*********************************************************************************************************
  99. * 函数名称:DC_I_calfunction
  100. * 函数功能:直流电流计算公式函数
  101. * 输入参数:uint16_t 电流的ADC值
  102. * 输出参数:uint32_t 浮点电流值(mA)
  103. * 返 回 值:uint32_t 浮点电流值(mA)
  104. * 创建日期:2024年04月06日
  105. * 注 意:12位ADC转换公式:实际电压值V = (ADC参考电压Vref * 采样数值N) / 2^12
  106. * 电流传感器转换公式:实际电流值I(A) = 实际电压值V / 灵敏度参数(V/A)
  107. * 实际计算时,让小数变成整数,最终结果扩大1000倍
  108. *********************************************************************************************************/
  109. uint32_t DC_I_calfunction(uint16_t da,uint8_t channel)
  110. {
  111. uint32_t temp_i = 0;
  112. uint32_t temp_v = 0;
  113. if(da > 0)
  114. {
  115. switch(channel)
  116. {
  117. #if SPPPORT_BIG_HAL
  118. case 0:
  119. case 1:
  120. case 4:
  121. case 5:
  122. {
  123. temp_v = da;
  124. if(da < 0xA)
  125. {
  126. temp_v = 0;
  127. }
  128. temp_v *= ADC_Vref;
  129. temp_v *= 1000;
  130. temp_v = temp_v >> 12;
  131. temp_v *= 2.5;
  132. temp_i = temp_v;
  133. temp_i /= 10;//去掉第3位小数
  134. temp_i *= 10;
  135. //temp_i += 200;
  136. if(temp_i <= 80)
  137. temp_i = 0;
  138. }
  139. break;
  140. #endif
  141. default:
  142. {
  143. temp_v = da;
  144. temp_v *= ADC_Vref;
  145. temp_v *= 1000;
  146. temp_v = temp_v >> 12;//temp_v /= ADC_Fulscale;
  147. temp_v /= A_gain;
  148. temp_i = temp_v / I_sens;
  149. temp_i /= 10;//去掉第3位小数
  150. temp_i *= 10;
  151. //temp_i += 70;
  152. if(temp_i <= 200)
  153. temp_i = 0;
  154. }
  155. }
  156. return temp_i;
  157. }
  158. else
  159. {
  160. return 0;
  161. }
  162. }
  163. static uint16_t sort_buff[ADC_CH_N][ADC_Avg_N] = {0};
  164. static void buff_sort(uint16_t *arr,int num)
  165. {
  166. int i,j;
  167. uint16_t tmp;
  168. for(j=0; j < num;j++)
  169. {
  170. for(i =0; i < (num -j-1);i++)
  171. {
  172. if(arr[i+1] > arr[i])
  173. {
  174. tmp = arr[i+1];
  175. arr[i+1] = arr[i];
  176. arr[i] = tmp;
  177. }
  178. }
  179. }
  180. }
  181. static uint32_t calculate_all(uint16_t *arr,int num)
  182. {
  183. uint32_t temp;
  184. for(int i= 0; i < num;i++)
  185. {
  186. temp+=arr[i];
  187. }
  188. temp = (temp /num);
  189. return temp;
  190. }
  191. void read_adc_val(void)
  192. {
  193. int8_t i = 0;
  194. if(adc_sample_n < ADC_Avg_N)
  195. {
  196. for(i = 0;i < ADC_CH_N ;i++)
  197. {
  198. sort_buff[i][adc_sample_n] = adc_original_value[i];
  199. }
  200. adc_sample_n++;
  201. }
  202. else
  203. {
  204. adc_sample_n = 0;
  205. for(i = 0;i < ADC_CH_N ;i++)
  206. {
  207. uint16_t *arr = &sort_buff[i][0];
  208. buff_sort(arr,ADC_Avg_N);
  209. adc_Avg_value[i] = sort_buff[i][6];
  210. if(adc_Avg_value[i] > adc_data_zero[i])
  211. {
  212. adc_Avg_value[i] -= adc_data_zero[i];
  213. }
  214. else
  215. {
  216. adc_Avg_value[i] = 0;
  217. }
  218. }
  219. adc_data_ok_flag = true;
  220. }
  221. }
  222. void che442e_Init(void)
  223. {
  224. rcu_periph_clock_enable(CH442E_RCU);
  225. gpio_mode_set(CH442E_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, CH442E_IN_GPIO | CH442E_EN_GPIO);
  226. gpio_bit_set(CH442E_GPIO, CH442E_IN_GPIO);
  227. gpio_bit_reset(CH442E_GPIO, CH442E_EN_GPIO);
  228. }
  229. void che442_change_ch(uint8_t channel)
  230. {
  231. switch(channel)
  232. {
  233. case STM32_ADC_V_1:
  234. CHOISE_STM32_1;
  235. break;
  236. case STM32_ADC_V_2:
  237. CHOISE_STM32_2;
  238. break;
  239. default:
  240. break;
  241. }
  242. }