Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bsp/nrf5x/libraries/drivers/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ if GetDepend(['BSP_USING_SPI']):

if GetDepend(['BSP_USING_GPIO']):
src += ['drv_gpio.c']

if GetDepend(['BSP_USING_SAADC']):
src += ['drv_adc.c']

if GetDepend(['BSP_USING_PWM']):
src += ['drv_pwm.c']
Expand Down
261 changes: 261 additions & 0 deletions bsp/nrf5x/libraries/drivers/drv_adc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-08-18 guohp1128 the first version
*/

#include "drv_adc.h"

#ifdef RT_USING_ADC

struct rt_adc_device nrf5x_adc_device;

drv_nrfx_saadc_result_t results;
nrf_saadc_value_t result_buff_cache[8];

static void nrf5x_saadc_event_hdr(nrfx_saadc_evt_t const * p_event)
{
uint8_t i,j;
if(p_event->type == NRFX_SAADC_EVT_DONE)
{
j = 0;
for(i = 0; i < 8; i++)
{
if(results.channels[i].channel_index == i)
{
results.result_buffer[i] = result_buff_cache[j];
j ++;
}
}
results.done = 1;
}
}

static uint32_t get_channels_mask(void)
{
uint8_t i;
uint32_t mask = 0;
for(i = 0; i < 8; i++)
{
if(results.channels[i].channel_index != 0xff)
{
mask |= (1 << results.channels[i].channel_index);
}
}
return mask;
}

static void set_channels(drv_nrfx_saadc_channel_t * channel)
{
uint8_t i;
if(channel -> mode == NRF_SAADC_MODE_SINGLE_ENDED)
{
results.channels[channel->channel_num] = (nrfx_saadc_channel_t)NRFX_SAADC_DEFAULT_CHANNEL_SE(channel -> pin_p + 1, channel -> channel_num);
}
else if(channel -> mode == NRF_SAADC_MODE_DIFFERENTIAL)
{
results.channels[channel->channel_num] = (nrfx_saadc_channel_t)NRFX_SAADC_DEFAULT_CHANNEL_DIFFERENTIAL(channel -> pin_p + 1, channel -> pin_n + 1, channel -> channel_num);
}
results.channel_count = 0;
for(i = 0; i < 8; i++)
{
if(results.channels[i].channel_index != 0xff)
{
results.channel_count ++;
}
}
}

/* channel: 0-7 */
static rt_err_t nrf5x_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
{
nrfx_err_t err_code = NRFX_SUCCESS;
uint8_t i,j;

if (enabled)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->parent.user_data != RT_NULL);

drv_nrfx_saadc_channel_t * drv_channel_config = NULL;
drv_channel_config = (drv_nrfx_saadc_channel_t *)device->parent.user_data;

set_channels(drv_channel_config);

nrfx_saadc_channel_t channels_cache[results.channel_count];

j = 0;
for(i = 0; i < 8; i++)
{
if(results.channels[i].channel_index != 0xff)
{
channels_cache[j] = results.channels[i];
j ++;
}
}

err_code = nrfx_saadc_channels_config(channels_cache,results.channel_count);

err_code = nrfx_saadc_simple_mode_set(get_channels_mask(),
NRF_SAADC_RESOLUTION_12BIT,
NRF_SAADC_OVERSAMPLE_DISABLED,
nrf5x_saadc_event_hdr);

err_code = nrfx_saadc_buffer_set(result_buff_cache, results.channel_count);
}
else
{
results.channels[channel].channel_index = 0xff;

results.channel_count = 0;
for(i = 0; i < 8; i++)
{
if(results.channels[i].channel_index != 0xff)
{
results.channel_count ++;
}
}

if(results.channel_count == 0)
{
nrfx_saadc_channel_t channels_cache[1];
err_code = nrfx_saadc_channels_config(channels_cache, 0);
return err_code;
}
else
{
nrfx_saadc_channel_t channels_cache[results.channel_count];

j = 0;
for(i = 0; i < 8; i++)
{
if(results.channels[i].channel_index != 0xff)
{
channels_cache[j] = results.channels[i];
j ++;
}
}

err_code = nrfx_saadc_channels_config(channels_cache,results.channel_count);

err_code = nrfx_saadc_simple_mode_set(get_channels_mask(),
NRF_SAADC_RESOLUTION_12BIT,
NRF_SAADC_OVERSAMPLE_DISABLED,
nrf5x_saadc_event_hdr);

err_code = nrfx_saadc_buffer_set(result_buff_cache, results.channel_count);
}
}

