一、按键驱动
1.1 按键引脚
合宙Air780E开发板的按键引脚定义可以参考其原理图。通常,一个用户可用的按键会连接到某个特定的GPIO引脚上。

根据原理图,引脚19对应GPIO22,这个引脚常被用作按键输入。
1.2 测试代码
接下来,我们编写Lua代码来测试这个按键。代码的核心是将GPIO22配置为上拉输入模式,然后循环读取其电平状态。
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "Key"
VERSION = "1.0.0"
-- 引入必要的库文件(lua编写), 内部库不需要require
sys = require(“sys”)
--=============================================================
log.info(“按键输入,打印引脚电平”)
local key0 = 22
gpio.setup(key0, nil,gpio.PULLUP)
--=============================================================
function KeyFun()
while 1 do
local resalt=gpio.get(key0)
--log.info(“GPIO22的电平=“,resalt)
if resalt==1 then
log.info(“key0 是高电平,值=“,resalt)
--sys.wait(500)
else
log.info(“key0 是低电平,值=“,resalt)
--sys.wait(500)
end
sys.wait(1000)
end
end
--=============================================================
sys.taskInit(KeyFun)
--=============================================================
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
这段代码逻辑清晰:初始化GPIO后,在一个循环任务中每秒读取一次引脚电平,并通过日志打印出来。按键未按下时,由于上拉电阻的作用,引脚为高电平(1);按下按键连接到地时,引脚变为低电平(0)。在计算机基础知识中,理解这种上拉输入电路是进行嵌入式嵌入式开发的基础。
1.3 测试结果
将代码烧录到Air780E开发板并运行,通过串口工具查看日志输出。
当按键未按下时,输出如下高电平信息:

当按下按键时,输出变为低电平信息:

二、模数转换(ADC)功能
2.1 引脚原理图和相关说明
模数转换器(ADC)是嵌入式系统中用于采集模拟信号(如电压、温度)的关键模块。在合宙Air780E上,ADC1对应引脚96。

什么是ADC?
模拟到数字转换器(Analog-to-Digital Converter),它是一种电子设备或模块,用于将连续变化的模拟信号转换为离散的数字信号,以便数字系统(如MCU)能够对其进行处理和分析。
ADC关键指标
对于某个确定的模组,其ADC分辨率通常是固定的(合宙主流模组多为12bit),但电压输入范围可能在不同条件下有所调整。这主要涉及两个常量:
adc.ADC_RANGE_MIN: 对应量程为0-1.5V
adc.ADC_RANGE_MAX: 对应量程为0-3.6V(Air8101为0-2.4V)

量程选择准则
官方文档给出了明确的量程选择建议:
- 当被测电压最大值在1.5V以内,使用
adc.ADC_RANGE_MIN。
- 当被测电压大于1.5V但小于3.6V(Air8101小于2.4V),使用
adc.ADC_RANGE_MAX,且不添加外部分压电路。
- 当被测电压最高值在3.6V以上(Air8101在2.4V以上)时,必须使用
adc.ADC_RANGE_MIN,并添加外部分压电路将电压降至1.5V量程内。
特别注意:adc.setRange(range)函数必须在adc.open(id)之前调用,否则设置无效。
ADC通道ID映射
不同型号的合宙模组,其外部ADC引脚与通道ID的对应关系如下:
- Air780E系列/Air8000系列:ADC0对应通道ID 0,ADC1对应ID 1,ADC2对应ID 2,ADC3对应ID 3。
- Air8101系列:内部具有更多ADC通道,例如ADC1对应通道ID 1,具体映射关系需参考详细手册。
内部专用通道
除了外部引脚,ADC模块还提供了两个内部通道,用于读取芯片内部信息,无需外接电路:
adc.CH_CPU: 用于读取CPU内部温度,单位为千分之一摄氏度。
adc.CH_VBAT: 用于读取VBAT供电电压,单位为mV。
读取这两个通道前,不需要调用adc.setRange(range)函数。
2.2 API函数详解
LuatOS为ADC操作提供了一组简洁的Lua API。

1. adc.open(id)
打开指定的ADC通道。

2. adc.setRange(range)
设置ADC的测量范围。必须在adc.open之前调用!

3. adc.read(id)
读取ADC通道的原始值和计算值。通常我们更关心计算值(data1),单位是mV。

4. adc.get(id)
获取ADC通道的计算值。这是adc.read(id)的简化版,只返回计算值。对于adc.CH_CPU通道,返回的是温度值。

5. adc.close(id)
关闭ADC通道。如果不需要持续读取,应关闭通道以降低功耗(约400uA)。

