Nordic nRF5 SDK 学习笔记之十三, SAADC

样例: ~\nRF5_SDK_15.2.0_9412b96\examples\peripheral\saadc


1. ADC 功能块图

2. ADC 计算公式

3. 于 sdk_config.h 中配置, 以及添加 nrfx_saadc.c 文件

4. nrf_drv_saadc_init 初始化

__STATIC_INLINE ret_code_t nrf_drv_saadc_init(nrf_drv_saadc_config_t const * p_config,
                                              nrf_drv_saadc_event_handler_t  event_handler)
{
    if (p_config == NULL)
    {
        static const nrfx_saadc_config_t default_config = NRFX_SAADC_DEFAULT_CONFIG;
        p_config = &default_config;
    }
    return nrfx_saadc_init(p_config, event_handler);
}

--------------------------------------------------------
#define NRFX_SAADC_DEFAULT_CONFIG                                               \
{                                                                               \
    .resolution         = (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION, \
    .oversample         = (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE, \
    .interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY,                       \
    .low_power_mode     = NRFX_SAADC_CONFIG_LP_MODE                             \
}

--------------------------------------------------------
typedef enum
{
    NRF_SAADC_RESOLUTION_8BIT  = SAADC_RESOLUTION_VAL_8bit,  ///< 8 bit resolution.
    NRF_SAADC_RESOLUTION_10BIT = SAADC_RESOLUTION_VAL_10bit, ///< 10 bit resolution.
    NRF_SAADC_RESOLUTION_12BIT = SAADC_RESOLUTION_VAL_12bit, ///< 12 bit resolution.
    NRF_SAADC_RESOLUTION_14BIT = SAADC_RESOLUTION_VAL_14bit  ///< 14 bit resolution.
} nrf_saadc_resolution_t;

?! 在使用 NRFX_SAADC_DEFAULT_CONFIG 配置时, 不管 sdk_config.h 中设备为 8,10,12,14位时, ADC 解析率始终为 10 bits!

5. ADC 通道配置

    nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
//		channel_config.gain = NRF_SAADC_GAIN1;		

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);
------------------------------------------------------------------
默认通道配置

#define NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
{                                                   \
    .resistor_p = NRF_SAADC_RESISTOR_DISABLED,      \
    .resistor_n = NRF_SAADC_RESISTOR_DISABLED,      \
    .gain       = NRF_SAADC_GAIN1_6,                \   增益: 1/6
    .reference  = NRF_SAADC_REFERENCE_INTERNAL,     \   内部参考电压: 0.6V
    .acq_time   = NRF_SAADC_ACQTIME_10US,           \
    .mode       = NRF_SAADC_MODE_SINGLE_ENDED,      \   模式: 单端
    .burst      = NRF_SAADC_BURST_DISABLED,         \
    .pin_p      = (nrf_saadc_input_t)(PIN_P),       \
    .pin_n      = NRF_SAADC_INPUT_DISABLED          \
}

6. 单次 ADC 转换 nrf_drv_saadc_sample_convert()

#define nrf_drv_saadc_sample_convert    nrfx_saadc_sample_convert

函数原型
nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value)
{
    nrfx_err_t err_code;

    if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
    {
        err_code = NRFX_ERROR_BUSY;
        NRFX_LOG_WARNING("Function: %s error code: %s.",
                         __func__,
                         NRFX_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }
    m_cb.adc_state = NRF_SAADC_STATE_BUSY;
    nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
    nrf_saadc_buffer_init(p_value, 1);
    if (m_cb.active_channels > 1)
    {
        for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
        {
            nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
        }
    }
    nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln);
    nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
    nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);

    bool result;
    NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_END), HW_TIMEOUT, 0, result);
    NRFX_ASSERT(result);

    nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
    nrf_saadc_event_clear(NRF_SAADC_EVENT_END);

    NRFX_LOG_INFO("Conversion value: %d, channel %d.", *p_value, channel);

    if (m_cb.active_channels > 1)
    {
        for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
        {
            nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln);
        }
    }

    if (m_cb.low_power_mode)
    {
        nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
    }
    else
    {
        nrf_saadc_int_enable(NRF_SAADC_INT_END);
    }

    m_cb.adc_state = NRF_SAADC_STATE_IDLE;

    err_code = NRFX_SUCCESS;
    NRFX_LOG_WARNING("Function: %s, error code: %s.",
                     __func__,
                     NRFX_LOG_ERROR_STRING_GET(err_code));
    return err_code;
}

7. 配置 EasyDMA

#define nrf_drv_saadc_buffer_convert    nrfx_saadc_buffer_convert

nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size)

-----------------------------------------------------------------
example:

#define SAMPLES_IN_BUFFER 5
static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];

nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);

8. SAADC 正式采集函数

