nrf52840 adc

简介

本文介绍如何在nrf52840上使用adc。

环境

1、zephyr v3.5.99

2、nrf connect sdk v2.6.1

具体操作
编写设备树
/ {

	zephyr,user {
        io-channels = <&adc 2>;
    };

};


&adc {
    #address-cells = <1>;
    #size-cells = <0>;

    channel@2 {
        reg = <2>;
        zephyr,gain = "ADC_GAIN_1_6";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,vref-mv = <600>;
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,input-positive = <NRF_SAADC_AIN2>;
        zephyr,resolution = <12>;
        zephyr,oversampling = <4>;
    };
};
编写驱动代码
#include "adc.h"  // 包含 ADC 相关头文件
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>

#if !DT_NODE_EXISTS(DT_NODELABEL(adc))
#error "No suitable ADC devicetree node found"
#endif

// ADC 原始值缓冲区
static uint16_t raw_val_buf;

// ADC 信息结构体
adc_info_t adc_info = {
    .adc_channel = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0),
    .sequence = {
        .buffer = &raw_val_buf,
        .buffer_size = sizeof(raw_val_buf),
    }
};

/**
 * @description: 初始化自定义 ADC
 * @param: info 指向 adc_info_t 结构体的指针
 * @return: 0 表示成功,-1 表示失败
 */
int custom_adc_init(adc_info_t* info)
{
    int err;

    /* 在采样之前单独配置通道 */
    if (!adc_is_ready_dt(&info->adc_channel)) {
        printk("ADC controller device %s not ready\n", info->adc_channel.dev->name);
        return -1;
    }

    err = adc_channel_setup_dt(&info->adc_channel);
    if (err < 0) {
        printk("Could not setup channel (%d)\n", err);
        return -1;
    }

    err = adc_sequence_init_dt(&info->adc_channel, &info->sequence);
    if (err < 0) {
        printk("Could not init sequence (%d)\n", err);
        return -1;
    }

    return 0;
}

/**
 * @description: 读取自定义 ADC 值
 * @param: info 指向 adc_info_t 结构体的指针
 * @return: 0 表示成功,-1 表示失败
 */
int custom_adc_read(adc_info_t* info)
{
    int err = 0;
    int32_t val_mv;

    printk("- %s, channel %d: ",
           info->adc_channel.dev->name,
           info->adc_channel.channel_id);

    err = adc_read_dt(&info->adc_channel, &info->sequence);
    if (err < 0) {
        // 返回 -22 表示提供的参数值无效
        printk("Could not read (%d)\n", err);
        return -1;
    }

    /*
     * 如果使用差分模式,ADC 采样缓冲区中的 16 位值
     * 应该是一个有符号的 2's 补码值。
     */
    if (info->adc_channel.channel_cfg.differential) {
        val_mv = (int32_t)((int16_t)raw_val_buf);
    } else {
        val_mv = (int32_t)raw_val_buf;
    }

    //printk("%"PRId32, val_mv);

    err = adc_raw_to_millivolts_dt(&info->adc_channel, &val_mv);
    /* 如果不支持转换到 mV, 则跳过 */
    if (err < 0) {
        printk(" (value in mV not available)\n");
    } else {
        printk(" = %"PRId32" mV\n", val_mv);
        info->val_mv = val_mv;
    }

    return 0;
}
编写应用代码
int main(void)
{
	int err = 0;
	int rc = 0;
	char temp[50];

	err = custom_ble_init();
	if (err) {
		LOG_ERR("Failed to initialize BLE (err: %d)", err);
	}
	else k_sem_give(&ble_init_ok);

	custom_adc_init(&adc_info);
	for (;;) {

		k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));

		custom_adc_read(&adc_info);
		temp[0] = adc_info.val_mv/1000;
		temp[0] <<= 4;
		temp[0] |= adc_info.val_mv%1000/100;
		temp[1] = adc_info.val_mv%100/10;
		temp[1] <<= 4;
		temp[1] |= adc_info.val_mv%10;
		if (bt_custom_send(NULL, temp, 2)) {
			LOG_WRN("Failed to send adc data over BLE connection");
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值