asp向串口发送_Luat系列官方教程7:串口收发

e3368be2e7e49b1790de591f1c9f1ff6.png

大家好,这一期特别推出晨旭大神Luat系列教程之串口收发。对之前教程感兴趣的同学,可查看文末相关链接。另外透露一下:晨旭大神结合实践的Lua语法学习工具值得关注,敬请期待~

阅读本文需要具有的技能:

看过该系列前几篇文章或明白前几篇文章内容的
可以明白字符串、字节码之间的区别
了解串口的原理和使用

文章篇幅较长,以下内容建议横屏查看,或在PC端打开本文链接。

官方demo代码

官方代码可以在github(https://github.com/openLuat/Luat_2G_RDA_8955/)的`Luat_2G_RDA_8955/script_LuaTask/demo/uart`目录,

或luatools的`LuaTools 1.x.x\script\script_LuaTask\demo\uart`目录找到。

如果你能看懂官方例程,那么可以直接去使用,不需要再看本文了。

1

先定义一个假装能用来测试的串口收发规则

  • 串口通讯使用9600波特率,3.3V ttl电平;

  • 模块开机第10秒后,向设备发送0x01 0x02 0x03三个字节;

  • 模块收到qwerty字符串后,回复asdfgh字符串;

  • 模块收到0xaa 0xbb 0xcc三个字节后,回复0xdd 0xee 0xff三个字节;

  • 模块收到abcdefghijklmnopqrstuvwxyz字符串后,回复ok字符串;

2

代码详解

2.1 建立文件结构

测试需要新建两个文件:

main.luatestuart.lua

main.lua在前面的文章中,已经新建过大概不下四次了,所以这里不再举例。

main.lua需要require"testuart"

testuart.lua

module(...,package.seeall)

require"utils"

require"pm"

--串口ID,1对应uart1

--如果要修改为uart2,把UART_ID赋值为2即可

local UART_ID = 1

--保持系统处于唤醒状态,此处只是为了测试需要,所以此模块没有地方调用pm.sleep("testUart")休眠,不会进入低功耗休眠状态

--在开发“要求功耗低”的项目时,一定要想办法保证pm.wake("testUart")后,在不需要串口时调用pm.sleep("testUart")

pm.wake("testUart")

--配置并且打开串口

uart.setup(UART_ID,9600,8,uart.PAR_NONE,uart.STOP_1)

可以看到,uart文件中已经配置好了串口。

2.2 发送串口信息

发送接口特别简单,只需要调用uart.write()函数即可,我们可以在设置唤醒状态代码前面加上发送函数:

--发送串口数据

function write(s)

   log.info("testuart.write",s:toHex(),s)

   uart.write(UART_ID,s)

end

2.3 接收串口信息

为了能接收到串口消息,我们在配置并且打开串口函数的上方注册串口接收函数:

--注册串口的数据接收函数,串口收到数据后,会以中断方式,调用read接口读取数据

uart.on(UART_ID,"receive",read)

并在发送函数上方新建接收函数:

--接收串口数据

local function read()

   local data = ""

   --底层core中,串口收到数据时:

   --如果接收缓冲区为空,则会以中断方式通知Lua脚本收到了新数据;

   --如果接收缓冲器不为空,则不会通知Lua脚本

   --所以Lua脚本中收到中断读串口数据时,每次都要把接收缓冲区中的数据全部读出,这样才能保证底层core中的新数据中断上来,此read函数中的while语句中就保证了这一点

   while true do        

       data = uart.read(UART_ID,"*l")

       --数据不存在时停止接收数据

       if not data or string.len(data) == 0 then break end

       --打开下面的打印会耗时

       log.info("testUart.read bin",data)

       log.info("testUart.read hex",data:toHex())

       --真正的串口数据处理函数

       proc(data)

   end

end

我们可以看到,所有串口数据都交给了proc()函数进行处理,我们可以在接收函数上方新建一个proc()函数:

--处理串口数据

local function proc(data)

   --todo

end

2.4 实现功能

2.4.1 模块开机第10秒后,向设备发送0x01 0x02 0x03三个字节

实现这个功能,我们只需要在文件末尾加上一个定时器即可:

--模块开机第10秒后,向设备发送`0x01 0x02 0x03`三个字节

sys.timerStart(function()

   write(string.fromHex("010203"))

end,10000)

2.4.2 模块收到qwerty字符串后,回复asdfgh字符串

处理这个信息,可以去proc()函数里进行修改,将函数更改为如下形式:

--处理串口数据

local function proc(data)

   if data == "qwerty" then

       --模块收到`qwerty`字符串后,回复`asdfgh`字符串

       write("asdfgh")

   end

end

2.4.3 剩下两个需求

剩下两个需求处理起来和前面一样,我们直接仿照着改就行:

--处理串口数据

local function proc(data)

   if data == "qwerty" then

       --模块收到`qwerty`字符串后,回复`asdfgh`字符串

       write("asdfgh")

   elseif data == string.fromHex("AABBCC") then

       --模块收到`0xaa 0xbb 0xcc`三个字节后,回复`0xdd 0xee 0xff`三个字节

       write(string.fromHex("DDEEFF"))

   elseif data == "abcdefghijklmnopqrstuvwxyz" then

       --模块收到`abcdefghijklmnopqrstuvwxyz`字符串后,回复`ok`字符串

       write("ok")

   end

end

2.5 测试

这个测试需要大家自己去测试了。

测试结果会发现,第三条指令无法完成。为什么呢?因为串口会有截断现象。

2.6 处理串口数据截断问题

串口数据接收经常会出现的一个问题:数据被截断。


这个现象很常见,你可以像普通单片机一样一个字节一个字节去解析,也可以加一个缓冲区定时清空处理。

我们首先在proc()函数上方,新建一个缓冲区:

local buf = ""

然后可以把proc()函数改造成下面这样:

--缓存数据

local buf = ""

--处理串口数据

local function proc(data)

   data = buf..data

   log.info("testUart.read proc",data)

   local used = true--数据是否被处理?

   if data == "qwerty" then

       --模块收到`qwerty`字符串后,回复`asdfgh`字符串

       write("asdfgh")

   elseif data == string.fromHex("AABBCC") then

       --模块收到`0xaa 0xbb 0xcc`三个字节后,回复`0xdd 0xee 0xff`三个字节

       write(string.fromHex("DDEEFF"))

   elseif data == "abcdefghijklmnopqrstuvwxyz" then

       --模块收到`abcdefghijklmnopqrstuvwxyz`字符串后,回复`ok`字符串

       write("ok")

   else

       --数据没匹配上任何东西,没被使用

       used = false

   end

   if not used then--数据没被使用

       if buf == "" then--如果缓冲区是空的

           sys.timerStart(function()

               buf = ""

           end,500)--500ms后清空缓冲区

       end

       buf = data--数据追加到缓存区

   else

       buf = ""

   end

end

函数中首先判断数据是否被使用,如果没被使用,就将数据追加到缓冲区,如果已被使用,缓冲区内容会被清除。

3

完整代码

经过一系列修改,testuart.lua整体代码如下:

module(...,package.seeall)

require"utils"

require"pm"

--串口ID,1对应uart1

--如果要修改为uart2,把UART_ID赋值为2即可

local UART_ID = 1

--缓存数据

local buf = ""

--处理串口数据

local function proc(data)

   data = buf..data

   log.info("testUart.read proc",data)

   local used = true--数据是否被处理?

   if data == "qwerty" then

       --模块收到`qwerty`字符串后,回复`asdfgh`字符串

       write("asdfgh")

   elseif data == string.fromHex("AABBCC") then

       --模块收到`0xaa 0xbb 0xcc`三个字节后,回复`0xdd 0xee 0xff`三个字节

       write(string.fromHex("DDEEFF"))

   elseif data == "abcdefghijklmnopqrstuvwxyz" then

       --模块收到`abcdefghijklmnopqrstuvwxyz`字符串后,回复`ok`字符串

       write("ok")

   else

       --数据没匹配上任何东西,没被使用

       used = false

   end

   if not used then--数据没被使用

       if buf == "" then--如果缓冲区是空的

           sys.timerStart(function()

               buf = ""

           end,500)--500ms后清空缓冲区

       end

       buf = data--数据追加到缓存区

   else

       buf = ""

   end

end

--接收串口数据

local function read()

   local data = ""

   --底层core中,串口收到数据时:

   --如果接收缓冲区为空,则会以中断方式通知Lua脚本收到了新数据;

   --如果接收缓冲器不为空,则不会通知Lua脚本

   --所以Lua脚本中收到中断读串口数据时,每次都要把接收缓冲区中的数据全部读出,这样才能保证底层core中的新数据中断上来,此read函数中的while语句中就保证了这一点

   while true do

       data = uart.read(UART_ID,"*l")

       --数据不存在时停止接收数据

       if not data or string.len(data) == 0 then break end

       --打开下面的打印会耗时

       log.info("testUart.read bin",data)

       log.info("testUart.read hex",data:toHex())

       --真正的串口数据处理函数

       proc(data)

   end

end

--发送串口数据

function write(s)

   log.info("testuart.write",s:toHex(),s)

   uart.write(UART_ID,s)

end

--保持系统处于唤醒状态,此处只是为了测试需要,所以此模块没有地方调用pm.sleep("testUart")休眠,不会进入低功耗休眠状态

--在开发“要求功耗低”的项目时,一定要想办法保证pm.wake("testUart")后,在不需要串口时调用pm.sleep("testUart")

pm.wake("testUart")

--注册串口的数据接收函数,串口收到数据后,会以中断方式,调用read接口读取数据

uart.on(UART_ID,"receive",read)

--配置并且打开串口

uart.setup(UART_ID,9600,8,uart.PAR_NONE,uart.STOP_1)

--模块开机第10秒后,向设备发送`0x01 0x02 0x03`三个字节

sys.timerStart(function()

   write(string.fromHex("010203"))

end,10000)

4

最终测试

4.1 开机后发送第10秒后,向设备发送0x01 0x02 0x03三个字节:

ab21fe1016378f1f88512890dd4810f1.png

4.2 模块收到qwerty字符串后,回复asdfgh字符串:

fa2cdb7682233588973e5ab5b94e204f.png

4.3 模块收到0xaa 0xbb 0xcc三个字节后,回复0xdd 0xee 0xff三个字节:

40a2a53ed52fe7c7ab6e2ca5571c6c5a.png

4.4 模块收到abcdefghijklmnopqrstuvwxyz字符串后,回复ok字符串:

240693db208b9aaea35c239fba658c34.png

以上就是Luat串口收发的完整操作,是不是比较简单呢,赶快试试吧~

bfec0206ed392689d6c1112a0c9b89f0.gif

93974356636d86fe950358737d445e22.gif

更多福利,敬请期待

ba0622b59d367888adc51b046acf4a9a.gif

Luat相关教程文章: Luat系列官方教程1:下载调试工具LuaTools的使用指南 Luat系列官方教程2:控制LED小灯

Luat系列官方教程3:Luat程序的基本时序

Luat系列官方教程4:学会使用并看懂Luatools的trace信息

Luat系列官方教程5: Socket代码详解 Luat系列官方教程6: MQTT代码详解

Luat小企业系列原创文章:

小企业怎么寻找生意的蓝海?

小企业2B新产品怎样定价?

小企业的2B业务怎么获客(一)?

合宙Luat将陆续推出小企业系列原创作品,敬请关注!

1f2f875094d25d59a6cbe7c13bd5d44e.png

96a8bb321502163a41cecd5034bc3ecf.png

 ▼ Luat热文推荐 ▼

>小企业怎么寻找生意的蓝海?

>NB-IoT,未来的物联网脊梁,还是扶不起的阿斗?

>2019年最值得工作和落户的几个城市,有你的家乡吗?

>为什么说『 物联网通信模块业务』没有前途?

>4G模块价格进入2位数时代,合宙Air720模块正式量产发货

>NB向左,GPRS向右,谁会率先突破百亿连接数?

>GPRS模块为什么会低至十几元?我所经历的物联网模块国产化过程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值