UART - 串口操作库
作者:魏健强
一、概述
UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种常用的串行通信协议,广泛应用于单片机或各种嵌入式设备之间的通信;
二、核心示例
1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;
2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;
3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/uart;
local uartid = 1 -- 根据实际设备选取不同的uartid
uart_mode_zbuff = true -- 是否使用zbuff方式收发数据收发
local function send_data_zbuff()
local txbuff = zbuff.create(1024) -- 发送数据的zbuff
-- 循环两秒向串口发一次数据
txbuff:write("测试数据01234567890") -- 向发送数据的zbuff写入数据
while true do
sys.wait(1000)
--发送数据
uart.tx(uartid, txbuff)
end
end
local function send_data_string()
-- 循环两秒向串口发一次数据
while true do
sys.wait(2000)
uart.write(uartid, "test data.")
end
end
if uart_mode_zbuff then
local rxbuff = zbuff.create(1024) -- 接收数据的zbuff
local function uart_cb(id, len) -- 串口接收数据回调函数
while 1 do
log.info("uart", "缓冲区", uart.rxSize(id)) -- 缓冲区中的数据数量
local len = uart.rx(id, rxbuff)
if len <= 0 then
break
end
log.info("uart", "receive", id, rxbuff:used(), rxbuff:toStr())
rxbuff:seek(0)
end
end
uart.setup(uartid)
uart.on(uartid, "receive", uart_cb)
sys.taskInit(send_data_zbuff)
else
local function uart_cb(id, len)
local s = ""
repeat
s = uart.read(id, 10240) -- 一次性读出所有缓冲区中的数据,避免分包
if #s > 0 then -- #s 是取字符串的长度
-- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
log.info("uart", "receive", id, #s, s)
-- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
end
until s == ""
end
-- 初始化
uart.setup(uartid, -- 串口id
115200, -- 波特率
8, -- 数据位
1, -- 停止位
uart.NONE, -- 校验位,可选 uart.None/uart.Even/uart.Odd。默认 uart.None 无校验
uart.LSB, -- 大小端,默认小端 uart.LSB, 可选 uart.MSB
1024 -- 缓冲区大小,默认值1024,接收大数据时需要根据数据大小增大缓冲区
)
-- 收取数据会触发回调, 这里的"receive" 是固定值
uart.on(uartid, "receive", uart_cb)
sys.taskInit(send_data_string)
end
三、常量详解
核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;
每个常量对应的常量取值仅做日志打印时查询使用,不要将这个常量取值用做具体的业务逻辑判断,因为LuatOS内核固件可能会变更每个常量对应的常量取值;
如果用做具体的业务逻辑判断,一旦常量取值发生改变,业务逻辑就会出错;
3.1 uart.Odd
常量含义:串口校验方式:奇校验;
数据类型:number;
常量取值:1;
示例代码: uart.setup(1, 115200, 8, 1, uart.Odd);
3.2 uart.Even
常量含义:串口校验方式:偶校验;
数据类型:number;
常量取值:2;
示例代码: uart.setup(1, 115200, 8, 1, uart.Even);
3.3 uart.None
常量含义:串口校验方式:无校验;
数据类型:number;
常量取值:0;
示例代码: uart.setup(1, 115200, 8, 1, uart.None);
3.4 uart.LSB
常量含义:数据存储方式:小端模式;
数据类型:number;
常量取值:0;
示例代码: uart.setup(1, 115200, 8, 1, uart.None, uart.LSB);
3.5 uart.MSB
常量含义:数据存储方式:大端模式;
数据类型:number;
常量取值:1;
示例代码: uart.setup(1, 115200, 8, 1, uart.None, uart.MSB);
3.6 uart.VUART_0
常量含义:usb虚拟端口(适用于Air780EXX系列和Air8000系列模组);
数据类型:number;
常量取值:32;
示例代码: uart.setup(uart.VUART_0, 115200, 8, 1);
3.7 uart.ERROR_DROP
常量含义:遇到错误时抛弃缓冲区中的数据。(适用于Air780EXX系列,Air8101系列和Air8000系列模组)
[缓冲区](串口接收数据时会先将数据存放至缓冲区,通过uart.read或uart.rx接口从缓冲区
中读取数据);
数据类型:number;
常量取值:214;
示例代码: uart.setup(1, 115200, 8, 1, uart.NONE, nil, 1024, nil, nil, nil, nil,
uart.ERROR_DROP);
3.8 uart.DEBUG
常量含义:开启调试功能(适用于Air780EXX系列,Air8101系列和Air8000系列模组);
数据类型:number;
常量取值:62;
示例代码: uart.setup(1, 115200, 8, 1, uart.NONE, nil, 1024, nil, nil, nil, uart.DEBUG,
uart.ERROR_DROP);
四、函数详解
4.1 uart.setup(id, baud_rate, data_bits, stop_bits, partiy, bit_order, buff_size, rs485_gpio, rs485_level, rs485_delay, debug_enable, error_drop)
功能
配置串口参数,并开启串口功能;
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.setup(1);
baud_rate
参数含义:波特率;
数据类型:number;
取值范围:可选择波特率表:{2000000,921600,460800,230400,115200,57600,38400,19200,9600,4800,2400};
是否必选:可选;
注意事项:默认115200;
参数示例:uart.setup(1, 115200);
data_bits
参数含义:数据位;
数据类型:number;
取值范围:7/8;
是否必选:可选;
注意事项:默认8;
参数示例:uart.setup(1, 115200, 8);
stop_bits
参数含义:停止位;
数据类型:number;
取值范围:0.5/1/1.5/2等;
是否必选:可选;
注意事项:默认为1;
参数示例:uart.setup(1, 115200, 8,1);
partiy
参数含义:校验位;
数据类型:number;
取值范围:uart.None/uart.Even/uart.Odd;
是否必选:可选;
注意事项:默认为uart.None无校验;
参数示例:uart.setup(1, 115200, 8, 1, uart.None);
bit_order
参数含义:数据存储方式:大小端;
数据类型:number;
取值范围:uart.LSB/uart.MSB;
是否必选:可选;
注意事项:默认小端 uart.LSB;
参数示例:uart.setup(1, 115200, 8, 1, uart.None,uart.LSB);
buff_size
参数含义:缓冲区大小;
数据类型:number;
取值范围:1024-16384;
是否必选:可选;
注意事项:[缓冲区](串口接收数据时会先将数据存放至缓冲区,通过uart.read或uart.rx接口从缓冲区中读取数
据)项目中需要接收大数据并且需要避免分包时,可以增加缓冲区大小,并且通过uart.rx接口一次性从
缓冲区中读取全部数据。(注意zbuff创建的大小也需要增大);
参数示例:uart.setup(1, 115200, 8, 1, uart.None,uart.LSB,1024);
rs485_gpio
参数含义:485模式下的转换GPIO;
数据类型:number;
取值范围:根据设备选择可用的gpio;
是否必选:可选;
注意事项:默认0xffffffff;
参数示例:uart.setup(1, 9600, 8, 1, uart.NONE, uart.LSB, 1024, 10, 0, 20000);
rs485_level
参数含义:485模式下的rx方向GPIO的电平;
数据类型:number;
取值范围:0/1;
是否必选:可选;
注意事项:默认值0;
参数示例:uart.setup(1, 9600, 8, 1, uart.NONE, uart.LSB, 1024, 10, 0, 20000);
rs485_delay
参数含义:485模式下tx向rx转换的延迟时间;
数据类型:number;
取值范围:暂无;
是否必选:可选;
注意事项:单位us, 9600波特率填20000。这个是经验值,其余波特率可以参考这个波特率,
根据比例自行计算,如4800波特率是20000*9600/4800 = 40000;
参数示例:uart.setup(1, 9600, 8, 1, uart.NONE, uart.LSB, 1024, 10, 0, 20000);
debug_enable
参数含义:是否开启调试功能(开启后底层日志中会输出更多相关信息);
数据类型:number;
取值范围:暂无;
是否必选:可选;
注意事项:默认使能,填写uart.DEBUG或者非数字使能,其他值都是关闭;
参数示例:uart.setup(1, 115200, 8, 1, uart.NONE, nil, 1024, nil, nil, nil, uart.DEBUG);
error_drop
参数含义:遇到接收错误是否放弃缓冲数据
[缓冲区](串口接收数据时会先将数据存放至缓冲区,通过uart.read或uart.rx接口从缓冲区中读取数据);
数据类型:number;
取值范围:暂无;
是否必选:可选;
注意事项:默认使能,填写uart.ERROR_DROP或者非数字使能,其他值都是关闭;
参数示例:uart.setup(1, 115200, 8, 1, uart.NONE, nil, 1024, nil, nil, nil, uart.DEBUG,
uart.ERROR_DROP);
返回值
local res = uart.setup(id)
log.info("uart.setup(id)", res)
res
含义说明:初始化并开启串口的结果;
数据类型:number;
取值范围:0或者其他;
注意事项:返回值为0代表成功,其他值代表失败;
返回示例:0;
示例
local res = uart.setup(1, 115200, 8, 1, uart.NONE)
4.2 uart.write(id, data,len)
功能
串口发送数据,返回值为成功发送的数据长度。串口数据发送完成的消息可以通过 uart.on 接口注册 sent 事件的回调函数获取。
大数据收发建议使用 uart.tx 和 uart.rx 接口(zbuff 可以自动扩容,并且接收数据不需要手动设置需要接收的数据大小,默认全部读取。zbuff 处理数据也更方便);
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.write(1, "rdy\r\n");
data
参数含义:需要发送的数据;
数据类型:string;
取值范围:暂无;
是否必选:必选;
注意事项:如果是zbuff会从指针起始位置开始发送;
参数示例: uart.write(1, "rdy\r\n");
len
参数含义:要发送的数据长度;
数据类型:number;
取值范围:暂无;
是否必选:可选;
注意事项:默认全发,只要ram够用,数据长度无限制;
参数示例:uart.write(1, "1234567890",5);
返回值
local number = uart.write(id, data,len)
log.info("uart.write", number)
number
含义说明:发送成功的数据长度;
数据类型:number;
取值范围:无;
注意事项:无;
返回示例:5;
示例
local result = uart.write(1, "1234567890",5)
4.3 uart.read(id, len)
功能
读取串口接收的数据。大数据收发建议使用 uart.tx 和 uart.rx 接口
(zbuff 可以自动扩容,并且接收数据不需要手动设置需要接收的数据大小,
默认全部读取。zbuff 处理数据也更方便);
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.read(1, 1024);
len
参数含义:期望读取数据的长度;
数据类型:number;
取值范围:暂无;
是否必选:可选;
注意事项:不填写len时,读取缓冲区中的全部数据;
填写的len小于等于缓冲区中的数据长度时,读取len长度的数据;
填写的len大于缓冲区中的数据长度时,读取缓冲区中的全部数据;
参数示例:uart.read(1, 1024);
返回值
s = uart.read(id, len)
log.info("uart", "receive", id, #s, s)
s
含义说明:读取到的字符串数据;
数据类型:string;
取值范围:无;
注意事项:无;
返回示例:"test";
示例
local function uart_cb(id, len)
local s = ""
repeat
s = uart.read(id, 1024) -- 一次性读出所有缓冲区中的数据,避免分包
if #s > 0 then -- #s 是取字符串的长度
-- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
log.info("uart", "receive", id, #s, s)
-- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
end
until s == ""
end
4.4 uart.close(id)
功能
关闭串口;
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.close(1)
返回值
无返回值
示例
uart.close(1)
4.5 uart.on(id, event, func)
功能
注册串口事件回调函数
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.on(1, "receive", uart_cb);
event
参数含义:触发的事件名称,相应事件发生时触发func回调函数;
数据类型:string;
取值范围:"receive":新数据接收完成或者接收缓冲满了;
"recv":新数据接收完成或者接收缓冲满了(等同于"receive");
"sent": 发送结束;
是否必选:必选;
注意事项:暂无;
参数示例:uart.on(1, "receive", uart_cb);
func
参数含义:注册回调函数,串口接收到数据,或者串口发送数据时触发回调函数;回调函数的格式为:
local function recv_cb(id, len)
-- id: number类型,串口id
-- len: 串口接收数据触发回调函数时,接收缓冲区中的数据长度
local data = uart.read(id, len)
log.info("uart", id, len, data)
end
local function sent_cb(id)
-- id: number类型,串口id
log.info("uart", id, "sent")
end
数据类型:function;
取值范围:无特别限制;
是否必选:必选;
注意事项:回调函数是在task之外的业务逻辑中被执行的,在回调函数内部无法使用
sys.wait(timeout)、sys.waitUntil(msg, timeout)、sys.waitMsg(task_name, msg, timeout)等必须用在task中的函数;
参数示例:如下所示,定义了一个函数id,len就可以做为此参数传入;
-- string方式读取数据
local function recv_cb(id, len)
local data = uart.read(id, len)
log.info("uart", id, len, data)
end
-- 或者zbuff方式读取数据
local function recv_cb(id, len) -- 串口接收数据回调函数
while 1 do
log.info("uart", "缓冲区", uart.rxSize(id)) -- 缓冲区中的数据数量
local len = uart.rx(id, rxbuff)
if len <= 0 then
break
end
log.info("uart", "receive", id, rxbuff:used(), rxbuff:toStr())
rxbuff:seek(0)
end
end
-- 串口发送数据回调
local function sent_cb(id)
-- id: number类型,串口id
log.info("uart", id, "sent")
end
返回值
无
示例
local function recv_cb(id, len)
local data = uart.read(id, len)
log.info("uart", id, len, data)
end
uart.on(uartid, "receive", recv_cb)
local function sent_cb(id)
log.info("uart", id, "sent")
end
uart.on(uartid, "sent",sent_cb)
4.6 uart.rx(id, buff)
功能
buff 形式读串口,一次读出全部数据存入 buff 中,串口接收缓冲区最大为 16K,16384 字节,所以一性需要接受的数据大于这个值时会分包;
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.rx(1, rxbuff);
buff
参数含义:zbuff对象,用于接收串口缓冲区中的数据,如果buff空间不足会自动扩容;
数据类型:zbuff;
取值范围:暂无;
是否必选:必选;
注意事项:需要先创建zbuff对象 local rxbuff = zbuff.create(1024);
参数示例:uart.rx(1, rxbuff);
返回值
local number = uart.rx(id, buff)
log.info("uart.rx", number)
number
含义说明:读取的数据长度;
数据类型:number;
取值范围:无;
注意事项:无;
返回示例:5;
示例
local function uart_cb(id, len) -- 串口接收数据回调函数
while 1 do
log.info("uart", "缓冲区", uart.rxSize(id)) -- 缓冲区中的数据数量
local len = uart.rx(id, rxbuff)
if len <= 0 then
break
end
log.info("uart", "receive", id, rxbuff:used(), rxbuff:toStr())
rxbuff:seek(0)
end
end
4.7 uart.rxSize(id)
功能
读取串口接收缓冲区剩余数据量;
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.rxSize(1);
返回值
local size = uart.rxSize(id)
log.info("uart", "缓冲区", size)
size
含义说明:返回的缓冲区数据的长度;
数据类型:number;
取值范围:无;
注意事项:无;
返回示例:5;
示例
local function uart_cb(id, len) -- 串口接收数据回调函数
log.info("uart", "缓冲区", uart.rxSize(id)) -- 缓冲区中的数据数量
end
4.8 uart.rxClear(id)
功能
清除串口接收缓冲区中剩余数据量;
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.rxClear(1);
返回值
无
示例
uart.rxClear(1)
4.9 uart.tx(id, buff, start, len)
功能
zbufff 方式发送串口数据;
参数
id
参数含义:串口id, uart0写0, uart1写1, 如此类推;
数据类型:number;
取值范围:最大值取决于设备;
是否必选:必选;
注意事项:暂无;
参数示例:uart.tx(uartid, txbuff,0,1024);
buff
参数含义:zbuff对象,待写入的数据,会从指针起始位置开始发送;
数据类型:zbuff;
取值范围:暂无;
是否必选:必选;
注意事项:需要创建zbuff对象并写有待发送的数据;
参数示例:local txbuff = zbuff.create(1024)
txbuff:write("测试数据")
uart.write(1, txbuff)
start
参数含义:要发送的数据起始位置,默认为0;
数据类型:number;
取值范围:0-zbuff的最大空间;
是否必选:可选;
注意事项:暂无;
参数示例:uart.tx(1, txbuff,0,1024);
len
参数含义:要发送的数据长度;
数据类型:number;
取值范围:0-zbuff的最大空间;
是否必选:可选;
注意事项:默认为zbuff内有效数据,最大值不超过zbuff的最大空间;
参数示例:uart.tx(1, txbuff,0,1024);
返回值
无
示例
uart.tx(1, txbuff)
五、产品支持说明
支持 LuatOS 开发的所有产品都支持 uart 核心库。