本文将介绍基于 rt-thread studio 的 sdk 开发 adc 的应用。本实验是在昨天的《中科蓝讯 AB32VG1 开发板OLED显示实验》项目基础上,增加ADC电压采集的功能,将模拟量通道7采集到的电压值显示在OLED显示屏。
《中科蓝讯 AB32VG1 开发板OLED显示实验》文章的地址连接:中科蓝讯 AB32VG1 开发板OLED显示实验 。
根据说明书,AB32VG1 开发板上有 16 个通道的 10 bit 的 ADC 模块,最大采样速度是 78k/s; ADC 模块时钟的最大速度是 1MHz,有内部 100k 的上拉电阻。本文通过 RT-Thread Studio 配置 ADC驱动,完成ADC7通道的电压采集,并显示在OLED工作,使开发板上电,自动采集电压,OLED显示两行字符串:第一行显示“The Voltage”,第二行显示电压值“0.00V”。电路原理如图所示,
从电路原理图可知,:使用的是 ADC 的第 7 个通道,根据原理图可知对应的是 PE5 管脚,所以这里需要用杜邦线将PE5接到3.3V电源上,开发板实物杜邦线连接如图所示:其中白色是连接PE5与3.3V电源,其余接线为OLED相关,详见图中标注。
I2C 的 OLED 屏,芯片 SSD1309 .
步骤说明:
首先启动RT-Thread Studio,在工程项目中打开AB32VG1_IIC_OLED,(如果还没有这个工程,请看中科蓝讯 AB32VG1 开发板OLED显示实验 (qq.com)完成工程创建),展开工程,双击打开RT-Thread Settings,如下图所示
双击任意软件包或者点击右侧的“<<”,都可以进入的配置界面,弹出软件包和硬件配置界面,如下图所示,这里切换到硬件选型,如图所示开启名字为ADC0的AD转换设备,打对号即可。配置好后 ctrl+s 保存配置
2. ADC 设备使用示例
ADC 设备的具体使用方式可以参考rt-thread官方开发文档,官网连接:ADC设备 (rt-thread.org),从官方demo看,示例代码的主要步骤如下:
首先根据 ADC 设备名称 “adc1” 查找设备获取设备句柄,代码如下:
/* 查找设备 */
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);
returnRT_ERROR;
}
这里如果设备不存在,rt_device_find函数将返回NULL(RT_NULL),串口控制台会看到打印adc sample run failed! can't find字样,程序执行结束。
如果设备存在,下一步就是使能设备后读取 adc1 设备对应的通道 5 的采样值,
/* 使能设备 */
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);
这里rt_kprintf将转换之后的数字量串口打印输出。
最后根据读取的数字量,做一个标度变换,将数字量转为为实际的电压值。根据分辨率为 12 位,参考电压为 3.3V 计算实际的电压值。代码如下:
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
这里rt_kprintf将标度变换之后的采样电压值串口打印输出。
最后关闭 ADC 设备对应通道。代码如下:
ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
demo例程的最后一行代码是导出到 msh 命令列表中,这样需要在 finsh 命令行输入 tab 键,弹出支持的命令,输入 adc_vol_sample,才可以启动AD转换。
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);
3.修改main函数代码
在了解了官方ADC设备示例代码之后,下面对main函数修改。首先将官方代码拷贝到main函数中,然后修改ADC 设备名称、ADC 通道、参考电压、转换位数如下所示:这里设备为ADC0,模拟量通道为7,采集3.3V电压,转换位数为10位。
#defineADC_DEV_NAME "adc0" /* ADC 设备名称 */
#defineADC_DEV_CHANNEL 7 /* ADC 通道 */
#defineREFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#defineCONVERT_BITS (1 << 10) /* 转换位数为12位 */
修改函数定义static int adc_vol_sample(int argc, char *argv[])为static intadc_vol_sample(),同时将程序最后一句代码MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);删除,因为直接在主程序调用,上电执行ADC转换,这个就不要了。修改之函数后代码如图所示:
主程序调用adc_vol_sample,就可以了。要在主程序添加变量static intadvlue;
编译没有错误,就可以将程序下载到开发板运行,打开downloader下载切换到开发模式,就可以看到ADC转换的结果如下图所示.
4.编写OLED显示代码
上一篇文章,通过OLED实现了字符串显示,要实现电压值的显示,这里首先要将整型的电压值,分解出每一位,然后转化为字符输出显示。转换显示代码如下所示。
main函数完整代码如下,开发板实际运行如最后图片所示。
/*
* Copyright (c) 2020-2021, Bluetrum Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/12/10 greedyhao The first version
*/
/**
* Notice!
* All functions or data that are called during an interrupt need to be in RAM.
* You can do it the way exception_isr() does.
*/
#include
#include
#include
#include
#include "board.h"
#include "ssd1306.h"//包含SSD1306的头文件
#defineADC_DEV_NAME "adc0" /* ADC 设备名称 */
#defineADC_DEV_CHANNEL 7 /* ADC 通道 */
#defineREFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#defineCONVERT_BITS (1 << 10) /* 转换位数为12位 */
voiddisplay(inttmp)
{
//330
unsigned charcount;
unsigned chardatas[] = {0, 0, 0, 0, 0};
datas[0] = tmp / 100;
datas[1] = tmp % 100 / 10;
datas[2] = tmp % 100 % 10;
ssd1306_SetCursor(40, 40);//添加代码,设置显示光标位置
ssd1306_WriteChar('0'+datas[0], Font_11x18, White);
ssd1306_WriteChar('.', Font_11x18, White);
for(count = 1; count != 3; count++)
{
ssd1306_WriteChar('0'+datas[count], Font_11x18, White);
}
ssd1306_WriteChar('V', Font_11x18, White);
ssd1306_UpdateScreen();////添加代码,更新显示屏信息
}
static intadc_vol_sample()
{
rt_adc_device_t adc_dev;
unsigned charTemp_Disp_Buff[17];
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);
returnRT_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);
display(vol);
returnret;
}
intmain(void)
{
uint8_t pin = rt_pin_get("PE.1");
static intadvlue;
rt_pin_mode(pin, PIN_MODE_OUTPUT);
rt_kprintf("Hello, world\n");
ssd1306_Init();//添加代码,显示屏初始化
ssd1306_SetCursor(2, 6);//添加代码,设置显示光标位置
ssd1306_WriteString("The voltage", Font_11x18, White);//添加代码,设置显示内容
ssd1306_SetCursor(40, 40);//添加代码,设置显示光标位置
display(0);
ssd1306_UpdateScreen();////添加代码,更新显示屏信息
while(1)
{
rt_pin_write(pin, PIN_LOW);
rt_thread_mdelay(500);
rt_pin_write(pin, PIN_HIGH);
rt_thread_mdelay(500);
advlue=adc_vol_sample();
}
}
下一期文章,等电路板返回,做一下DS18B20测温实现。
编辑:fqj
全部0条评论
快来发表一下你的评论吧 !