dev_misc.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-02-22 onelife Initial creation for EFM32
  9. * 2011-07-27 onelife Modify according to ADC driver changes
  10. */
  11. /***************************************************************************//**
  12. * @addtogroup efm32
  13. * @{
  14. ******************************************************************************/
  15. /* Includes ------------------------------------------------------------------*/
  16. #include "board.h"
  17. #include "drv_adc.h"
  18. #if defined(RT_USING_MISC)
  19. /* Private typedef -----------------------------------------------------------*/
  20. /* Private define ------------------------------------------------------------*/
  21. /* Private macro -------------------------------------------------------------*/
  22. #ifdef RT_MISC_DEBUG
  23. #define misc_debug(format,args...) rt_kprintf(format, ##args)
  24. #else
  25. #define misc_debug(format,args...)
  26. #endif
  27. /* Private constants ---------------------------------------------------------*/
  28. static rt_device_t adc0;
  29. static struct efm32_adc_control_t control = \
  30. {ADC_MODE_SINGLE, {}, {0, (rt_uint8_t)EFM32_NO_DMA}};
  31. /* Private variables ---------------------------------------------------------*/
  32. /* Private function prototypes -----------------------------------------------*/
  33. rt_int32_t efm32_misc_getCelsius(rt_uint32_t adcSample);
  34. /* Private functions ---------------------------------------------------------*/
  35. /***************************************************************************//**
  36. * @brief
  37. * Get current temperature value in degree celsius
  38. *
  39. * @details
  40. *
  41. * @note
  42. *
  43. * @return
  44. * Temperature value (signed integer) in degree celsius times 100
  45. *
  46. ******************************************************************************/
  47. rt_int32_t rt_hw_get_temp(void)
  48. {
  49. ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
  50. struct efm32_adc_result_t result;
  51. rt_uint32_t temp;
  52. /* Set input to temperature sensor. Acquisition time must be 256 cycles.
  53. Reference must be 1.25V */
  54. singleInit.acqTime = adcAcqTime32;
  55. singleInit.reference = adcRef1V25;
  56. singleInit.input = adcSingleInpTemp;
  57. control.single.init = &singleInit;
  58. adc0->control(adc0, RT_DEVICE_CTRL_ADC_MODE, &control);
  59. result.mode = control.mode;
  60. result.buffer = (void *)&temp;
  61. adc0->control(adc0, RT_DEVICE_CTRL_RESUME, &result);
  62. adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &result);
  63. return efm32_misc_getCelsius(temp);
  64. }
  65. /***************************************************************************//**
  66. * @brief
  67. * Get current VDD value in volt
  68. *
  69. * @details
  70. *
  71. * @note
  72. *
  73. * @return
  74. * VDD value (unsigned integer) in volt times 100
  75. *
  76. ******************************************************************************/
  77. rt_uint32_t rt_hw_get_vdd(void)
  78. {
  79. ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
  80. struct efm32_adc_result_t result;
  81. rt_uint32_t vdd;
  82. /* Set input to temperature sensor. Reference must be 1.25V */
  83. singleInit.acqTime = adcAcqTime32;
  84. singleInit.reference = adcRef1V25;
  85. singleInit.input = adcSingleInpVDDDiv3;
  86. control.single.init = &singleInit;
  87. adc0->control(adc0, RT_DEVICE_CTRL_ADC_MODE, &control);
  88. result.mode = control.mode;
  89. result.buffer = (void *)&vdd;
  90. adc0->control(adc0, RT_DEVICE_CTRL_RESUME, &result);
  91. adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &result);
  92. return (vdd * 125 * 3) / 4096;
  93. }
  94. /***************************************************************************//**
  95. * @brief
  96. * Initialize all the miscellaneous drivers
  97. *
  98. * @details
  99. *
  100. * @note
  101. *
  102. * @return
  103. * Error code
  104. ******************************************************************************/
  105. rt_err_t rt_hw_misc_init(void)
  106. {
  107. do
  108. {
  109. /* Find ADC device */
  110. adc0 = rt_device_find(RT_ADC0_NAME);
  111. if (adc0 == RT_NULL)
  112. {
  113. misc_debug("Misc err: Can't find device: %s!\n", RT_ADC0_NAME);
  114. break;
  115. }
  116. misc_debug("Misc: Find device %s\n", RT_ADC0_NAME);
  117. return RT_EOK;
  118. } while (0);
  119. misc_debug("Misc err: Init failed!\n");
  120. return -RT_ERROR;
  121. }
  122. /***************************************************************************//**
  123. * @brief
  124. * Convert ADC result to degree celsius.
  125. *
  126. * @details
  127. *
  128. * @note
  129. * See section 2.3.4 in the reference manual for details on this calculatoin
  130. *
  131. * @param adcResult
  132. * Raw value from ADC to be converted to celsius
  133. *
  134. * @return
  135. * The temperature value (signed integer) in degrees celsius times 100
  136. *
  137. ******************************************************************************/
  138. rt_int32_t efm32_misc_getCelsius(rt_uint32_t adcResult)
  139. {
  140. /* Factory calibration temperature from device information page. */
  141. rt_int32_t cal_temp = ((DEVINFO->CAL & _DEVINFO_CAL_TEMP_MASK) \
  142. >> _DEVINFO_CAL_TEMP_SHIFT) * 100;
  143. /* Factory calibration value from device information page. */
  144. rt_int32_t cal_value = ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_TEMP1V25_MASK) \
  145. >> _DEVINFO_ADC0CAL2_TEMP1V25_SHIFT) * 10000;
  146. /* Temperature gradient (from datasheet) in (ADC unit / degree celsius * 100) */
  147. rt_int32_t t_grad = -385;
  148. return (cal_temp - (cal_value - (rt_int32_t)adcResult * 10000) / t_grad);
  149. }
  150. /*******************************************************************************
  151. * Export to FINSH
  152. ******************************************************************************/
  153. #ifdef RT_USING_FINSH
  154. #include <finsh.h>
  155. void list_temp(void)
  156. {
  157. rt_int32_t temp = rt_hw_get_temp();
  158. rt_kprintf("Temperature is %2d.%02d C\n", temp / 100, temp % 100);
  159. }
  160. FINSH_FUNCTION_EXPORT(list_temp, list current temperature value.)
  161. void list_vdd(void)
  162. {
  163. rt_uint32_t vdd = rt_hw_get_vdd();
  164. rt_kprintf("VDD is %1d.%02d V\n", vdd / 100, vdd % 100);
  165. }
  166. FINSH_FUNCTION_EXPORT(list_vdd, list current VDD value.)
  167. #endif /* RT_USING_FINSH */
  168. #endif /* defined(RT_USING_MISC) */
  169. /***************************************************************************//**
  170. * @}
  171. ******************************************************************************/