2.3 测试代码
我们编写两个测试例程,分别演示基础用法和循环读取多种数据。
测试代码1:基础顺序读取
此代码依次读取CPU温度、VBAT电压和外部ADC1引脚电压。
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = “ADC”
VERSION = “1.0.0”
-- sys库是标配
sys = require(“sys”)
--=============================================================
local adcx = 1
local function MY_ADC()
-- 读取CPU温度, 单位为0.001摄氏度, 是内部温度, 非环境温度
while 1 do
sys.wait(1000)
adc.open(adc.CH_CPU)
local temp = adc.get(adc.CH_CPU)
log.info(“CPU温度=“,temp/1000)
--adc.close(adc.CH_CPU)
-- adc.CH_CPU,CPU内部温度的通道id,内部通道,直接获取,不占用ADC 0-3,不外接任何电路
-- 读取VBAT供电电压, 单位为mV
--=============================================================
sys.wait(1000)
adc.open(adc.CH_VBAT)
local vbat = adc.get(adc.CH_VBAT)
log.info(“VBAT供电电压“,vbat/1000)
--adc.close(adc.CH_VBAT)
-- adc.CH_VBAT,VBAT供电电压的通道id,内部通道,直接获取,不占用ADC 0-3,不外接任何电路
-- adc.CH_CPU 和 adc_CH_VBAT 在做读取动作之前,不需要像 ADC 0-3通道一样先打开adc.setRange(range)函数
--=============================================================
sys.wait(1000)
--修改IO电平,都可以通过LuatOS软件设置为1.8V/2.8V/3.0V/3.3V
pm.ioVol(pm.IOVOL_ALL_GPIO, 3300)
-- 设置ADC引脚的测量范围0-3.6V,这种方式被测电压不可经过外部电阻分压后再挂在ADC上;
adc.setRange(adc.ADC_RANGE_MAX)
-- 打开adc通道1,并读取
adc.open(adcx)
local ADC_Value=adc.get(adcx)
log.info(“adc1=“, ADC_Value,“mV”) -- 返回电压值;
--=============================================================
end
end
--=============================================================
sys.taskInit(MY_ADC)
--=============================================================
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
测试代码2:状态机循环读取
这个代码使用一个简单的状态机(step变量),循环轮流读取三种数据,结构更紧凑。
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = “ADC”
VERSION = “1.0.0”
-- sys库是标配
sys = require(“sys”)
--=============================================================
local adcx = 1
local function MY_ADC()
local step=0
-- adc.CH_CPU,CPU内部温度的通道id,内部通道,直接获取,不占用ADC 0-3,不外接任何电路
-- adc.CH_VBAT,VBAT供电电压的通道id,内部通道,直接获取,不占用ADC 0-3,不外接任何电路
-- adc.CH_CPU 和 adc_CH_VBAT 在做读取动作之前,不需要像 ADC 0-3通道一样先打开adc.setRange(range)函数
adc.open(adc.CH_CPU)
adc.open(adc.CH_VBAT)
pm.ioVol(pm.IOVOL_ALL_GPIO, 3300) -- 设置ADC引脚的测量范围0-3.6V,这种方式被测电压不可经过外部电阻分压后再挂在ADC上;
adc.setRange(adc.ADC_RANGE_MAX)
-- 打开adc通道1
adc.open(adcx)
while true do
sys.wait(1000)
log.info(“step =“,step)
if step == 0 then
local temp = adc.get(adc.CH_CPU)
log.info(“CPU温度=“,temp/1000)
step = 1
elseif step == 1 then
local vbat = adc.get(adc.CH_VBAT)
log.info(“VBAT供电电压“,vbat/1000)
step = 2
elseif step == 2 then
local ADC_Value=adc.get(adcx)
log.info(“adc1=“, ADC_Value,“mV”) -- 返回电压值;
step = 0
else
step = 0
end
end
end
--=============================================================
sys.taskInit(MY_ADC)
--=============================================================
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
2.4 测试结果
将ADC1引脚先后接地(GND)和接3.3V电源,运行上述任一测试代码,通过串口日志可以观察到电压值的变化。

从日志中可以看到:
VBAT供电电压在4.017V左右,这是板子的供电电压。
- 当ADC1接地时,
adc1读取值为0 mV。
- 当ADC1接3.3V时,
adc1读取值约为3309 mV,与预期相符(存在微小偏差属于正常现象)。
CPU温度稳定在27摄氏度左右。
总结
通过本文的实践,我们掌握了在合宙Air780E开发板上使用LuatOS驱动GPIO按键和ADC模块的基本方法。从引脚识别、代码编写到结果验证,完成了完整的开发流程。GPIO输入是检测数字开关信号的基础,而ADC则为连接各类模拟传感器(如光照、压力、温度传感器)打开了大门,是嵌入式开发中至关重要的技能。希望这篇教程能帮助你快速上手。更多深入的技术讨论和项目分享,欢迎访问云栈社区与广大开发者交流。
参考