I've seen various threads here with sample code attached that show how to set up a timer to measure a battery voltage periodically. They also seem to use an external crystal for greater accuracy.
What if I need neither of them? How do I do a single shot measurement of the voltage on an ADC pin right now? Have tried the below code without success. A breakpoint in my ADC_IRQHandler() function is never reached.
Here's my battery_level.c:
#include "nrf_gpio.h"
#include "nrf_soc.h"
void battery_level_init(void)
{
// Enable interrupt on ADC data ready event.
NRF_ADC->INTENSET = ADC_INTENSET_END_Msk;
sd_nvic_SetPriority(ADC_IRQn, NRF_APP_PRIORITY_LOW);
sd_nvic_EnableIRQ(ADC_IRQn);
NRF_ADC->CONFIG = (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos) // We don't have any external reference pins.
| (ADC_CONFIG_PSEL_AnalogInput2 << ADC_CONFIG_PSEL_Pos) // Use analog input 2.
| (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) // Use internal 1.2V bandgap voltage as reference for conversion.
| (ADC_CONFIG_INPSEL_AnalogInputNoPrescaling << ADC_CONFIG_INPSEL_Pos) // No prescaling.
| (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos); // 8 bit resolution.
// Enable ADC
NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
}
void battery_level_read(void)
{
// Start ADC sampling.
NRF_ADC->TASKS_START = 1;
}
// Interrupt handler for ADC data ready event.
void ADC_IRQHandler(void)
{
// Clear data ready event
NRF_ADC->EVENTS_END = 0; // <-- Breakpoint here is never reached.
// TODO: Put this in a global variable somewhere: NRF_ADC->RESULT
// Use the STOP task to save current. Workaround for PAN_028 rev1.5 anomaly 1.
NRF_ADC->TASKS_STOP = 1;
}
And in main():
int main(void)
{
battery_level_init();
battery_level_read();
for (;;)
{
}
}
I've also tried this with the BLE stack in play and softdevice enabled. Same result.