drv_adc.c 5.0 KB

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