#define nrf_drv_saadc_sample            nrfx_saadc_sample

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是使用Nordic nRF5 SDK创建新的BLE服务的详细示例: 1. 首先,在nRF5 SDK中打开“examples\ble_peripheral\ble_app_template”示例。 2. 在“ble_app”文件夹中,打开“ble_srv_common.h”文件。此文件包含了一些常用的BLE服务定义,你可以通过阅读该文件来了解BLE服务的实现方式。 3. 在“ble_app”文件夹中,打开“ble_srv_common.c”文件。此文件包含了一些常用的BLE服务实现代码,你可以通过阅读该文件来了解BLE服务的实现方式。 4. 在“ble_app”文件夹中,创建一个新的文件夹,命名为“my_service”。 5. 在“my_service”文件夹中,创建一个新的文件,命名为“my_service.h”。在该文件中,你需要定义你的自定义BLE服务的UUID,以及相关的特性和属性等信息。例如: ``` #ifndef MY_SERVICE_H #define MY_SERVICE_H #include "ble.h" #include "ble_srv_common.h" #define BLE_UUID_MY_SERVICE 0x1234 // 自定义服务的UUID // 自定义服务的特性UUID #define BLE_UUID_MY_SERVICE_CHARACTERISTIC 0x5678 // 自定义服务的特性值结构体 typedef struct { uint8_t value; } ble_my_service_characteristic_t; // 自定义服务的事件结构体 typedef struct { ble_my_service_characteristic_t char_value; } ble_my_service_evt_t; // 自定义服务的事件句柄类型 typedef void (*ble_my_service_evt_handler_t) (ble_my_service_evt_t * p_evt); // 自定义服务的初始化函数 uint32_t ble_my_service_init(void); // 自定义服务的事件注册函数 void ble_my_service_evt_handler_register(ble_my_service_evt_handler_t evt_handler); #endif // MY_SERVICE_H ``` 6. 在“my_service”文件夹中,创建一个新的文件,命名为“my_service.c”。在该文件中,你需要实现你的自定义BLE服务的初始化、事件处理等功能。例如: ``` #include "my_service.h" static uint16_t m_service_handle; // 自定义服务的句柄 static ble_gatts_char_handles_t m_char_handles; // 自定义服务的特性句柄 static ble_my_service_evt_handler_t m_evt_handler; // 自定义服务的事件处理函数 // 自定义服务的事件回调函数 static void my_service_evt_handler(ble_evt_t const * p_ble_evt) { switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: break; case BLE_GAP_EVT_DISCONNECTED: break; case BLE_GATTS_EVT_WRITE: if (p_ble_evt->evt.gatts_evt.params.write.handle == m_char_handles.value_handle) { ble_my_service_evt_t evt; evt.char_value.value = p_ble_evt->evt.gatts_evt.params.write.data[0]; m_evt_handler(&evt); } break; default: break; } } // 自定义服务的事件注册函数 void ble_my_service_evt_handler_register(ble_my_service_evt_handler_t evt_handler) { m_evt_handler = evt_handler; } // 自定义服务的初始化函数 uint32_t ble_my_service_init(void) { uint32_t err_code; ble_uuid_t ble_uuid; ble_uuid128_t base_uuid = {BLE_UUID_MY_SERVICE_BASE}; // 生成自定义服务的UUID err_code = sd_ble_uuid_vs_add(&base_uuid, &ble_uuid.type); VERIFY_SUCCESS(err_code); ble_uuid.uuid = BLE_UUID_MY_SERVICE; // 添加自定义服务 err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &m_service_handle); VERIFY_SUCCESS(err_code); // 添加自定义服务的特性 ble_gatts_char_md_t char_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.read = 1; char_md.char_props.write = 1; ble_gatts_attr_md_t attr_md; memset(&attr_md, 0, sizeof(attr_md)); attr_md.read_perm = BLE_GAP_CONN_SEC_MODE_OPEN; attr_md.write_perm = BLE_GAP_CONN_SEC_MODE_OPEN; attr_md.vloc = BLE_GATTS_VLOC_STACK; ble_uuid_t char_uuid; char_uuid.uuid = BLE_UUID_MY_SERVICE_CHARACTERISTIC; char_uuid.type = ble_uuid.type; ble_gatts_attr_t attr; memset(&attr, 0, sizeof(attr)); attr.p_uuid = &char_uuid; attr.p_attr_md = &attr_md; attr.init_len = sizeof(ble_my_service_characteristic_t); attr.max_len = sizeof(ble_my_service_characteristic_t); attr.p_value = NULL; err_code = sd_ble_gatts_characteristic_add(m_service_handle, &char_md, &attr, &m_char_handles); VERIFY_SUCCESS(err_code); // 注册事件回调函数 err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_GENERIC_TAG); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) DEVICE_NAME, strlen(DEVICE_NAME)); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, TX_POWER); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_SCAN_INIT, 0, TX_POWER); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, 0, TX_POWER); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_ppcp_set(&ppcp); VERIFY_SUCCESS(err_code); return NRF_SUCCESS; } ``` 7. 在“main.c”文件中,包含“my_service.h”头文件,并在初始化函数中调用“ble_my_service_init()”函数来初始化你的自定义BLE服务。例如: ``` #include "my_service.h" int main(void) { uint32_t err_code; // 初始化BLE协议栈 ble_stack_init(); // 初始化GAP参数 gap_params_init(); // 初始化GATT参数 gatt_init(); // 初始化自定义服务 err_code = ble_my_service_init(); APP_ERROR_CHECK(err_code); // 启动广播 advertising_start(); // 进入主循环 for (;;) { idle_state_handle(); } } ``` 到此为止,我们已经完成了一个简单的自定义BLE服务的创建实例。你可以根据自己的需要修改“my_service.h”和“my_service.c”文件,来实现更加复杂的自定义BLE服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值