return err_code;
}

static rt_err_t nrf5x_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
nrfx_err_t err_code = NRFX_SUCCESS;

if (results.channels[channel].channel_index != 0xff)
{
results.done = 0;
err_code = nrfx_saadc_mode_trigger();
while(results.done == 0)
{
;
}
* value = results.result_buffer[channel];
results.done = 0;
}

return err_code;
}

static const struct rt_adc_ops nrf5x_adc_ops =
{
.enabled = nrf5x_adc_enabled,
.convert = nrf5x_get_adc_value,
};

int rt_hw_adc_init(void)
{
int result = RT_EOK;
uint8_t i;
char name_buf[6] = {'S', 'A', 'A', 'D', 'C', 0};

for(i = 0; i < 8; i++)
{
results.channels[i].channel_index = 0xff;
results.result_buffer[i] = 0;
results.channel_count = 0;
results.done = 0;
}

/* initializing SAADC interrupt priority */
if (nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY) != NRFX_SUCCESS)
{
rt_kprintf("%s init failed", name_buf);
rt_kprintf("The driver is already initialized.");
result = -RT_ERROR;
}
else
{
/* register ADC device */
if (rt_hw_adc_register(&nrf5x_adc_device, name_buf, &nrf5x_adc_ops, nrf5x_adc_device.parent.user_data) == RT_EOK)
{
rt_kprintf("%s init success", name_buf);
}
else
{
rt_kprintf("%s register failed", name_buf);
result = -RT_ERROR;
}
}
return result;
}
INIT_BOARD_EXPORT(rt_hw_adc_init);


/*test saadc*/
#include <drv_adc.h>

void saadc_sample(void)
{
drv_nrfx_saadc_channel_t channel_config;
rt_uint32_t result;

rt_adc_device_t adc_dev;
adc_dev = (rt_adc_device_t)rt_device_find("SAADC");
adc_dev->parent.user_data = &channel_config;

channel_config = (drv_nrfx_saadc_channel_t){.mode = 0, .pin_p = 1, .pin_n = 1, .channel_num = 0};
rt_adc_enable(adc_dev, channel_config.channel_num);

channel_config = (drv_nrfx_saadc_channel_t){.mode = 0, .pin_p = 2, .pin_n = 1, .channel_num = 1};
rt_adc_enable(adc_dev, channel_config.channel_num);

channel_config = (drv_nrfx_saadc_channel_t){.mode = 0, .pin_p = 7, .pin_n = 1, .channel_num = 5};
rt_adc_enable(adc_dev, channel_config.channel_num);

int count = 1;
while(count++)
{
result = rt_adc_read(adc_dev, 0);
rt_kprintf("saadc channel 0 value = %d, ",result);

result = rt_adc_read(adc_dev, 1);
rt_kprintf("saadc channel 1 value = %d, ",result);

result = rt_adc_read(adc_dev, 5);
rt_kprintf("saadc channel 5 value = %d",result);

rt_kprintf("\r\n");
rt_thread_mdelay(1000);
}
}
MSH_CMD_EXPORT(saadc_sample, saadc sample);

#endif /* RT_USING_ADC */

46 changes: 46 additions & 0 deletions bsp/nrf5x/libraries/drivers/drv_adc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-08-18 guohp1128 the first version
*/

#ifndef __DRV_ADC_H__
#define __DRV_ADC_H__

#include <board.h>
#include "rtdevice.h"
#include <hal/nrf_saadc.h>
#include <drivers/include/nrfx_saadc.h>

/*
previous definition in application

set single-ended mode or differential mode.
selection ADC input pin, and config the number of Channel.

mode: 0 single-ended mode,1 differential mode
pin_p: 0-7
pin_n: 0-7,if single-ended mode, pin_n invalid
channel_num: 0-7
*/
typedef struct
{
nrf_saadc_mode_t mode; ///< SAADC mode. Single-ended or differential.
uint8_t pin_p; ///< Input positive pin selection.
uint8_t pin_n; ///< Input negative pin selection.
uint8_t channel_num; ///< Channel number.
} drv_nrfx_saadc_channel_t;

typedef struct
{
nrfx_saadc_channel_t channels[8];
uint8_t channel_count;
nrf_saadc_value_t result_buffer[8];
uint8_t done;
} drv_nrfx_saadc_result_t;

#endif /* __DRV_ADC_H__ */
Loading