以下内容是我个人的学习笔记,因为个人能力有限,如有错误欢迎指出,非常感谢。
在RT-Thread的应用层中提供ADC接口,函数如下
但是在不同BSP中,需要自己移植入对应的固件
这个视频:2021最新RT-Thread实时操作系统教程,入门到精通全套完整版_哔哩哔哩_bilibili
是STM32移植CubeMX配置下的HAL代码,而对于GD32可能无法用,因此需要移植GD官方的。
我们使用ENV裁切工具,方便快捷地添加ADC固件:
首先输入menuconfig,进入下面的Hardware Drivers config配置
进入 On-chip Peripheral Drivers
空格选中使能ADC
按ESC直到弹出保存提示框,按空格选择Yes保存
输入scons --target=mdk5,重新编译好MDK5的文件
打开工程project.uvprojx
上述的操作,ENV工具其实已经帮我们添加以下文件到工程,而如果我们手动添加可能会失败
所以我们无需手动添加了。
1.GD官方固件gd32f30x_adc.c
位于..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\
gd32f30x_adc.c (DMA本次先不使用,可不添加)
2.rt-thread的adc.c
位于:..\..\..\..\components\drivers\misc\adc.c
3.rt-thread的drv_adc.c
位于:..\libraries\gd32_drivers\drv_adc.c
打开上述工程后,编译,会发现报错如下:
看到这个报错,我们已经完成一大半了。这个错误是因为drv_adc.c中的条件编译代码我们没有添加好宏定义,编译器无法执行到,因此处于缺失状态。
二.添加好宏定义#define BSP_USING_xxx
我们在drv_adc.c文件中,可见到很多条件编译命令,如果在vscode打开,可以很明显看到这些代码块是灰色的,即没有宏定义到该代码块,不会被执行。
因此,我们在rtconfig.h里面宏定义使用ADC0(其他也可):
三.移植初始化ADC代码
在《基于GD32F303RCT6单片机在RT-Thread下的零基础学习记录(1)例程下载》中,我已经下载好了GD的固件例程和配置修改好了RT-Thread的demo,下面以GD32F30x_Firmware_Library_V2.1.3\Examples\ADC\ADC0_regular_channel_with_DMA的例程进行移植到RT-Thread。当然,这次简单点,只是用他的初始化。
方法很简单,打开上述目录中的main.c文件,拷贝
1. void rcu_config(void)
2.void gpio_config(void)
到rt-thread 的工程中的board.c文件的最下面,由于该例程是用DMA的,可删掉DMA部分,删改后的程序如下:(以GPIO-B0为例)
void ADC_GD32_init()
{
/* enable GPIOA clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC0);
/* config ADC clock */
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);
/* config the GPIO as analog mode */
gpio_init(GPIOB, GPIO_MODE_AIN, GPIO_OSPEED_10MHZ, GPIO_PIN_0);
}
对应通道可参考drv_adc.c中结构体数组
如图,PB0位于数组第8位,即通道8
四.添加rt-thread的ADC demo
参考:
也可用下面我稍作修改的代码:
/*
* 程序清单: ADC 设备使用例程
* 例程导出了 adc_sample 命令到控制终端
* 命令调用格式:adc_sample
* 程序功能:通过 ADC 设备采样电压值并转换为数值。
* 示例代码参考电压为3.3V,转换位数为12位。
*/
#include <rtthread.h>
#include <rtdevice.h>
#define ADC_DEV_NAME "adc0" /* ADC 设备名称 */
#define ADC_DEV_CHANNEL 8 /* ADC 通道,上述有说明怎么根据管脚对应通道 */
#define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */
static int adc_vol_sample(int argc, char *argv[])
{
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);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);
上面的demo直接复制到自己创建的.c文件或者直接放在main.c中,在终端中执行help可看到该命令
连接到对应管脚,执行adc_vol_sample
万用表测一下:
还算挺准的啦,调整一下电阻值,再测:
效果还可以。