drv_adc.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-05-16 shelton first version
  9. * 2024-07-21 liujianhua added mcxa153
  10. *
  11. */
  12. #include <rtconfig.h>
  13. #include <rtdevice.h>
  14. #include "fsl_lpadc.h"
  15. #include "fsl_spc.h"
  16. #define DBG_TAG "drv.adc"
  17. #define DBG_LVL DBG_INFO
  18. #include <rtdbg.h>
  19. #ifdef RT_USING_ADC
  20. #define DEFAULT_HW_AVG (kLPADC_HardwareAverageCount4)
  21. #define DEFAULT_SAMPLE_TIME (kLPADC_SampleTimeADCK7)
  22. /* by default: cmd = chl+1 */
  23. static uint8_t adc_chl2cmd[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  24. static uint8_t adc_cmd2trig[] = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3};
  25. struct mcx_adc
  26. {
  27. struct rt_adc_device mcx_adc_device;
  28. ADC_Type *adc_base;
  29. clock_attach_id_t clock_attach_id;
  30. clock_div_name_t clock_div_name;
  31. uint8_t clock_div;
  32. uint8_t referenceVoltageSource; /* 00, VREFH reference pin, 01, ANA_7(VREFI/VREFO) pin, 10, VDDA supply pin */
  33. uint8_t resolution;
  34. char *name;
  35. };
  36. static struct mcx_adc mcx_adc_obj[] =
  37. {
  38. #ifdef BSP_USING_ADC0
  39. {
  40. .adc_base = ADC0,
  41. .clock_attach_id = kFRO12M_to_ADC0,
  42. .clock_div_name = kCLOCK_DivADC0,
  43. .clock_div = 2,
  44. .referenceVoltageSource = 0,
  45. .name = "adc0",
  46. },
  47. #endif
  48. };
  49. static rt_err_t a153_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
  50. {
  51. struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data;
  52. if (enabled)
  53. {
  54. lpadc_config_t adc_config;
  55. LPADC_GetDefaultConfig(&adc_config);
  56. adc_config.enableAnalogPreliminary = true;
  57. adc_config.referenceVoltageSource = adc->referenceVoltageSource;
  58. adc_config.conversionAverageMode = kLPADC_ConversionAverage128; /* this is for calibartion avg mode */
  59. adc_config.powerLevelMode = kLPADC_PowerLevelAlt4;
  60. adc_config.enableConvPause = false;
  61. adc_config.convPauseDelay = 0;
  62. LPADC_Init(adc->adc_base, &adc_config);
  63. LPADC_DoOffsetCalibration(adc->adc_base);
  64. LPADC_DoAutoCalibration(adc->adc_base);
  65. lpadc_conv_command_config_t cmd_cfg;
  66. LPADC_GetDefaultConvCommandConfig(&cmd_cfg);
  67. cmd_cfg.channelNumber = channel;
  68. cmd_cfg.conversionResolutionMode = kLPADC_ConversionResolutionHigh;
  69. cmd_cfg.hardwareAverageMode = DEFAULT_HW_AVG;
  70. cmd_cfg.loopCount = 0;
  71. cmd_cfg.sampleTimeMode = DEFAULT_SAMPLE_TIME;
  72. cmd_cfg.sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
  73. LPADC_SetConvCommandConfig(adc->adc_base, adc_chl2cmd[channel], &cmd_cfg);
  74. lpadc_conversion_resolution_mode_t resolution_mode = cmd_cfg.conversionResolutionMode;
  75. if (resolution_mode == kLPADC_ConversionResolutionHigh)
  76. adc->resolution = 16;
  77. else
  78. adc->resolution = 0;
  79. lpadc_conv_trigger_config_t trig_config;
  80. LPADC_GetDefaultConvTriggerConfig(&trig_config);
  81. trig_config.targetCommandId = adc_chl2cmd[channel];
  82. trig_config.enableHardwareTrigger = false;
  83. LPADC_SetConvTriggerConfig(adc->adc_base, adc_cmd2trig[trig_config.targetCommandId], &trig_config); /* Configurate the trigger0. */
  84. }
  85. else
  86. {
  87. LPADC_Deinit(adc->adc_base);
  88. }
  89. return RT_EOK;
  90. }
  91. static rt_int16_t a153_get_vref(struct rt_adc_device *device)
  92. {
  93. if (device == RT_NULL)
  94. return -RT_ERROR;
  95. return 3300;
  96. }
  97. static rt_err_t a153_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
  98. {
  99. struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data;
  100. lpadc_conv_result_t mLpadcResultConfigStruct;
  101. LPADC_DoSoftwareTrigger(adc->adc_base, 1 << (adc_cmd2trig[adc_chl2cmd[channel]])); /* 1U is trigger0 mask. */
  102. while (!LPADC_GetConvResult(adc->adc_base, &mLpadcResultConfigStruct));
  103. *value = mLpadcResultConfigStruct.convValue;
  104. return RT_EOK;
  105. }
  106. static rt_uint8_t a153_adc_get_resolution(struct rt_adc_device *device)
  107. {
  108. RT_ASSERT(device != RT_NULL);
  109. struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data;
  110. return adc->resolution;
  111. }
  112. static const struct rt_adc_ops mcx_adc_ops =
  113. {
  114. .get_resolution = a153_adc_get_resolution,
  115. .enabled = a153_adc_enabled,
  116. .convert = a153_get_adc_value,
  117. .get_vref = a153_get_vref,
  118. };
  119. static int rt_hw_adc_init(void)
  120. {
  121. int result = RT_EOK;
  122. int i = 0;
  123. /* Enable VREF */
  124. SPC0->ACTIVE_CFG1 |= 0xFFFFFFFF;
  125. SPC_SetActiveModeBandgapModeConfig(SPC0, kSPC_BandgapEnabledBufferEnabled);
  126. for (i = 0; i < sizeof(mcx_adc_obj) / sizeof(mcx_adc_obj[0]); i++)
  127. {
  128. CLOCK_SetClockDiv(mcx_adc_obj[i].clock_div_name, mcx_adc_obj[i].clock_div);
  129. CLOCK_AttachClk(mcx_adc_obj[i].clock_attach_id);
  130. rt_hw_adc_register(&mcx_adc_obj[i].mcx_adc_device, mcx_adc_obj[i].name, &mcx_adc_ops, &mcx_adc_obj[i]);
  131. }
  132. return result;
  133. }
  134. INIT_BOARD_EXPORT(rt_hw_adc_init);
  135. #endif /* BSP_USING_ADC */