基于Lua脚本语言的嵌入式UART通信方案设计
通过以上操作,就可以正确地取出脚本中p0口参数没置表中cnable属性字段的值。其他属性字段的提取与其相同。虚拟栈中的内容变化如图4所示。 从而在C程序中,只需要调用下面语句即可将该串口发送缓冲区中索引为1的内存区域没置成0x22:
如需在C中访问参数1,则既可以通过索引号1进行,也可通过索引号-3进行。其中,正索引按入栈顺序从1依次递增,负索引按出栈顺序从-1依次递减。
通常情况下,串口的配置主要有以下几项:是否使能、数据位数、停止位数、奇偶校验标志位和波特率。因此,在Lua脚本中,本文采用Lua的表结构对其进行设置,示例如下(本文中斜体代码表示为Lua脚本,以下同):
该例表示对UART芯片的P0 口进行使能,并且采用8位数据位、1位停止位、偶校验(本文定义parityBit的值取0为无校验,取1为奇校验,取2为偶校验)的帧格式,波特率为9 600 bps。
在C语言中,要获取表中enable属性字段的值,可采用以下步骤:
①调用接口函数并以表名称作为参数,将该表入栈:
lua_getglobal(L,“uart_p0”);
②调用接口函数将enable属性字段的属性名称入栈:
lua_pushstring(L,“enable”);
③调用接口函数提取属性值,该操作在C中可看作是一个先出栈再入栈的过程,结果将在②中已入栈的属性名称所在位置填入属性值:
lua_gettable(L,-2);
其中,参数“-2”为栈中的索引号。
④调用接口函数取出栈顶中该属性字段的值,并调用出栈函数,以恢复调用环境:
p0_enable=(int)lua_tonumber(L,-1);
lua_pop(L,1);
其中,lua_tonumber函数的参数“-1”也为栈中的索引号,该操作将取出栈顶元素的数值,鉴于Lua中的数据都为浮点数,所以需将其强制转换为整型数据。lua_pop中参数“1”为非索引,仅说明从栈顶将1个元素出栈。
3.3 调用Lua函数设置发送缓冲区
为通过Lua脚本对串口发送缓冲区进行设置,在脚本中定义了如下函数:
从脚本内容可以看出,在此采用了一个Lua中的循环结构对发送缓冲区进行没置,并返回设置的数据个数。其中,全局变量data是Lua脚本巾的表,类似于数组,在此表示需要设置的缓冲区内容;ied.set_tx_buf()为在3.1节中提到的已注册到虚拟机中的C函数库中的一个函数。其参数port表示端口号,i-1表示缓冲区索引号,data[i]表示具体的数据内容。在应用中需要注意的是,在Lua中,数组索引默认从1开始,而不像C中从0开始。另外,在C中定义set_tx_buf函数时并未设置参数,这主要是因为参数的提取必须借助于虚拟栈才能实现。在脚本中调用时,对其参数将按照从左到右的顺序依次入栈,在C中要取出参数时,按照其在栈中相应的索引号取出即可。存Lua中对每个函数的调用都有一个独立的栈,因此,若以i取2时调用情况为例,在C函数set_tx_buf中看到的栈内容将如图5所示。
当在C程序中需对串口发送缓冲区进行设置时,将按如下方法调用该脚本函数:
lua_getglobal(L,“uart_p0_set_txBuf”);
lua pcall(L,0.1,0);
其中,函数lua_getglobal的参数“uart_p0_set_txBuf”为要调用的脚本函数名,函数lua_pcall的函数原型为:
因所调用的脚本函数uart_p0_set_txBuf没有参数,有一个返回值,所以分别将nargs、nresults置为0、1,而错误处理函数暂不使用,故置为0。
对于脚本中的返回值,将在脚本函数调用结束时,置于lua_pcall调用环境所在的虚拟栈的栈顶中,可由C程序根据索引取出。
经以上过程,就完成了对串口发送缓冲区的内容设置,然后就可以通过串口芯片的驱动程序将其发送到外围设备。
在现场应用时,只需根据不同外围设备问询报文的要求来修改脚本中data数组以及p0_send_num变量的内容即可,而不用对装置的C程序进行任何修改。
3.4 通过Lua函数处理接收缓冲区数据
通过Lua和C的交互来对串口接收缓冲区数据的处理方法同发送缓冲区的处理基本相似。
当装置通过串口驱动程序将外围设备发来的数据置入接收缓冲区后,在C函数中调用脚本函数:
lua_getglobal(L,“uart p0_del_rxBuf”);
lua pushnumber(L,size);
ret=lua_pcall(L,1.1,0);
其中,参数uart_p0_del_rxBuf为脚本中定义的缓冲区数据处理函数名,通过lua_pushnumber将接收数据的大小入栈,从而传给Lua脚本函数,脚本函数的原型如下:
function uart_p0_del_rxBuf(rx_size)
在该函数中,可通过调用注册的C函数get_rx_buf来获取接收缓冲区中的内容:
data[i]=ied.get_rx_buf(port,index)
其中,data为脚本中类似于数组的表类型。port为串口芯片的端口号,index为缓冲区的索引号,在C程序中通过以下语句对脚本返回所取数据值:
可以看出,在脚本中也是借助于虚拟栈来获取C程序的返回值。通过以上方法成功获取了串口接收缓存区的内容后,就可根据具体的外围设备在脚本中对其接收数据的正确性进行判断,如果判断结果正确,则调用前面注册的C函数uart_ok_del进行相关业务处理。
ied.uart_ok_del(port)
结语
从本文提供的方案可以看出,从始至终,IED装置的C语言应用程序在lua虚拟机与外围设备之间,除了报文的透明传输功能外,并不负责具体数据业务的处理,这就使在C程序的设计中完全不需要考虑外围设备所采用的串口通信数据格式,具体的数据内容都可放在脚本文件中进行没置和处理。在现场应用中,就可以达到仅修改Lua脚本文件就能完成IED装置与不同的串口通信外围设备之间的数据交互功能,从而实现对装置串口通信规约的现场可配置化。
UART 通信 方案设计 嵌入式 语言 Lua 脚本 基于 相关文章:
- 使用IDE降低您的MCU功耗(05-29)
- 如何解决UART通信的射频干扰问题(09-06)
- 串口通讯基础及S3C2410 UART控制器(12-06)
- 单片机IO口模拟UART串口通信(12-26)
- 直接数字合成技术实现函数信号发生器(12-09)
- 一种基于USB/RS232的无线通讯终端系统设计(03-25)