1 使用nordic库实现 nRF52832ADC采集的一个例子
https://www.cnblogs.com/zzu-liulei/p/6519141.html
2 用nRF52840自带的ADC采集camera内部的温度
原理图:
3 思路:
1).camera内部的热敏电阻与上拉电阻分压1.8V
2). 通过nRF52840自带ADC采集电压
3). 根据分压关系及热敏电阻与温度的关系,得到camera内部温度
4 公式推导
两个公式,一个可以从热敏电阻规格书中得到(热敏电阻与温度的关系),另一个是分压关系,
从而得到温度与电压的关系
5 代码实现(五个camera)
1) 初始化:初始化ADC,并对每路ADC初始化对应的pin脚及给出参考电压
在源码中给了7路ADC,而我们只用到其中5路,源码pin脚定义涉及到所以pin脚,而我们只关心ADC对应的pin脚,
这样可以使用定义数组的方式来定义专门针对ADC
源码ADC定义
typedef enum {
NRF52_ADC_0,
NRF52_ADC_1,
NRF52_ADC_2,
NRF52_ADC_3,
NRF52_ADC_4,
NRF52_ADC_5,
NRF52_ADC_6,
NRF52_ADC_7,
NUM_NRF52_ADCS
} adc_t;
源码pin脚定义
typedef enum {
NRF52_GPIO_PIN_0_0,
NRF52_GPIO_PIN_0_1,
NRF52_GPIO_PIN_0_2,
NRF52_GPIO_PIN_0_3,
。
。
。
NRF52_GPIO_PIN_0_28,
NRF52_GPIO_PIN_0_29,
NRF52_GPIO_PIN_0_30,
NRF52_GPIO_PIN_0_31,
#if defined(NRF52840_XXAA) || defined(NRF52840_XXBB)
NRF52_GPIO_PIN_1_0,
NRF52_GPIO_PIN_1_1,
NRF52_GPIO_PIN_1_2,
。
。
。
NRF52_GPIO_PIN_1_14,
NRF52_GPIO_PIN_1_15,
#endif
NUM_NRF52_GPIO_PINS,
NRF52_GPIO_PIN_UNUSED
} gpio_pin_t;
自定义数组如下:
const adc_t TEMP_ADCS[CAMERA_NUM_SENSORS] = {
CAM0_TEMP_ADC,
CAM1_TEMP_ADC,
CAM2_TEMP_ADC,
CAM3_TEMP_ADC,
CAM4_TEMP_ADC,
};
const gpio_pin_t TEMP_PINS[CAMERA_NUM_SENSORS] = {
GPIO_PIN_CAM0_TEMP,
GPIO_PIN_CAM1_TEMP,
GPIO_PIN_CAM2_TEMP,
GPIO_PIN_CAM3_TEMP,
GPIO_PIN_CAM4_TEMP,
};
其中
#define CAMERA_NUM_SENSORS 5
#define CAM0_TEMP_ADC NRF52_ADC_0
#define CAM1_TEMP_ADC NRF52_ADC_1
#define CAM2_TEMP_ADC NRF52_ADC_5
#define CAM3_TEMP_ADC NRF52_ADC_6
#define CAM4_TEMP_ADC NRF52_ADC_7
#define GPIO_PIN_CAM0_TEMP NRF52_GPIO_PIN_0_2
#define GPIO_PIN_CAM1_TEMP NRF52_GPIO_PIN_0_3
#define GPIO_PIN_CAM2_TEMP NRF52_GPIO_PIN_0_29
#define GPIO_PIN_CAM3_TEMP NRF52_GPIO_PIN_0_30
#define GPIO_PIN_CAM4_TEMP NRF52_GPIO_PIN_0_31
初始化:
void camera_temp_init(void)
{
// initialize the ADC for each camera temperature sensor
for (int i = 0; i < CAMERA_NUM_SENSORS; i++) {
const adc_init_t init_adc = {
.gpio_pin = TEMP_PINS[i],
.reference_voltage_mv = 1800,
};
adc_init(TEMP_ADCS[i], &init_adc);
}
}
adc_init_t init_adc = {
.gpio_pin = TEMP_PINS[i],
.reference_voltage_mv = 1800,
};
adc_init(TEMP_ADCS[i], &init_adc);
}
}
其中:
typedef struct {
//! \brief The GPIO pin to connect to the ADC
gpio_pin_t gpio_pin;
//! \brief The reference (max) voltage for the ADC in mV
uint32_t reference_voltage_mv;
} adc_init_t;
adc_init_t;
2)电压采集:根据采集到的ADC数据值,换算成电压
比如MCU是12位,然后参考电压是1800mv,那么,当MCU采出来的ADC值是2^12时,对应的电压是1800mv,
则,当MCU采出的ADC值为 X 时,对应的电压为 X*1800/(2^12)
uint32_t adc_get_value(adc_t adc)
{
static nrf_saadc_value_t sample;
APP_ERROR_CHECK(nrf_drv_saadc_sample_convert(adc, &sample));
uint32_t result = (sample < 0) ? 0 : sample;
// convert result into mV
return result * MAX_VOLTAGE_MV/ ADC_MAX_VALUE;
}
其中:
#define ADC_MAX_VALUE (1 << 12)
#define MAX_VOLTAGE_MV 1800
3)根据电压,得到五个camera温度
即将上面推导的电压与温度的关系写成代码实现
static int16_t temp_mv_to_deg_c(uint32_t value_mv)
{
float temp_sample = 0;
temp_sample = (RESISTENCEUP * 1.0) / RESISTENCENORMAL; //R/R0
temp_sample = temp_sample * value_mv / (REFERENCEVOLTAGE - value_mv);//* V/(VDD-V)
temp_sample = log(temp_sample);
temp_sample /= BCOEFFICIENT; // /B
temp_sample *= TEMPERATURENOMINAL; // *(T0+273.15)
temp_sample = TEMPERATURENOMINAL / (temp_sample+1); //T
temp_sample -= ABSOLUTEZERO; // -273.15
return temp_sample + 0.5;
}
其中:
#define TEMPERATURENOMINAL (25+273.15)
#define RESISTENCENORMAL (100)
#define RESISTENCEUP (51)
#define REFERENCEVOLTAGE (1800)
#define BCOEFFICIENT (4250)
#define ABSOLUTEZERO (273.15)
注意点:
1 上面代码紫色部分必须要乘以1.0,才能得到浮点数0.51,否则得到的数值为0
因为:整型/整型=整型,而无法得到浮点型
即 51/100 = 0 ; 而51*1.0/100 = 0.51
2 最后标蓝色部分对最后温度值进行四舍五入,因为要得到一个整型的温度值
4)更新camera温度
static int16_t read_temp_sensor(uint8_t camera_id)
{
UHAL_ASSERT(camera_id < CAMERA_NUM_SENSORS, "Invalid camera index");
const uint32_t value_mv = adc_get_value(TEMP_ADCS[camera_id]);
return temp_mv_to_deg_c(value_mv);
}
void camera_temp_update(void)
{
for (int i = 0; i < CAMERA_NUM_SENSORS; ++i) {
int16_t t = read_temp_sensor(i);
__atomic_store_n(&m_cached_temps[i], &t, __ATOMIC_RELAXED);
}
}
其中:
static int16_t m_cached_temps[CAMERA_NUM_SENSORS] = {0};
__atomic_store_n是原子队列,将获取的温度值t,依次存到缓存区数组中,相当于一个缓存区存储,如果用这个温度值的时候,从这个缓存区中将温度值取出来
int16_t camera_temp_get(uint8_t camera_id)
{
UHAL_ASSERT(camera_id < CAMERA_NUM_SENSORS, "Invalid camera index");
return __atomic_load_n(&m_cached_temps[camera_id], __ATOMIC_RELAXED);
}