【APM32E030R Micro-EVB开发板评测】在rt-thread中配置ADC并踩坑一次
#申请原创# 在rt-thread中配置ADC并踩坑一次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);
#ifdefined(SOC_SERIES_APM32F0) || defined(SOC_SERIES_APM32E0)
if ((adc_cfg->adc == ADC) )
{
if (channel <= 18)
{
return RT_EOK;
}
}
#endif
#ifdefined(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看样子是不用再关心底层驱动的实现了,是这样的吗?
页:
[1]