drv_adc.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-02-25 iysheng first version
  9. * 2022-04-13 wangh adc init and convert bug fix
  10. */
  11. #include <board.h>
  12. #ifdef RT_USING_ADC
  13. #define DBG_TAG "drv.adc"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. #define MAX_EXTERN_ADC_CHANNEL 16
  17. typedef struct
  18. {
  19. struct rt_adc_device adc_dev;
  20. char name[8];
  21. rt_base_t adc_pins[16];
  22. void *private_data;
  23. } gd32_adc_device;
  24. static gd32_adc_device adc_devs[] = {
  25. #ifdef BSP_USING_ADC0
  26. {
  27. .name = "adc0",
  28. .adc_pins = {
  29. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  30. GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
  31. GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
  32. GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5),
  33. },
  34. .private_data = (void *)ADC0,
  35. },
  36. #endif
  37. #ifdef BSP_USING_ADC1
  38. {
  39. .name = "adc1",
  40. .adc_pins = {
  41. GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
  42. GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
  43. GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
  44. GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5),
  45. },
  46. .private_data = (void *)ADC1,
  47. },
  48. #endif
  49. };
  50. static void gd32_adc_gpio_init(rt_base_t pin)
  51. {
  52. rcu_periph_clock_enable((rcu_periph_enum)PIN_GDRCU(pin));
  53. gpio_init(PIN_GDPORT(pin), GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, PIN_GDPIN(pin));
  54. }
  55. static rt_err_t drv_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
  56. {
  57. if ((device == NULL) || (channel >= MAX_EXTERN_ADC_CHANNEL))
  58. {
  59. LOG_E("invalid channel\r\n");
  60. return -RT_EINVAL;
  61. }
  62. gd32_adc_device *gd32_adc = (gd32_adc_device *)device;
  63. uint32_t adc_periph = (uint32_t )(device->parent.user_data);
  64. if (enabled == ENABLE)
  65. {
  66. gd32_adc_gpio_init(gd32_adc->adc_pins[channel]);
  67. adc_deinit(adc_periph);
  68. adc_channel_length_config(adc_periph, ADC_REGULAR_CHANNEL, 1);
  69. adc_data_alignment_config(adc_periph, ADC_DATAALIGN_RIGHT); /* 数据右对齐 */
  70. adc_external_trigger_config(adc_periph, ADC_REGULAR_CHANNEL, ENABLE); /* 规则组外部触发使能 */
  71. adc_external_trigger_source_config(adc_periph, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);
  72. adc_special_function_config(adc_periph, ADC_SCAN_MODE, DISABLE); /* 扫描模式禁止,单通道模式 */
  73. adc_special_function_config(adc_periph, ADC_CONTINUOUS_MODE, DISABLE); /* 连续转换禁止,单次转换模式 */
  74. adc_discontinuous_mode_config(adc_periph, ADC_REGULAR_CHANNEL, 1); /* 规则组间断使能及转换通道数目 */
  75. adc_enable(adc_periph);
  76. rt_hw_us_delay(500);
  77. adc_calibration_enable(adc_periph); /* ADC自校准 */
  78. }
  79. else
  80. {
  81. adc_disable(adc_periph);
  82. }
  83. return 0;
  84. }
  85. static rt_err_t drv_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
  86. {
  87. if ((device == NULL) || (channel >= MAX_EXTERN_ADC_CHANNEL) || (value == NULL))
  88. {
  89. LOG_E("invalid param\r\n");
  90. return -RT_EINVAL;
  91. }
  92. uint32_t adc_periph = (uint32_t )(device->parent.user_data);
  93. adc_regular_channel_config(adc_periph, 0, channel, ADC_SAMPLETIME_239POINT5);
  94. adc_software_trigger_enable(adc_periph, ADC_REGULAR_CHANNEL);
  95. while(!adc_flag_get(adc_periph, ADC_FLAG_EOC)); /* 等待ADC转换完成 */
  96. adc_flag_clear(adc_periph, ADC_FLAG_EOC); /* 清除转换完成标志位 */
  97. adc_flag_clear(adc_periph, ADC_FLAG_STRC);
  98. *value = adc_regular_data_read(adc_periph);
  99. return 0;
  100. }
  101. static struct rt_adc_ops drv_adc_ops = {
  102. .enabled = drv_adc_enabled,
  103. .convert = drv_adc_convert,
  104. };
  105. static int rt_hw_adc_init(void)
  106. {
  107. int ret, i = 0;
  108. #ifdef BSP_USING_ADC0
  109. rcu_periph_clock_enable(RCU_ADC0);
  110. #endif
  111. #ifdef BSP_USING_ADC1
  112. rcu_periph_clock_enable(RCU_ADC1);
  113. #endif
  114. rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6); /* 72/6 = 12MHz need < 14MHZ */
  115. adc_mode_config(ADC_MODE_FREE);
  116. for (; i < sizeof(adc_devs) / sizeof(gd32_adc_device); i++)
  117. {
  118. ret = rt_hw_adc_register(&adc_devs[i].adc_dev,
  119. (const char *)adc_devs[i].name,
  120. &drv_adc_ops, (void *)adc_devs[i].private_data);
  121. if (ret != RT_EOK)
  122. {
  123. /* TODO err handler */
  124. LOG_E("failed register %s, err=%d\r\n", adc_devs[i].name, ret);
  125. }
  126. }
  127. return ret;
  128. }
  129. INIT_BOARD_EXPORT(rt_hw_adc_init);
  130. #endif