基于rt-thread studio的sdk开发adc的应用详解

描述

本文将介绍基于 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”。电路原理如图所示,

RT-Thread

从电路原理图可知,:使用的是 ADC 的第 7 个通道,根据原理图可知对应的是 PE5 管脚,所以这里需要用杜邦线将PE5接到3.3V电源上,开发板实物杜邦线连接如图所示:其中白色是连接PE5与3.3V电源,其余接线为OLED相关,详见图中标注。

RT-Thread

I2C 的 OLED 屏,芯片 SSD1309 .

RT-Thread

步骤说明:

首先启动RT-Thread Studio,在工程项目中打开AB32VG1_IIC_OLED,(如果还没有这个工程,请看中科蓝讯 AB32VG1 开发板OLED显示实验 (qq.com)完成工程创建),展开工程,双击打开RT-Thread Settings,如下图所示

RT-Thread

双击任意软件包或者点击右侧的“<<”,都可以进入的配置界面,弹出软件包和硬件配置界面,如下图所示,这里切换到硬件选型,如图所示开启名字为ADC0的AD转换设备,打对号即可。配置好后 ctrl+s 保存配置

RT-Thread

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转换,这个就不要了。修改之函数后代码如图所示:

RT-Thread

主程序调用adc_vol_sample,就可以了。要在主程序添加变量static intadvlue;

RT-Thread

编译没有错误,就可以将程序下载到开发板运行,打开downloader下载切换到开发模式,就可以看到ADC转换的结果如下图所示.

RT-Thread

4.编写OLED显示代码

上一篇文章,通过OLED实现了字符串显示,要实现电压值的显示,这里首先要将整型的电压值,分解出每一位,然后转化为字符输出显示。转换显示代码如下所示。

RT-Thread

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();

}

}

RT-Thread

下一期文章,等电路板返回,做一下DS18B20测温实现。

RT-Thread

编辑:fqj

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分