drv_adc.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. */
  10. #include "drv_adc.h"
  11. #include "fsl_lpadc.h"
  12. #include "fsl_spc.h"
  13. #include "fsl_common.h"
  14. #if defined(BSP_USING_ADC0) || defined(BSP_USING_ADC1)
  15. #define DEFAULT_HW_AVG (kLPADC_HardwareAverageCount4)
  16. #define DEFAULT_SAMPLE_TIME (kLPADC_SampleTimeADCK7)
  17. /* by default: cmd = chl+1 */
  18. 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};
  19. static uint8_t adc_cmd2trig[] = {0, 1, 2 ,3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3};
  20. struct mcx_adc
  21. {
  22. struct rt_adc_device mcx_adc_device;
  23. ADC_Type *adc_base;
  24. clock_attach_id_t clock_attach_id;
  25. clock_div_name_t clock_div_name;
  26. uint8_t clock_div;
  27. uint8_t referenceVoltageSource; /* 00, VREFH reference pin, 01, ANA_7(VREFI/VREFO) pin, 10, VDDA supply pin */
  28. char *name;
  29. };
  30. static struct mcx_adc mcx_adc_obj[] =
  31. {
  32. #ifdef BSP_USING_ADC0
  33. {
  34. .adc_base = ADC0,
  35. .clock_attach_id = kCLK_IN_to_ADC0,
  36. .clock_div_name = kCLOCK_DivAdc0Clk,
  37. .clock_div = 2,
  38. .referenceVoltageSource = 0,
  39. .name = "adc0",
  40. },
  41. #endif
  42. };
  43. static rt_err_t at32_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
  44. {
  45. struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data;
  46. lpadc_conv_command_config_t cmd_cfg;
  47. LPADC_GetDefaultConvCommandConfig(&cmd_cfg);
  48. cmd_cfg.channelNumber = channel;
  49. cmd_cfg.conversionResolutionMode = kLPADC_ConversionResolutionHigh;
  50. cmd_cfg.hardwareAverageMode = DEFAULT_HW_AVG;
  51. cmd_cfg.loopCount = 0;
  52. cmd_cfg.sampleTimeMode = DEFAULT_SAMPLE_TIME;
  53. /*
  54. kLPADC_SampleChannelSingleEndSideA = 0U,
  55. kLPADC_SampleChannelSingleEndSideB = 1U,
  56. kLPADC_SampleChannelDiffBothSide = 2U,
  57. kLPADC_SampleChannelDualSingleEndBothSide =
  58. */
  59. cmd_cfg.sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
  60. LPADC_SetConvCommandConfig(adc->adc_base, adc_chl2cmd[channel], &cmd_cfg);
  61. lpadc_conv_trigger_config_t trig_config;
  62. LPADC_GetDefaultConvTriggerConfig(&trig_config);
  63. trig_config.targetCommandId = adc_chl2cmd[channel];
  64. trig_config.enableHardwareTrigger = false;
  65. LPADC_SetConvTriggerConfig(adc->adc_base, adc_cmd2trig[trig_config.targetCommandId], &trig_config); /* Configurate the trigger0. */
  66. return RT_EOK;
  67. }
  68. static rt_err_t at32_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
  69. {
  70. struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data;
  71. lpadc_conv_result_t mLpadcResultConfigStruct;
  72. LPADC_DoSoftwareTrigger(adc->adc_base, 1<<(adc_cmd2trig[adc_chl2cmd[channel]])); /* 1U is trigger0 mask. */
  73. while (!LPADC_GetConvResult(adc->adc_base, &mLpadcResultConfigStruct, 0))
  74. {
  75. }
  76. *value = mLpadcResultConfigStruct.convValue;
  77. return RT_EOK;
  78. }
  79. static const struct rt_adc_ops mcx_adc_ops =
  80. {
  81. .enabled = at32_adc_enabled,
  82. .convert = at32_get_adc_value,
  83. };
  84. static int rt_hw_adc_init(void)
  85. {
  86. int result = RT_EOK;
  87. int i = 0;
  88. /* Enable VREF */
  89. SPC0->ACTIVE_CFG1 |= 0xFFFFFFFF;
  90. SPC_SetActiveModeBandgapModeConfig(SPC0, kSPC_BandgapEnabledBufferEnabled);
  91. for (i = 0; i < sizeof(mcx_adc_obj) / sizeof(mcx_adc_obj[0]); i++)
  92. {
  93. CLOCK_SetClkDiv(mcx_adc_obj[i].clock_div_name, mcx_adc_obj[i].clock_div);
  94. CLOCK_AttachClk(mcx_adc_obj[i].clock_attach_id);
  95. lpadc_config_t adc_config;
  96. LPADC_GetDefaultConfig(&adc_config);
  97. adc_config.enableAnalogPreliminary = true;
  98. adc_config.referenceVoltageSource = mcx_adc_obj[i].referenceVoltageSource;
  99. adc_config.conversionAverageMode = kLPADC_ConversionAverage128; /* this is for calibartion avg mode */
  100. adc_config.powerLevelMode = kLPADC_PowerLevelAlt4;
  101. adc_config.enableConvPause = false;
  102. adc_config.convPauseDelay = 0;
  103. LPADC_Init(mcx_adc_obj[i].adc_base, &adc_config);
  104. LPADC_DoOffsetCalibration(mcx_adc_obj[i].adc_base);
  105. LPADC_DoAutoCalibration(mcx_adc_obj[i].adc_base);
  106. rt_hw_adc_register(&mcx_adc_obj[i].mcx_adc_device, mcx_adc_obj[i].name, &mcx_adc_ops, &mcx_adc_obj[i]);
  107. }
  108. return result;
  109. }
  110. INIT_BOARD_EXPORT(rt_hw_adc_init);
  111. #endif /* BSP_USING_ADC */