本文主要是介绍52832 3通道ADC笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
因为业务需要, 需要在52832上, 采集3个pin的电压.
52832的ADC, 分为什么single, 连续, 扫描模式
single就是只有一个通道并采集一次, 连续就是不停的扫描, 如果要捕捉声音之类, 就配合DMA, 连续不停的采集, 转换就行了.
扫描模式就是如果是多通道, 就一开始初始化多个通道, 存放数据的数组, 以及采样次数, 然后全扫, 扫完回调中去拿数据即可.
初始化:
// 初始化SAADC,配置使用的SAADC通道的参数和缓存
void saadc_3c_init(void) {ret_code_t err_code;// 使用NRF_SAADC_INPUT_AIN7通道,即P0.31引脚, 生成一个通道配置结构体nrf_saadc_channel_config_t channel_config = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);err_code = nrf_drv_saadc_init(NULL, saadc_callback);APP_ERROR_CHECK(err_code);// 初始化ADC通道0err_code = nrfx_saadc_channel_init(0, &channel_config);APP_ERROR_CHECK(err_code);// 为NRF_SAADC_INPUT_AIN5, 初始化ADC 通道1channel_config.pin_p = NRF_SAADC_INPUT_AIN5;err_code = nrfx_saadc_channel_init(1, &channel_config);// 为NRF_SAADC_INPUT_AIN6, 初始化ADC 通道2APP_ERROR_CHECK(err_code);channel_config.pin_p = NRF_SAADC_INPUT_AIN6;err_code = nrfx_saadc_channel_init(2, &channel_config);APP_ERROR_CHECK(err_code);// 双缓存模式err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0], ADC_SAMPLES_BUFFER_LEN);APP_ERROR_CHECK(err_code);err_code = nrfx_saadc_buffer_convert(m_buffer_pool[1], ADC_SAMPLES_BUFFER_LEN);APP_ERROR_CHECK(err_code);}
这里使用的是双缓存模式, 采样的数据量为ADC_SAMPLES_BUFFER_LEN, 因为是3个通道, 所以采样3次就行了, 或者你喜欢浪费时间, 采样3的倍数也可以,如果不是3的倍数, 就会出现数据错位.
注册的回调时saadc_callback
这里使用的是非阻塞模式, 因为毕竟有蓝牙, 你阻塞好像不是那么回事.
// SAADC事件回调函数,只有一个缓存填满后才会进入事件回调函数
static void saadc_callback(nrfx_saadc_evt_t const *p_event) {float val; // 保存SAADC采样数据计算的实际电压值if (p_event->type == NRFX_SAADC_EVT_DONE) {ret_code_t err_code;// 设置好缓存,为下一次采样准备err_code = nrfx_saadc_buffer_convert(p_event->data.done.p_buffer, ADC_SAMPLES_BUFFER_LEN);APP_ERROR_CHECK(err_code);int i;// 串口输出ADC采样值。// NRF_LOG_INFO("ADC event number: %d \n", (int) m_adc_evt_counter);for (i = 0; i < ADC_SAMPLES_BUFFER_LEN; i++) {// 如果直接输出采样结果,使用这个代码int16_t adc_result = p_event->data.done.p_buffer[i];// NRF_LOG_INFO("Sample value: %d \n", adc_result);// 电压值 = 采样值 * 3.6 /2^10// val = p_event->data.done.p_buffer[i] * 3.6 / 1024;// NRF_LOG_INFO("Voltage = %.3fV\n", val);}uint8_t batVolPercentage = get_battery_percentage(p_event->data.done.p_buffer[0]);NRF_LOG_INFO("batVolPercentage:%d \n", batVolPercentage);dis_battery_level_update_handle(batVolPercentage);// 事件次数加1m_adc_evt_counter++;}
}
回调中, 先转换, 然后就可以打印每个数据的内容, 查看adc的采样值. 并根据业务需要, 比如把adc值转成mv为单位的电压值, 然后做char值修改等等.
static uint8_t get_battery_percentage(nrf_saadc_value_t adc_result) {uint16_t batt_lvl_in_milli_volts;batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) + DIODE_FWD_VOLT_DROP_MILLIVOLTS;NRF_LOG_INFO("battery = %d mv \n\r", batt_lvl_in_milli_volts);return bat_mini_volt_to_percentage(batt_lvl_in_milli_volts);
}
这里是adc转mv, 下面是我老板写的, mv转百分数.
// 针对4.2伏特锂电池的点亮百分比算法.
uint8_t bat_mini_volt_to_percentage(uint16_t mvolts) {uint8_t battery_level;if (mvolts >= 4200) {battery_level = 100;} else if (mvolts > 3720) {battery_level = 100 - (4200 - mvolts) / 6;} else if (mvolts > 3200) {battery_level = 20 - (3720 - mvolts) / 26;} else {battery_level = 0;}return battery_level;
}
原谅有这么多魔术数字, 你自己写的时候可不能这样哦…
这篇关于52832 3通道ADC笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!