[活动] 【APM32E030R Micro-EVB开发板评测】在rt-thread中配置ADC并踩坑一次

[复制链接]
500|5
#申请原创# 在rt-thread中配置ADC并踩坑一次

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

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

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

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

  4. #if  defined(SOC_SERIES_APM32F0) || defined(SOC_SERIES_APM32E0)
  5.     if ((adc_cfg->adc == ADC) )
  6.     {
  7.         if (channel <= 18)
  8.         {
  9.             return RT_EOK;
  10.         }
  11.     }
  12. #endif

  13. #if  defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
  14.     if ((adc_cfg->adc == ADC1) || (adc_cfg->adc == ADC2))
  15.     {
  16.         if (channel <= 15)
  17.         {
  18.             return RT_EOK;
  19.         }
  20.     }
  21. #endif

  22. #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1)
  23.     if (adc_cfg->adc == ADC3)
  24.     {
  25.         if (channel <= 8)
  26.         {
  27.             return RT_EOK;
  28.         }
  29.     }
  30. #endif

  31. #if defined(SOC_SERIES_APM32F4)
  32.     if (adc_cfg->adc == ADC3)
  33.     {
  34.         if (channel <= 13)
  35.         {
  36.             return RT_EOK;
  37.         }
  38.     }
  39. #endif

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

  41.     return -RT_ERROR;
  42. }
这次编译顺利通过,但还有一些报警,直接无视

06.JPG
4 下载并运行
采用pyocd flash写入开发板,注意,对应于开发板的定义需要和pack中的定义一致,如APM32E030就不能通过,这里是APM32E030R8,才行
09.JPG
写入开发板,顺利读出ADC口的数据,
在代码中加入了main的命令,在msh中输入main的指令,就可以再次执行,实现会话式读取ADC的数据

08.JPG
5 补充,代码分析
  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #include <board.h>

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

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

  10. int main(void)
  11. {
  12.     /* set LED2 pin mode to output */
  13.     rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
  14.     rt_adc_device_t adc_dev;
  15.     rt_uint32_t value, vol;
  16.     rt_err_t ret = RT_EOK;

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

  24.     /* 使能设备 */
  25.     ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);

  26.     /* 读取采样值 */
  27.     value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
  28.     rt_kprintf("the value is :%d \n", value);

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

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

  34.     while (1)
  35.     {
  36.         rt_pin_write(LED2_PIN, PIN_HIGH);
  37.         rt_thread_mdelay(500);
  38.         rt_pin_write(LED2_PIN, PIN_LOW);
  39.         rt_thread_mdelay(500);
  40.     }

  41.     return RT_EOK;
  42. }

  43. 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分别有芯片温度读取和芯片电压读取,
10.JPG
但是这个rt-thread的驱动配置,为了整个APM32都适配,加了一个判断语句,最大的通道是16,在整个代码段里多次定义,所以,这里没有办法单独访问这两个
通道的adc数据。但是对应外部的参数,按照数据表格里面对应指定的引脚,是可以比较容易的实现的。
11.JPG
这里就是通道5对应的引脚
6 小结
配合这个小小的踩坑过程,可以比较完整的显示如何配置一个rtthread工程,并且在哪里进行驱动修改,如何进行修改。其他的外设,如PWM,RTC等都是完全一样的,实际发现,配置完还是都需要有所修改和调整的,整个过程可玩性不错。效果还是挺好的。


05.JPG
水之呢喃 发表于 2025-8-27 19:51 | 显示全部楼层
如果使用RT-Thread看样子是不用再关心底层驱动的实现了,是这样的吗?
 楼主| 北方西门吹雪 发表于 2025-9-1 16:27 | 显示全部楼层
水之呢喃 发表于 2025-8-27 19:51
如果使用RT-Thread看样子是不用再关心底层驱动的实现了,是这样的吗?

驱动移植好以后,确实是这样。
不过,新的芯片和开发板都要重新做BSP。
水之呢喃 发表于 2025-9-10 11:22 | 显示全部楼层
编写BSP驱动还是挺麻烦的事情。尤其是领导突发奇想更换主芯片
 楼主| 北方西门吹雪 发表于 2025-9-10 13:58 | 显示全部楼层
水之呢喃 发表于 2025-9-10 11:22
编写BSP驱动还是挺麻烦的事情。尤其是领导突发奇想更换主芯片

这个还是靠社区比较好一些。自己踩坑后分享。
不过rt-thread已经很友好了,换bsp难度适中
穷得响叮当侠 发表于 2025-9-28 13:02 | 显示全部楼层
踩坑的经历总是宝贵的,通过你的分享,我们可以避免走同样的弯路
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

125

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部