• 【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,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 设备创建注册

    这里笔者只简单修改了一点,采样精度改成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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 基于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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4.搭建应用层demo

    底层IO初始化

    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_14_GPIO1_IO14, 0U); 
    IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_14_GPIO1_IO14, 0xB0U); 
    
    • 1
    • 2

    应用读取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*****************************************************/
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

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

    请添加图片描述

  • 相关阅读:
    JS+CSS随机点名详细介绍复制可用(可自己添加人名)
    2023/9/28 -- ARM
    应用案例|基于三维机器视觉的曲轴自动化上下料应用方案
    pytorch代码复现1(基础知识)
    【攻破css系列——第七天】属性值的计算
    向量空间概述
    微软:Octo Tempest是最危险的金融黑客组织之一
    【CPP】数据结构
    机器学习的逻辑回归
    【C++类和对象】定义 | 封装 | 访问限定符 | 作用域 | 对象模型 | this指针
  • 原文地址:https://blog.csdn.net/weixin_38426553/article/details/125616420