gd32_adc.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include "gd32_adc.h"
  2. #include "gpio.h"
  3. #include "clock.h"
  4. #include "libs/shark_types.h"
  5. #include "libs/shark_task.h"
  6. /* For 12-bits resolution, the total conversion time is
  7. *sampling time + 12.5 ADCCLK cycles
  8. *all channel is enabled oversample to reach 16bit accurate
  9. */
  10. static int volatile adc_work = ADC_WORK_IDLE;
  11. //#define DMA_ADC_CH DMA_CH0
  12. #ifdef DMA_ADC_CH
  13. #define dma_irq DMA_Channel0_IRQn
  14. #define dma_buf_len 66
  15. static uint16_t dma_buf[dma_buf_len];
  16. #endif
  17. int gd32_adc_error = 0;
  18. void gd32_adc_init(void){
  19. rcu_periph_clock_enable(RCU_GPIOA);
  20. rcu_periph_clock_enable(RCU_GPIOB);
  21. gpio_mode_analog_input(GPIOA, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
  22. gpio_mode_analog_input(GPIOB, GPIO_PIN_1|GPIO_PIN_0);
  23. /* config ADC clock */
  24. rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6); //adc clock:7M
  25. rcu_periph_clock_enable(RCU_ADC);
  26. adc_deinit();
  27. /* ADC trigger config */
  28. adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
  29. /* ADC data alignment config */
  30. adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
  31. /* ADC channel length config */
  32. adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
  33. adc_resolution_config(ADC_RESOLUTION_12B);
  34. //adc_special_function_config(ADC_SCAN_MODE,ENABLE);
  35. adc_discontinuous_mode_config(ADC_REGULAR_CHANNEL, 1);
  36. adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
  37. #ifdef DMA_ADC_CH
  38. dma_config();
  39. #endif
  40. }
  41. void gd32_adc_deinit(void){
  42. adc_deinit();
  43. rcu_periph_clock_disable(RCU_ADC);
  44. }
  45. #ifdef DMA_ADC_CH
  46. void dma_config(void)
  47. {
  48. /* ADC_DMA_channel configuration */
  49. dma_parameter_struct dma_data_parameter;
  50. /* ADC DMA_channel configuration */
  51. dma_deinit(DMA_ADC_CH);
  52. /* initialize DMA single data mode */
  53. dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA);
  54. dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  55. dma_data_parameter.memory_addr = (uint32_t)dma_buf;
  56. dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_DISABLE;
  57. dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
  58. dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT;
  59. dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
  60. dma_data_parameter.number = 1U;
  61. dma_data_parameter.priority = DMA_PRIORITY_HIGH;
  62. dma_init(DMA_ADC_CH, &dma_data_parameter);
  63. dma_circulation_disable(DMA_ADC_CH);
  64. dma_interrupt_enable(DMA_ADC_CH, DMA_INT_FTF);
  65. nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
  66. nvic_irq_enable(dma_irq, 4U, 0U);
  67. }
  68. /* step 1 */
  69. int adc_is_idle(void){
  70. return adc_work == ADC_WORK_IDLE;
  71. }
  72. int adc_start_sample(int chan, int number){
  73. //hardware oversample to 16bit
  74. adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
  75. adc_oversample_mode_enable();
  76. /* use max convert time to make sure the adc work fine */
  77. adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);//55.5 + 12.5 = 68 cycle, 68/(7*1000000)
  78. adc_enable();
  79. delay_us(1000); //MUST delay, for adc work fine
  80. adc_calibration_enable();
  81. DMA_CHCNT(DMA_ADC_CH) = (number & DMA_CHANNEL_CNT_MASK);
  82. dma_channel_enable(DMA_ADC_CH);
  83. /* ADC DMA function enable */
  84. adc_dma_mode_enable();
  85. /* ADC software trigger enable */
  86. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
  87. adc_work = ADC_WORK_ING;
  88. }
  89. void DMA_Channel0_IRQHandler(void){
  90. adc_disable();
  91. dma_channel_disable(DMA_ADC_CH);
  92. dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
  93. adc_work = ADC_WORK_SAMPLE_COMPLTE
  94. }
  95. int adc_is_complete(void){
  96. return adc_work == ADC_WORK_SAMPLE_COMPLTE;
  97. }
  98. int adc_get_sample(void){
  99. if (adc_work != ADC_WORK_SAMPLE_COMPLTE){
  100. return adc_work;
  101. }
  102. int value = 0;
  103. int count = DMA_CHCNT(DMA_ADC_CH) & DMA_CHANNEL_CNT_MASK;
  104. int min = 0xFFFFF;
  105. int max = -0xFFFFF;
  106. int i;
  107. for (i = 0; i < count; i++){
  108. int one = dma_buf[i];
  109. value += one;
  110. if (one > max){
  111. max = one;
  112. }
  113. if (one < min) {
  114. min = one;
  115. }
  116. }
  117. adc_work = ADC_WORK_IDLE;
  118. return (value - min - max)/(count - 2);
  119. }
  120. int adc_sample_avg(int chan, int times){
  121. int value = 0;
  122. int count = 0;
  123. int min = 0xFFFFF;
  124. int max = -0xFFFFF;
  125. if (adc_work == ADC_WORK_ING){
  126. adc_disable();
  127. dma_channel_disable(DMA_ADC_CH);
  128. adc_dma_mode_disable();
  129. dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
  130. adc_work = ADC_WORK_INTERTUPED;
  131. }
  132. //hardware oversample to 16bit
  133. adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_2B, ADC_OVERSAMPLING_RATIO_MUL64);
  134. adc_oversample_mode_enable();
  135. /* use max convert time to make sure the adc work fine */
  136. adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)
  137. adc_enable();
  138. delay_us(1000); //MUST delay, for adc work fine
  139. /* ADC calibration and reset calibration */
  140. adc_calibration_enable();
  141. while(count < times){
  142. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
  143. while(SET != adc_flag_get(ADC_FLAG_EOC));
  144. int one = adc_regular_data_read();
  145. adc_flag_clear(ADC_FLAG_EOC);
  146. value += (one & 0xFFFF);
  147. count ++;
  148. if (one > max){
  149. max = one;
  150. }
  151. if (one < min) {
  152. min = one;
  153. }
  154. }
  155. adc_disable();
  156. return (value - min - max)/(times-2);
  157. }
  158. #else
  159. int adc_sample(int chan, int calibration){
  160. int value = -0xFFFFFF;
  161. int mask = 0xFFFF;
  162. //hardware oversample to 16bit
  163. adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_2B, ADC_OVERSAMPLING_RATIO_MUL64);
  164. adc_oversample_mode_enable();
  165. /* use max convert time to make sure the adc work fine */
  166. adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);//239.5 + 12.5 = 242 cycle, 242/(28*1000000)
  167. adc_enable();
  168. delay_us(1000); //MUST delay, for adc work fine
  169. if (calibration) {
  170. /* ADC calibration and reset calibration */
  171. adc_calibration_enable();
  172. }
  173. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
  174. while(SET != adc_flag_get(ADC_FLAG_EOC));
  175. value = adc_regular_data_read();
  176. adc_flag_clear(ADC_FLAG_EOC);
  177. adc_disable();
  178. return value & mask;
  179. }
  180. static int adc_sample_internal(int chan, int times, int *error) {
  181. int value = 0;
  182. int count = 0;
  183. int min = 0xFFFFF;
  184. int max = -0xFFFFF;
  185. adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)
  186. adc_enable();
  187. delay_us(1000); //MUST delay, for adc work fine
  188. /* ADC calibration and reset calibration */
  189. adc_calibration_enable();
  190. *error = 0;
  191. while(count < times){
  192. u64 start_time = shark_get_mseconds();
  193. adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
  194. while(SET != adc_flag_get(ADC_FLAG_EOC)){
  195. if (shark_get_mseconds() - start_time >= 10){
  196. *error = -1;
  197. break;
  198. }
  199. };
  200. int one = adc_regular_data_read();
  201. adc_flag_clear(ADC_FLAG_EOC);
  202. value += (one & 0xFFF);
  203. count ++;
  204. if (one > max){
  205. max = one;
  206. }
  207. if (one < min) {
  208. min = one;
  209. }
  210. }
  211. adc_disable();
  212. if (times <= 2) {
  213. return value/times;
  214. }
  215. return (value - min - max)/(times-2);
  216. }
  217. //times * 0.6ms + 1ms
  218. int adc_sample_avg(int chan, int times){
  219. int error = 0;
  220. int value = adc_sample_internal(chan, times, &error);
  221. if (error < 0) {
  222. gd32_adc_error ++;
  223. gd32_adc_deinit();
  224. delay_us(5 * 1000);
  225. gd32_adc_init();
  226. value = adc_sample_internal(chan, times, &error);
  227. }
  228. return value;
  229. }
  230. #endif /* DMA_ADC_CH */