5.3 LUA 串口接收
LUA 中自由串口协议中,接收回调函数为 on_uart_recv_data(packet)
函数名: on_uart_recv_data(packet)
形参: packet, 下表从 0 开始,表示接收的字节数组
5.3.1 帧头+帧尾
以帧头 0x5A、 帧尾 0xA5 0x5A 0xA5 0xA5、 含 CRC16 校验为例,屏幕对该帧结构做
以下解析示例。 源码可参考《1.帧头+帧尾(Header+End) .rar》
基本思路:
1. 触发 on_uart_recv_data(packet),检索是否有帧头 0x5A; 当检索到帧头且标
志 cmd_head_tag=0 时,将帧头标志位置位 cmd_head_tag = 1
2. 开始填充缓存 buff
3. 检测到帧尾 cmd_head_tag = 0XA55AA5A5,表示接收到完整一帧数据
4. 调用 add_crc16(start, n, data), 进行 CRC16 检验
5. 检验成功,调用 my_processmessage(msg)执行相关操作
6. 最后清除相关的标记和缓冲,完成一帧的读取, 继续获取下一帧数据
代码清单如程序清单 1 所示:
local cmd_end = 0XA55AA55A --帧尾
local buff = {} --缓冲区
local cmd_length = 0 --帧长度
local cmd_head_tag = 0 --帧头标识
local cmd_end_tag = 0 --帧尾标识
--calculate CRC16
--@data: t,data to be verified
--@n:number of verified
--@return :cheak result
function add_crc16(start,n,data)
local carry_flag
local a = 0
local result = 0Xffff
local i = start
while(true)
do
result = result ~ data[i]
--是因为七个字节然后,进行校验吗
for j = 0,7
do
a = result
carry_flag = a&0x0001
result = result >> 1
if carry_flag == 1
then
result = result ~ 0xa001
end
end
i = i+1
if i == start + n
then
break
end
end
return result
end
--Instruction analysis
--@msg:data table
function my_processmessage(msg)
--帧头用于区分功能,如果帧头msg[1]==Func_lampState,用于调节开关,并获取数据
local funncode = msg[1]
if funccode == Func_lampState --确定改变灯开关
then
--确定更改状态,把信息传递到xth_lamp和xth_lamp_state的状态。
local xth_lamp = msg[2]
local xth_lamp_state = msg[3]
my_set_lamp_state(xth_lamp,xth_lamp_state)
elseif funccode == Func_lampLight --确定改变灯亮度
then
local xth_lamp = msg[2]
local xth_lamp_light = msg[3]
my_set_lamp_light(xth_lamp,xth_lamp_state)
end
end
-- 系统函数: 初始化 :启动串口
function on_init()
uart_set_timeout(0, 0)
end
--系统函数:初始化,最重要数据处理函数
function on_uart_recv_data(packet) --packet装的是什么数据呢?
--获取数据报文的长度,
-- # 一元运算符,#返回字符串或表的长度。例子:#"Hello" 返回 5
local recv_packet_size = (#(packet))
local check16 = 0
for i = 0 ,recv_packet_size --写一个for循环来读取数据
do
--检测帧头
if packet[i] == cmd_head and cmd_head_tag == 0
then--如果满足就cmd_head_tag置1
cmd_head_tag = 1
end
--找到帧头以后
if cmd_head_tag == 1
then --缓存区装取数据,cmd_length初始化为0
buff[cmd_length] = pack[i] --向缓存区存储数据
cmd_length = cmd_length+1
--cmd_end_tag初始化为零
cmd_end_tag = (cmd_end_tag<<8)|(packet[i]) --这句话怎么理解,有点不太到位
--当找到尾部帧的时候:
if(cmd_end_tag&cmd_end)==cmd_end --这里为啥要与一下,怎么理解
then
--把校验码合成出来
check16 = ((buff[cmd_length-6]<<8)|buff[cmd_lenth-5])&0xFFFF
--进行校验
if check16 == add_crc16(1,cmd_length-7,buff) --crc校验为啥是剪掉7个字节呢
then --存数据+清除
my_processmessage(buff)
buff = {}
cmd_length = 0
cmd_end_tag = 0
cmd_head_tag = 0
else
--数据不对,直接清零
buff = {}
cmd_length = 0
cmd_end_tag = 0
cmd_head_tag = 0
end
end
end
end
end