1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* 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) */
/***************************************************************************//**
* @}
******************************************************************************/
|