drv_adc.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /**************************************************************************//**
  2. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-9-16 Philo First version
  9. *
  10. ******************************************************************************/
  11. #include <rtconfig.h>
  12. #include <rtdevice.h>
  13. #include "NuMicro.h"
  14. #ifdef BSP_USING_ADC
  15. /* Private define ---------------------------------------------------------------*/
  16. /* Private Typedef --------------------------------------------------------------*/
  17. struct nu_adc
  18. {
  19. struct rt_adc_device dev;
  20. char *name;
  21. ADC_T *adc_base;
  22. int adc_reg_tab;
  23. int adc_max_ch_num;
  24. };
  25. typedef struct nu_adc *nu_adc_t;
  26. /* Private functions ------------------------------------------------------------*/
  27. static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled);
  28. static rt_err_t nu_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value);
  29. /* Public functions ------------------------------------------------------------*/
  30. int rt_hw_adc_init(void);
  31. /* Private variables ------------------------------------------------------------*/
  32. static struct nu_adc nu_adc_arr [] =
  33. {
  34. #if defined(BSP_USING_ADC0)
  35. {
  36. .name = "adc0",
  37. .adc_base = ADC,
  38. .adc_max_ch_num = 15,
  39. },
  40. #endif
  41. {0}
  42. };
  43. static const struct rt_adc_ops nu_adc_ops =
  44. {
  45. nu_adc_enabled,
  46. nu_get_adc_value,
  47. };
  48. typedef struct rt_adc_ops *rt_adc_ops_t;
  49. /* nu_adc_enabled - Enable ADC clock and wait for ready */
  50. static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
  51. {
  52. ADC_T *adc_base = ((nu_adc_t)device)->adc_base;
  53. int *padc_reg_tab = &((nu_adc_t)device)->adc_reg_tab;
  54. RT_ASSERT(device != RT_NULL);
  55. if (channel >= ((nu_adc_t)device)->adc_max_ch_num)
  56. return -(RT_EINVAL);
  57. if (enabled)
  58. {
  59. ADC_POWER_ON(adc_base);
  60. if (*padc_reg_tab == 0)
  61. {
  62. ADC_Open(adc_base, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE, (0x1 << channel));
  63. }
  64. *padc_reg_tab |= (0x1 << channel);
  65. }
  66. else
  67. {
  68. *padc_reg_tab &= ~(0x1 << channel);
  69. if (*padc_reg_tab == 0)
  70. {
  71. ADC_Close(adc_base);
  72. }
  73. ADC_POWER_DOWN(adc_base);
  74. }
  75. return RT_EOK;
  76. }
  77. static rt_err_t nu_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
  78. {
  79. RT_ASSERT(device != RT_NULL);
  80. RT_ASSERT(value != RT_NULL);
  81. ADC_T *adc_base = ((nu_adc_t)device)->adc_base;
  82. int *padc_reg_tab = &((nu_adc_t)device)->adc_reg_tab;
  83. if (channel >= ((nu_adc_t)device)->adc_max_ch_num)
  84. {
  85. *value = 0xFFFFFFFF;
  86. return -(RT_EINVAL);
  87. }
  88. if ((*padc_reg_tab & (1 << channel)) == 0)
  89. {
  90. *value = 0xFFFFFFFF;
  91. return -(RT_EBUSY);
  92. }
  93. ADC_SET_INPUT_CHANNEL(adc_base, (0x1<<channel));
  94. ADC_CLR_INT_FLAG(adc_base, ADC_ADF_INT);
  95. ADC_ENABLE_INT(adc_base, ADC_ADF_INT);
  96. ADC_START_CONV(adc_base);
  97. while (ADC_GET_INT_FLAG(adc_base, ADC_ADF_INT) == 0);
  98. *value = ADC_GET_CONVERSION_DATA(adc_base, channel);
  99. return RT_EOK;
  100. }
  101. int rt_hw_adc_init(void)
  102. {
  103. rt_err_t result = RT_ERROR;
  104. int nu_sel = 0;
  105. while (nu_adc_arr[nu_sel].name != 0)
  106. {
  107. nu_adc_arr[nu_sel].adc_reg_tab = 0;
  108. result = rt_hw_adc_register(&nu_adc_arr[nu_sel].dev, nu_adc_arr[nu_sel].name, &nu_adc_ops, NULL);
  109. RT_ASSERT(result == RT_EOK);
  110. nu_sel++;
  111. }
  112. return (int)result;
  113. }
  114. INIT_BOARD_EXPORT(rt_hw_adc_init);
  115. #endif //#if defined(BSP_USING_ADC)