简介
Air724UG有多个串口,但是用于和外部模块或者单片机进行通信的,只推荐使用UART1或UART3。
UART2 在开机后会自动打印一段log,波特率921600,这段log不能通过修改软件来关闭,所以推荐优先使用UART1 和 UART3。
Air820内部的GPS模块占用了UART3,所以用户只能使用UART1。
串口电平转换
UART1和UART3都是1.8V电平逻辑的,因此和其他串口通信时要做电平转换。
下面是使用分立元件搭建的stm32与Air724串口通信的电平转换电路,实现了3.3V到1.8V串口电平的转换。
串口初始化
-- 带有[]代表带有默认值的可选参数
uart.setup( id, baud, databits, parity, stopbits,
[msgmode],
[txDoneReport],
[flowcontrol] )
--例子:
uart.setup( 1, 9600, 8, uart.PAR_NONE, uart.STOP_1,0,0,0)
参数1:id,串口编号。1(UART1),2(UART2),3(UART3),0x81(USB)
参数2:baud,波特率设置。可选1200,2400,4800,9600,10400,14400,19200,28800,38400,57600,115200,230400,460800,921600
参数3: databits,数据位长度,只能填8
参数4:parity,校验方式。uart.PAR_EVEN, 偶校验;uart.PAR_ODD,奇校验;uart.PAR_NONE,无校验
参数5:stopbits,停止位位数。uart.STOP_1,一位停止位;uart.STOP_2,两位停止位;
参数6:msgmode,串口消息接收模式。0:默认值,启用数据接收事件通知机制,当串口收到一包数据时,会产生“receive事件”,系统会自动调用用户注册的事件处理函数。1:关闭数据接收事件通知机制,用户需要使用轮训法来接收串口数据。
参数7:txDoneReport,串口数据发送完成通知开关。0:默认值,关闭数据发送完成事件通知机制。1:开启数据发送完成事件通知机制。当使用uart.write发送一包数据完成后,将产生"sent"事件,系统自动调用用户注册的事件处理函数。
参数8:flowcontrol,硬流控功能。0:关闭(默认),1:打开
串口数据发送
--这是一个变长参数函数
uart.write( id, data1, [data2], …[datan] )
--例子:
uart.write(1,"hello world") --uart1发送字符串
uart.write(1,0x5A) --uart1发送整数0x5A
uart.write(1,0x5A,"hello") --uart1发送整数0x5A和字符串
参数1:id,串口编号。1(UART1),2(UART2),3(UART3),0x81(USB)
参数2~n:发送的数据,可以是number或者string类型
串口数据接收
使用uart.read()从底层的接收缓冲区读取数据。那么底层缓冲区有数据后,应用层代码如何收到通知呢?这就需要使用uart.on()来注册。
当uart.setup()的第6个参数msgmode为0时,就启用了数据接收事件通知机制。这种情况下,当串口底层的接收缓冲区从空状态转换为有数据可读状态时,就会触发'receive'接收事件。通使用uart.on()来注册事件处理函数,就可以在串口触发'receive'事件时,调用注册的接收事件处理函数。注意,当缓冲区为空时,收到数据插入缓冲区,然后才产生数据中断消息;如果缓冲区不为空,收到数据时仅仅插入缓冲区,并不会产生数据中断消息。所以在接收事件处理函数中,要循环读取串口数据,直到把缓冲区中的数据读完,这样才能保证下次收到的数据,可以产生中断消息。
同样的道理,串口在发送完成数据后,也会产生一个"sent"事件,如果需要启用这个机制,则art.setup()的第7个参数txDoneReport要设置为1。
uart.on (id, event, callback)
--例子:
--定义串口1的接收中断函数
local function uart1ReceiveCb()
local data=""
local temp=""
while true do
temp = uart.read(UART_ID_1,10) --每次尝试读10字节
if not temp or string.len(temp) == 0 then --如果把接收缓冲区读空了
break
else
data = data..temp --拼接
end
end
--log.info("uart1",#data) --log打印
--处理接收到的报文
uart1ProcRecv(data)
end
--注册UART1的 "receive" 事件处理函数
uart.on(1,"receive",uart1ReceiveCb)
--函数
--详见:https://doc.openluat.com/wiki/21?wiki_page_id=2250
uart.read( id, format)
--如果参数format传递一个数字,则代表从接收缓冲区读取指定长度的数据。下面是读取1024个字节。
--如果缓冲区中没有数据,则返回空字符串,返回值为string类型
--如果缓冲区中的数据长度小于等于要读取的数据长度,则返回缓冲区中的所有数据,返回值为string类型
--如果缓冲区中的数据长度大于要读取的数据长度,则返回要读取的长度的数据,返回值为string类型
--如果对方发送的是10进制字节数据:97,98,99,则此函数返回的是字符串 "abc"
uart.read(1,1024)
--从缓冲区读数据,一直读取到换行符\n
-- 如果缓冲区中没有数据,则返回空字符串,返回值为string类型
-- 如果缓冲区中的数据没有\n,则返回缓冲区中的所有数据,返回值为string类型
-- 如果缓冲区中的数据有\n,则返回到\n结束的所有数据(包括\n),返回值为string类型
uart.read(1,"*l")
sent事件
当发送数据比较频繁时,需要保证上一包数据发送完成,才能进行当前一包数据的发送,这个时候可能需要用到sent事件,sent事件可以这样用:
local uart1_tc = true --发送完成标志
--初始化串口1
--启用数据接收事件通知机制
--启用数据发送完成事件通知机制
uart.setup(UART1_ID, 115200, 8, uart.PAR_NONE, uart.STOP_1,0,1,0)
--定义sent事件回调函数
local function uart1SentCb()
uart1_tc = true
end
--注册sent事件回调函数
uart.on(UART1_ID,"sent",uart1SentCb)
sys.taskInit(
function ()
while true do
sys.wait(200)
--等待发送完成
while not uart1_tc do end
uart1_tc = false --设置发送完成标志为false
uart.write(UART1_ID,"hello world\n")
end
end
)
一个完整的例子
使用串口1,波特率115200,间隔1s发送数据。串口1收到的数据则通过LOG打印出来。
--必须在这个位置定义PROJECT和VERSION变量
PROJECT = "TestUART"
VERSION = "1.0.0"
require "sys"
--加载日志功能模块,并且设置日志输出等级
--如果关闭调用log模块接口输出的日志,等级设置为log.LOG_SILENT即可
require "log"
LOG_LEVEL = log.LOGLEVEL_TRACE
--[[
如果使用UART输出日志,打开这行注释的代码"--log.openTrace(true,1,115200)"即可,根据自己的需求修改此接口的参数
如果要彻底关闭脚本中的输出日志(包括调用log模块接口和Lua标准print接口输出的日志),执行log.openTrace(false,第二个参数跟调用openTrace接口打开日志的第二个参数相同),例如:
1、没有调用过sys.opntrace配置日志输出端口或者最后一次是调用log.openTrace(true,nil,921600)配置日志输出端口,此时要关闭输出日志,直接调用log.openTrace(false)即可
2、最后一次是调用log.openTrace(true,1,115200)配置日志输出端口,此时要关闭输出日志,直接调用log.openTrace(false,1)即可
]]
--log.openTrace(true,1,115200)
require "net"
--每1分钟查询一次GSM信号强度
--每1分钟查询一次基站信息
net.startQueryAll(60000, 60000)
--此处关闭RNDIS网卡功能
--否则,模块通过USB连接电脑后,会在电脑的网络适配器中枚举一个RNDIS网卡,电脑默认使用此网卡上网,导致模块使用的sim卡流量流失
--如果项目中需要打开此功能,把ril.request("AT+RNDISCALL=0,1")修改为ril.request("AT+RNDISCALL=1,1")即可
--注意:core固件:V0030以及之后的版本、V3028以及之后的版本,才以稳定地支持此功能
ril.request("AT+RNDISCALL=0,1")
--========================================================================
--定义串口1的接收中断处理函数
local function uart1ReceiveCb()
local data=""
local temp=""
while true do
temp = uart.read(1,10) --每次尝试读10字节
if not temp or string.len(temp) == 0 then --如果把接收缓冲区读空了
break
else
data = data..temp --拼接
end
end
--处理接收到的报文
log.info("uart1 recv",data) --log打印收到的数据
end
--注册串口的数据接收函数,串口收到数据后,会以中断方式,调用uart1ReceiveCb接口读取数据
uart.on(1,"receive",uart1ReceiveCb)
--串口初始化
uart.setup(1,115200,8,uart.PAR_NONE,uart.STOP_1,0,0,0)
--开一个任务,间隔1s使用串口1输出字符串
sys.taskInit(
function ()
while true do
sys.wait(1000)
uart.write(1,"hello uart1")
end
end
)
--启动系统框架
--这个代码后面不能再有其他代码
sys.init(0, 0)
sys.run()