概述
ADC具有温度相关偏移量,如果ADC要运行在较大的温度范围内,则开启校准会校准结果更加准确
校准方法:定期运行CALIBRATEOFFSET,硬件会自动进行校准
1 nordic提供的底层函数:
ret_code_t nrf_drv_saadc_calibrate_offset()
{
ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED);
ret_code_t err_code;
if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
{
err_code = NRF_ERROR_BUSY;
NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
//将ADC的状态设置为校准
m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION;
nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);//清除CALIBRATEDONE事件(寄存器写入0)
nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE); //使能CALIBRATEDONE 事件中断(寄存器写入1)
nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);//触发校准task(寄存器写入1)
err_code = NRF_SUCCESS;
NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION;
nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);//清除CALIBRATEDONE事件(寄存器写入0)
nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE); //使能CALIBRATEDONE 事件中断(寄存器写入1)
nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);//触发校准task(寄存器写入1)
err_code = NRF_SUCCESS;
NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
其中:ADC 状态有以下三种
typedef enum
{
NRF_SAADC_STATE_IDLE = 0,(空闲)
NRF_SAADC_STATE_BUSY = 1,(在进行ADC采集)
NRF_SAADC_STATE_CALIBRATION = 2 (ADC校准)
} nrf_saadc_state_t;
/**
* @brief Function for triggering a specific SAADC task.
*
* @param[in] saadc_task SAADC task.
*/
__STATIC_INLINE void nrf_saadc_task_trigger(nrf_saadc_task_t saadc_task)
{
*((volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_task)) = 0x1UL;
}
0x1UL;
}
#define NRF_SAADC ((NRF_SAADC_Type *) NRF_SAADC_BASE)
#define NRF_SAADC_BASE 0x40007000UL
2 上层调用:周期性调用nrf_drv_saadc_calibrate_offset()来启动ADC校准
1)温度采集线程中每2s进行一次校准,其他时间则是进行ADC数据采集及转换
void camera_temp_common_thread_main(const void *arg)
{
uint32_t calibration_counter = 0;
while (true) { //每2s校准一次
if ((calibration_counter++ % CALIBRATION_INTERVAL) == 0) {
camera_temp_calibrate();
}
//获取camera温度
for (int i = 0; i < CAMERA_NUM_SENSORS; ++i) {
const int32_t temp = camera_temp_read(i);
__atomic_store_n(&m_cached_temps[i], temp, __ATOMIC_RELAXED);
}
osDelay(TEMP_UPDATE_INTERVAL_MS);
}
}
其中:
#define TEMP_UPDATE_INTERVAL_MS 100
#define CALIBRATION_INTERVAL 20
2)校准函数调用实现
先调用底层函数nrf_drv_saadc_calibrate_offset()启动校准,然后等待校准完成,
通过判断ADC状态是否为IDLE来确定校准是否完成
void camera_temp_calibrate(void)
{
adc_calibrate();
}
void adc_calibrate(void)
{
UHAL_ASSERT(m_periph_init, "ADC not initialized");
UHAL_ASSERT(nrf_drv_saadc_calibrate_offset() == NRF_SUCCESS, "Failed to start calibration");
while (nrf_drv_saadc_is_busy()); //等待校准完成
}
; //等待校准完成
}
bool nrf_drv_saadc_is_busy(void)
{
return (m_cb.adc_state != NRF_SAADC_STATE_IDLE);
}
最后
以上就是傻傻小蘑菇为你收集整理的nRF52840 ADC校准的全部内容,希望文章能够帮你解决nRF52840 ADC校准所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复