【RT-Thread】nxp rt10xx 设备驱动框架之--adc搭建和使用

ADC(Analog-to-Digital Converter) 指模数转换器。将模拟电压信号转换成数字信号,通常ADC接口会连接一些传感器,如:温度传感器;陀螺仪加速度计;电位器等等。

开发前准备

  • 硬件平台:nxp rt10xx单片机
  • IDE: Keil

1.Kconfig 修改和menuconfig配置

Env环境menuconfigRT-Thread Components->Device Drivers 设备驱动默认为n,所以需要开启。

请添加图片描述

先在Kconfig中添加如下语句,然后在Env环境menuconfigHardware Drivers Config->On-Chip Peripheral Drivers 使能ADC

请添加图片描述

2.工程添加ADC驱动框架和BSP驱动接口

设备驱动框架:adc.c BSP接口:drv_adc.c fsl_adc.c fsl_adc_etc.c(imxrt 特有功能,本章用不到)

请添加图片描述

3.添加或修改drv_adc.c

笔者查阅了文件,发现 drv_adc.c 这个文件,只写了很初级的adc查询的方法,这种方式简单,适用于比较单一的adc项目。实际在应用中我们通常会采用中断方式,或者adc dma这样会让整个系统更加灵活,系统也不会等待adc状态消耗cpu资源。补充一下:imxrt系列 的adc,可使用adc etc结合外设pit 和 xbara触发转换,本章不会添加这些,后期有时间,再去完善drv_adc.c 和 adc.c文件,暂时使用现成已经写好的框架文件。

  • 定义rtc adc device
struct rt_adc_ops
{
    rt_err_t (*enabled)(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled);
    rt_err_t (*convert)(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value);
};

struct rt_adc_device
{
    struct rt_device parent;
    const struct rt_adc_ops *ops;
};

static struct rt_adc_ops imxrt_adc_ops =
{
    .enabled = imxrt_hp_adc_enabled,
    .convert = imxrt_hp_adc_convert,
};
  • 设备创建注册

这里笔者只简单修改了一点,采样精度改成10bit,降低一些功耗吧,具体看项目来,另外新增硬件平均

int rt_hw_adc_init(void)
{
    int result = RT_EOK;

#if defined(BSP_USING_ADC1)

    ADC_GetDefaultConfig(&ADC1_config_value);
    ADC1_config_value.resolution = kADC_Resolution10Bit; 
    ADC_Init(ADC1, &ADC1_config_value);

#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
    ADC_EnableHardwareTrigger(ADC1, false);
#endif

	ADC_SetHardwareAverageConfig(ADC1, kADC_HardwareAverageCount16); 

    ADC_DoAutoCalibration(ADC1);

    result = rt_hw_adc_register(&adc1_device, "adc1", &imxrt_adc_ops, ADC1);

    if (result != RT_EOK)
    {
        LOG_E("register adc1 device failed error code = %d\n", result);
    }

#endif /* BSP_USING_ADC1 */

#if defined(BSP_USING_ADC2)

    ADC_GetDefaultConfig(&ADC2_config_value);
    ADC_Init(ADC2, &ADC2_config_value);

#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
    ADC_EnableHardwareTrigger(ADC2, false);
#endif
    ADC_DoAutoCalibration(ADC2);

    result = rt_hw_adc_register(&adc2_device, "adc2", &imxrt_adc_ops, ADC2);

    if (result != RT_EOK)
    {
        LOG_E("register adc2 device failed error code = %d\n", result);
    }

#endif /* BSP_USING_ADC2 */

    return result;
}

INIT_DEVICE_EXPORT(rt_hw_adc_init);
  • 基于imxrt adc device 相关函数

内容很简单直接贴代码

static rt_err_t imxrt_hp_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
{
    return RT_EOK;
}

static rt_err_t imxrt_hp_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
    adc_channel_config_t adc_channel;
    ADC_Type *base;
    base = (ADC_Type *)(device->parent.user_data);

    adc_channel.channelNumber = channel;
    adc_channel.enableInterruptOnConversionCompleted = false;

    ADC_SetChannelConfig(base, 0, &adc_channel);

    while (0U == ADC_GetChannelStatusFlags(base, 0))
    {
        continue;
    }

    *value = ADC_GetChannelConversionValue(base, 0);

    return RT_EOK;
}

4.搭建应用层demo

底层IO初始化

IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_14_GPIO1_IO14, 0U); 
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_14_GPIO1_IO14, 0xB0U); 

应用读取adc1 通道3数据

/**************************************************START OF FILE*****************************************************/






/*------------------------------------------------------------------------------------------------------------------
Includes
*/
#include <rtthread.h>
#include <rtdevice.h>


/*------------------------------------------------------------------------------------------------------------------
Macros
*/
#define ADC_DEV_NAME        "adc1"      /* ADC 设备名称 */
#define ADC_DEV_CHANNEL     3           /* ADC 通道 */


/*------------------------------------------------------------------------------------------------------------------
Variables
*/
static rt_adc_device_t adc_dev;

/*------------------------------------------------------------------------------------------------------------------
Functions
*/
static int adcSample(int argc, char *argv[])
{
    rt_uint32_t value;
    rt_err_t ret = RT_EOK;

    /* 查找设备 */
    adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
    if (adc_dev == RT_NULL)
    {
        rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
        return RT_ERROR;
    }

	rt_kprintf("adc start", value);

    return ret;
}

static void adcRead(void)
{
	rt_uint32_t value;
    rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
    value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
	rt_kprintf("the value is :%d \n", value);
    rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
}


/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adcSample, adc voltage convert sample);
MSH_CMD_EXPORT(adcRead, adc read);

/****************************************************END OF FILE*****************************************************/


输入命令adcSample运行应用,输入adcRead打印当前adc值,笔者就仅仅将adc引脚触碰GND和3.3V测试

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值