gd32_adc.c 6.7 KB

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