drv_adc.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2022-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-01-22 chasel first version
  9. * 2025-02-10 chasel fix adc calibration did not clear flag bits
  10. */
  11. #include <rtdevice.h>
  12. #include "board.h"
  13. #include "drv_adc.h"
  14. #include <hal_gpio.h>
  15. #include <hal_adc.h>
  16. #include <hal_rcc.h>
  17. #include <hal_misc.h>
  18. #if defined(BSP_USING_ADC)
  19. struct mm32_adc
  20. {
  21. struct rt_adc_device mm32_adc_device;
  22. ADC_TypeDef *adc_x;
  23. char *name;
  24. };
  25. #if defined(BSP_USING_ADC1)
  26. struct mm32_adc mm32_adc1_config = {
  27. .adc_x = ADC1,
  28. .name = "adc1",
  29. };
  30. #endif /* BSP_USING_ADC1 */
  31. #if defined(BSP_USING_ADC2)
  32. struct mm32_adc mm32_adc2_config = {
  33. .adc_x = ADC2,
  34. .name = "adc2",
  35. };
  36. #endif /* BSP_USING_ADC2 */
  37. static void ADCxChannelEnable(ADC_TypeDef* ADCn, rt_uint32_t channel)
  38. {
  39. ADCn->ADCHS &= ~(1 << channel);
  40. ADCn->ADCHS |= (1 << channel);
  41. }
  42. static rt_err_t mm32_adc_init(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
  43. {
  44. ADC_InitTypeDef ADC_InitStruct;
  45. ADC_TypeDef *adc_x;
  46. RT_ASSERT(device != RT_NULL);
  47. adc_x = device->parent.user_data;
  48. if (enabled) {
  49. mm32_msp_adc_init((void *)adc_x);
  50. ADC_CalibrationConfig(adc_x, 0x1FE);
  51. ADC_StructInit(&ADC_InitStruct);
  52. ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
  53. ADC_InitStruct.ADC_Prescaler = ADC_Prescaler_16; //ADC prescale factor
  54. ADC_InitStruct.ADC_Mode = ADC_Mode_Scan; //Set ADC mode to scan conversion mode
  55. ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; //AD data right-justified
  56. ADC_Init(adc_x, &ADC_InitStruct);
  57. ADC_SampleTimeConfig(adc_x, channel, ADC_SampleTime_240_5);
  58. ADC_ChannelCmd(adc_x, channel, ENABLE);
  59. ADC_DifferentialConversionConfig(adc_x, ADC_Pseudo_Differential_Conversion_4_5);
  60. ADC_Cmd(adc_x, ENABLE);
  61. } else {
  62. #if defined(BSP_USING_ADC1)
  63. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE); //disable ADC1 clock
  64. #endif /* BSP_USING_ADC1 */
  65. #if defined(BSP_USING_ADC2)
  66. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, DISABLE); //disable ADC2 clock
  67. #endif /* BSP_USING_ADC2 */
  68. ADC_DeInit(adc_x);
  69. ADC_Cmd(adc_x, DISABLE);
  70. }
  71. return RT_EOK;
  72. }
  73. static rt_err_t mm32_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
  74. {
  75. ADC_TypeDef *adc_x;
  76. RT_ASSERT(device != RT_NULL);
  77. adc_x = device->parent.user_data;
  78. ADC_SoftwareStartConvCmd(adc_x, ENABLE);
  79. while(ADC_GetFlagStatus(adc_x, ADC_FLAG_EOC) == 0);
  80. ADC_ClearFlag(adc_x, ADC_FLAG_EOC);
  81. *value = ADC_GetChannelConvertedValue(adc_x, channel);
  82. return RT_EOK;
  83. }
  84. static rt_uint8_t mm32_adc_get_resolution(struct rt_adc_device *device)
  85. {
  86. ADC_TypeDef *adc_x = device->parent.user_data;
  87. RT_ASSERT(device != RT_NULL);
  88. switch( ((adc_x->ADCFG)&(0x00000380)) )
  89. {
  90. case ADC_Resolution_12b:
  91. return 12;
  92. case ADC_Resolution_11b:
  93. return 11;
  94. case ADC_Resolution_10b:
  95. return 10;
  96. case ADC_Resolution_9b:
  97. return 9;
  98. case ADC_Resolution_8b:
  99. return 8;
  100. default:
  101. return 12;
  102. }
  103. }
  104. static rt_int16_t mm32_adc_get_vref(struct rt_adc_device *device)
  105. {
  106. if(device == RT_NULL)
  107. return -RT_ERROR;
  108. return 3300;
  109. }
  110. static const struct rt_adc_ops mm32_adc_ops =
  111. {
  112. .enabled = mm32_adc_init,
  113. .convert = mm32_get_adc_value,
  114. .get_resolution = mm32_adc_get_resolution,
  115. .get_vref = mm32_adc_get_vref,
  116. };
  117. int rt_hw_adc_init(void)
  118. {
  119. #if defined(BSP_USING_ADC1)
  120. rt_hw_adc_register(&mm32_adc1_config.mm32_adc_device, mm32_adc1_config.name, &mm32_adc_ops, mm32_adc1_config.adc_x);
  121. #endif /* BSP_USING_ADC1 */
  122. #if defined(BSP_USING_ADC2)
  123. rt_hw_adc_register(&mm32_adc2_config.mm32_adc_device, mm32_adc2_config.name, &mm32_adc_ops, mm32_adc2_config.adc_x);
  124. #endif /* BSP_USING_ADC2 */
  125. return RT_EOK;
  126. }
  127. INIT_BOARD_EXPORT(rt_hw_adc_init);
  128. #endif /* BSP_USING_ADC */