Hello,
I'm using BL654 module (nrf52840 inside); SDK15; softdevice s140; IAR.
In my projects I'm using peripherals: I2C(TWI), SPI. Project based on ble_app_uart example (most of sdk_config.h are default, exept TWI/SPI instances and timer3)
My goal is to add sampling data from 4 analog input channels:

Channel 1 - input 0;
Channel 2 - input 5;
Channel 3 - input 4;
Channel 4 - input 7;
My code for SAADC:
#define SAMPLES_IN_BUFFER 4
#define BUFFERS_IN_CH 2
#define SAADC_SAMPLE_PERIOR_MS 1000
volatile uint8_t state = 1;
static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(3);
static nrf_saadc_value_t m_buffer_pool[BUFFERS_IN_CH][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t m_ppi_channel;
static uint32_t m_adc_evt_counter;
void timer_handler(nrf_timer_event_t event_type, void * p_context)
{
//
}
void saadc_sampling_event_init(void)
{
ret_code_t err_code;
err_code = nrf_drv_ppi_init();
APP_ERROR_CHECK(err_code);
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
APP_ERROR_CHECK(err_code);
// setup m_timer for compare event every X ms
uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, SAADC_SAMPLE_PERIOR_MS);
nrf_drv_timer_extended_compare(&m_timer,
NRF_TIMER_CC_CHANNEL3,
ticks,
NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK,
false);
nrf_drv_timer_enable(&m_timer);
uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
NRF_TIMER_CC_CHANNEL3);
uint32_t saadc_sample_task_addr = nrf_drv_saadc_sample_task_get();
// setup ppi channel so that timer compare event is triggering sample task in SAADC
err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
timer_compare_event_addr,
saadc_sample_task_addr);
APP_ERROR_CHECK(err_code);
}
void saadc_sampling_event_enable(void)
{
ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
APP_ERROR_CHECK(err_code);
}
void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
ret_code_t err_code;
// set buffers
err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
APP_ERROR_CHECK(err_code);
// print samples on hardware UART and parse data for BLE transmission
NRF_LOG_INFO("ADC event number: %d\r\n",(int)m_adc_evt_counter);
for (int i = 0; i < SAMPLES_IN_BUFFER; i++)
{
NRF_LOG_INFO("CH_[%d] adc_value: %d\r\n", i, p_event->data.done.p_buffer[i]);
}
m_adc_evt_counter++;
}
}
void saadc_init(void)
{
ret_code_t err_code;
nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
nrf_saadc_channel_config_t channel_1_config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
nrf_saadc_channel_config_t channel_2_config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
nrf_saadc_channel_config_t channel_3_config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
nrf_saadc_channel_config_t channel_4_config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_channel_init(0, &channel_1_config);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_channel_init(5, &channel_2_config);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_channel_init(4, &channel_3_config);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_channel_init(7, &channel_4_config);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAMPLES_IN_BUFFER);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER);
APP_ERROR_CHECK(err_code);
}
void SAADC_Init(void)
{
saadc_sampling_event_init();
saadc_init();
saadc_sampling_event_enable();
}
Main(removed stuff with TWI and SPI):
int main(void)
{
uart_init();
log_init();
timers_init();
power_management_init();
ble_stack_init();
//printf("ble_stack started...\r\n");
gap_params_init();
gatt_init();
services_init();
advertising_init();
conn_params_init();
SAADC_Init();
// Start execution.
advertising_start();
// Enter main loop.
for (;;)
{
idle_state_handle();
}
}
Problem:
Channel's position numbers doest match their positions in output. And sometimes hopping in arrays...
For example, I'm shorting AIN0 (channel #1) to GND and thats what I see under debug:

AIN5 (channel #2):

AIN4 (channel #3):

AIN7 (channel #4):

And one more things I would like to ask:
Since TIMER0 is used by softdevice, I'm using TIMER3 for SAADC. Am I correct that in saadc_sampling_event_init() I shoud compare events/adresses for TIMER3?

Regards