/***************************************************************************//** * @file dev_misc.c * @brief Miscellaneous driver of RT-Thread RTOS for EFM32 * COPYRIGHT (C) 2012, RT-Thread Development Team * @author onelife * @version 1.0 ******************************************************************************* * @section License * The license and distribution terms for this file may be found in the file * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE ******************************************************************************* * @section Change Logs * Date Author Notes * 2011-02-22 onelife Initial creation for EFM32 * 2011-07-27 onelife Modify according to ADC driver changes ******************************************************************************/ /***************************************************************************//** * @addtogroup efm32 * @{ ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "board.h" #include "drv_adc.h" #if defined(RT_USING_MISC) /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ #ifdef RT_MISC_DEBUG #define misc_debug(format,args...) rt_kprintf(format, ##args) #else #define misc_debug(format,args...) #endif /* Private constants ---------------------------------------------------------*/ static rt_device_t adc0; static struct efm32_adc_control_t control = \ {ADC_MODE_SINGLE, {}, {0, (rt_uint8_t)EFM32_NO_DMA}}; /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ rt_int32_t efm32_misc_getCelsius(rt_uint32_t adcSample); /* Private functions ---------------------------------------------------------*/ /***************************************************************************//** * @brief * Get current temperature value in degree celsius * * @details * * @note * * @return * Temperature value (signed integer) in degree celsius times 100 * ******************************************************************************/ rt_int32_t rt_hw_get_temp(void) { ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; struct efm32_adc_result_t result; rt_uint32_t temp; /* Set input to temperature sensor. Acquisition time must be 256 cycles. Reference must be 1.25V */ singleInit.acqTime = adcAcqTime32; singleInit.reference = adcRef1V25; singleInit.input = adcSingleInpTemp; control.single.init = &singleInit; adc0->control(adc0, RT_DEVICE_CTRL_ADC_MODE, &control); result.mode = control.mode; result.buffer = (void *)&temp; adc0->control(adc0, RT_DEVICE_CTRL_RESUME, &result); adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &result); return efm32_misc_getCelsius(temp); } /***************************************************************************//** * @brief * Get current VDD value in volt * * @details * * @note * * @return * VDD value (unsigned integer) in volt times 100 * ******************************************************************************/ rt_uint32_t rt_hw_get_vdd(void) { ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; struct efm32_adc_result_t result; rt_uint32_t vdd; /* Set input to temperature sensor. Reference must be 1.25V */ singleInit.acqTime = adcAcqTime32; singleInit.reference = adcRef1V25; singleInit.input = adcSingleInpVDDDiv3; control.single.init = &singleInit; adc0->control(adc0, RT_DEVICE_CTRL_ADC_MODE, &control); result.mode = control.mode; result.buffer = (void *)&vdd; adc0->control(adc0, RT_DEVICE_CTRL_RESUME, &result); adc0->control(adc0, RT_DEVICE_CTRL_ADC_RESULT, &result); return (vdd * 125 * 3) / 4096; } /***************************************************************************//** * @brief * Initialize all the miscellaneous drivers * * @details * * @note * * @return * Error code ******************************************************************************/ rt_err_t rt_hw_misc_init(void) { do { /* Find ADC device */ adc0 = rt_device_find(RT_ADC0_NAME); if (adc0 == RT_NULL) { misc_debug("Misc err: Can't find device: %s!\n", RT_ADC0_NAME); break; } misc_debug("Misc: Find device %s\n", RT_ADC0_NAME); return RT_EOK; } while (0); misc_debug("Misc err: Init failed!\n"); return -RT_ERROR; } /***************************************************************************//** * @brief * Convert ADC result to degree celsius. * * @details * * @note * See section 2.3.4 in the reference manual for details on this calculatoin * * @param adcResult * Raw value from ADC to be converted to celsius * * @return * The temperature value (signed integer) in degrees celsius times 100 * ******************************************************************************/ rt_int32_t efm32_misc_getCelsius(rt_uint32_t adcResult) { /* Factory calibration temperature from device information page. */ rt_int32_t cal_temp = ((DEVINFO->CAL & _DEVINFO_CAL_TEMP_MASK) \ >> _DEVINFO_CAL_TEMP_SHIFT) * 100; /* Factory calibration value from device information page. */ rt_int32_t cal_value = ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_TEMP1V25_MASK) \ >> _DEVINFO_ADC0CAL2_TEMP1V25_SHIFT) * 10000; /* Temperature gradient (from datasheet) in (ADC unit / degree celsius * 100) */ rt_int32_t t_grad = -385; return (cal_temp - (cal_value - (rt_int32_t)adcResult * 10000) / t_grad); } /******************************************************************************* * Export to FINSH ******************************************************************************/ #ifdef RT_USING_FINSH #include <finsh.h> void list_temp(void) { rt_int32_t temp = rt_hw_get_temp(); rt_kprintf("Temperature is %2d.%02d C\n", temp / 100, temp % 100); } FINSH_FUNCTION_EXPORT(list_temp, list current temperature value.) void list_vdd(void) { rt_uint32_t vdd = rt_hw_get_vdd(); rt_kprintf("VDD is %1d.%02d V\n", vdd / 100, vdd % 100); } FINSH_FUNCTION_EXPORT(list_vdd, list current VDD value.) #endif /* RT_USING_FINSH */ #endif /* defined(RT_USING_MISC) */ /***************************************************************************//** * @} ******************************************************************************/