Air724UG之串口通信

简介

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

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值