前面一期内容讲述了GPIO的控制编程和配置,今天来学习一下ADC采集,能够学习到RTT的同学自然也都是玩单片机的老手了,至于ADC是什么东西也不用我来解释说明了,如果有不懂的可以去百度或者去官方标准手册里面查看。在学习ADC采集之前我们需要引入一下Kconfig语法,目的是让大家知道为何要在Settings中进行选择,为何选择后就能够驱动起来ADC。注意:记得提前安装CubeMX否则无法进行配置开发
1.Kconfig的引入
Kconfig在RT-Thread中的工作机制:
C语言项目的裁剪配置本质上通过条件编译和宏的展开来实现的,RT-Thread借助Kconfig这套机制更方便的实现了这一功能。当前以Windows下Env工具中的使用为例,简述Kconfig在RT-Thread的工作机制。
Kconfig机制包括了Kconfig文件和配置UI界面(如menuconfig,pyconfig等)。Kconfig机制有如下特点:
- Kconfig文件中的配置项会映射至rtconfig.h中
- Kconfig文件可以随源码分散至各级子目录,便于灵活修改。
由于内容太多并且复杂,具体的内容到官方网站上的手册中查看,路径如下:
2.对照Kconfig查看Settings
在对Kconfig有一定了解后可以参考Settings来验证手册中讲述的Kconfig语法作用。这个可视化界面Settings和Kconfig语法编写的Kconfig文件是一一对应的所以在制作自己的bsp包的时候可以利用Kconfig语法来丰富自己的bsp包从而达到在以后的开发中更加高效轻松的目的。
3.开始ADC的配置
打开Settings点击红框里面的按钮,进入到硬件配置。
Ctrl+S保存一下配置然后编译一下,这时候会发现报错了,爆了一大堆,不要慌!报错的原因是虽然在应用层使能了ADC框架但是在驱动层上没有进行配置,这时候打开工程文件的CubeMX开始配置ADC驱动引脚。
在工程列表下找到board文件夹打开找到下图文件
进入这个文件,然后就能看到CubeMX的工程文件了(注意:记得提前安装CubeMX否则无法进行配置开发)
点击进去,然后界面如下:
这是打开开发板原理图寻找一个ADC通道。这里我们就随便选一个PC0吧,去到CubeMX进行配置。
可以看到有多组ADC,我们随便选择就行,我们选择ADC1的通道10,这时候生成代码便可。
重新编译一下,没有报错了
这时候下载程序,然后进入串口助手进行调试。
4.FinSH命令调试
系统运行后桉tab键即可弹出可以使用的命令,这时adc也出现了然后根据图片命令顺序进行调试即可。(注意:这里只是调试,代码应用在下一小节)
5.ADC读取电平代码应用
在文件夹里面创建一个adc.c文件(注意:创建文件的方法和位置不固定,按照个人爱好来操作即可)
创建完后开始编写adc采集代码(代码官方手册中有示例可以参考,如果编译报错很多的话就到Settings中关闭ADC编译一下然后再打开ADC编译就没有问题了,这个因该是软件的bug,还有一种办法就是在工程列表空白处右键然后点击“同步scons配置至项目”)
/*adc.c
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-05 ZXY the first version
*/
/*
* 程序清单: ADC 设备使用例程
* 例程导出了 adc_sample 命令到控制终端
* 命令调用格式:adc_sample
* 程序功能:通过 ADC 设备采样电压值并转换为数值。
* 示例代码参考电压为3.3V,转换位数为12位。
*/
#include <rtthread.h>
#include <rtdevice.h>
#define ADC_DEV_NAME "adc1" /* ADC 设备名称 */
#define ADC_DEV_CHANNEL 10 /* 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);
代码里面都有注释,每个API在手册里面都有非常详细的使用说明,这也是应用层需要掌握的知识,本系列教程重在应用所以不会讲到太深入的地方(底层驱动就不会详细讲述)。对于代码最后的msh导出命令也就是在串口助手中调试的时候输出的命令,这些命令都是由msh导出的,这样使用一次命令就运行一次定义msh命令的代码,这和裸机的运行不一样,所以我们需要让代码一直循环运行的话就需要改变他的初始化顺序,让这adc采集自动初始化开机就能运行。修改后代码如下:
/*adc.c
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-05 ZXY the first version
*/
/*
* 程序清单: ADC 设备使用例程
* 例程导出了 adc_sample 命令到控制终端
* 命令调用格式:adc_sample
* 程序功能:通过 ADC 设备采样电压值并转换为数值。
* 示例代码参考电压为3.3V,转换位数为12位。
*/
#include <rtthread.h>
#include <rtdevice.h>
#define ADC_DEV_NAME "adc1" /* ADC 设备名称 */
#define ADC_DEV_CHANNEL 10 /* 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);
while(1)
{
/* 读取采样值 */
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);
rt_thread_mdelay(500);
}
return ret;
}
INIT_APP_EXPORT(adc_vol_sample);