这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 在rt-thread中配置ADC并踩坑一次

共1条 1/1 1 跳转至

在rt-thread中配置ADC并踩坑一次

院士
2025-08-19 18:58:41     打赏

1 概述
在rt-thread配置外设原本是妥妥的轻松,不过,这次在APM32E030R Micro-EVB却踩了一个坑。续前帖子,配置外设,从menuconfig就可以轻松搞定,但是,对于新的开发板,还是在移植上有不少的地方,还是需要微调才行。
2 配置ADC
还是启动menuconfig,进入到chip芯片的硬件配置,这个是配置外设,需要选中Enable ADC就是是能ADC的功能,这个开关就把rtthread的ADC驱动导入工程,

记住还要选择ADC1,这个是选择ADC的通道的,必选


然后点击存储,继续存在配置文件中,然后退出则可


3 踩坑并排查
编译工程,立刻就出现了状况,显示ADC1和ADC2没有定义,无法生成二进制文件

找到这个对应的文件所在,进行如下修改。原代码在这里并没有专门设置对应于芯片的配置,APM32E030R Micro-EVB只有一个ADC通道,所以,在官方的驱动中,就不再分ADC1和ADC2等,所以,如果没有选择定义,就出现了这样的情况。看似解决问题很容易,但是需要逐条语句排查硬件pack代码中对应ADC部分的全部定义和参数配置,再对照rt-thread的定义阵列都正确定义,最后可以顺利编译通过。需要队底层驱动和rt-thread都比较了解才好,

static rt_err_t apm32_adc_channel_check(struct rt_adc_device *device, rt_uint32_t channel)
{
    struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);

#if  defined(SOC_SERIES_APM32F0) || defined(SOC_SERIES_APM32E0)
    if ((adc_cfg->adc == ADC) )
    {
        if (channel <= 18)
        {
            return RT_EOK;
        }
    }
#endif

#if  defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
    if ((adc_cfg->adc == ADC1) || (adc_cfg->adc == ADC2))
    {
        if (channel <= 15)
        {
            return RT_EOK;
        }
    }
#endif

#if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1)
    if (adc_cfg->adc == ADC3)
    {
        if (channel <= 8)
        {
            return RT_EOK;
        }
    }
#endif

#if defined(SOC_SERIES_APM32F4)
    if (adc_cfg->adc == ADC3)
    {
        if (channel <= 13)
        {
            return RT_EOK;
        }
    }
#endif

    LOG_E("channel %d of %s is not supported.", channel, adc_cfg->name);

    return -RT_ERROR;
}

这次编译顺利通过,但还有一些报警,直接无视


4 下载并运行
采用pyocd flash写入开发板,注意,对应于开发板的定义需要和pack中的定义一致,如APM32E030就不能通过,这里是APM32E030R8,才行

写入开发板,顺利读出ADC口的数据,
在代码中加入了main的命令,在msh中输入main的指令,就可以再次执行,实现会话式读取ADC的数据


5 补充,代码分析

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define ADC_DEV_NAME        "adc1"      /* ADC 设备名称 */
#define ADC_DEV_CHANNEL     5           /* ADC 通道 */
#define REFER_VOLTAGE       330         /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS        (1 << 12)   /* 转换位数为12位 */

/* defined the LED2 pin: PB6 */
#define LED2_PIN    GET_PIN(B, 6)

int main(void)
{
    /* set LED2 pin mode to output */
    rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
    rt_adc_device_t adc_dev;
    rt_uint32_t value, vol;
    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;
    }

    /* 使能设备 */
    ret = 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);

    /* 转换为对应电压值 */
    vol = value * REFER_VOLTAGE / CONVERT_BITS;
    rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);

    /* 关闭通道 */
    ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);

    while (1)
    {
        rt_pin_write(LED2_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED2_PIN, PIN_LOW);
        rt_thread_mdelay(500);
    }

    return RT_EOK;
}

MSH_CMD_EXPORT(main, adc voltage convert sample);

在这些配置中,按照rt-thread的工作逻辑,都是需要先创建一个设备,这里是ADC设备,然后直接使能改设备
ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
随后就可以读取数据了,adc_dev是定义的adc外设设备,选择通道就可以。
本来,对应于APM32E030,在通道17,通道18分别有芯片温度读取和芯片电压读取,

但是这个rt-thread的驱动配置,为了整个APM32都适配,加了一个判断语句,最大的通道是16,在整个代码段里多次定义,所以,这里没有办法单独访问这两个
通道的adc数据。但是对应外部的参数,按照数据表格里面对应指定的引脚,是可以比较容易的实现的。

这里就是通道5对应的引脚
6 小结
配合这个小小的踩坑过程,可以比较完整的显示如何配置一个rtthread工程,并且在哪里进行驱动修改,如何进行修改。其他的外设,如PWM,RTC等都是完全一样的,实际发现,配置完还是都需要有所修改和调整的,整个过程可玩性不错。效果还是挺好的。




关键词: rt-thread     ADC    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]