基于Lua脚本语言的嵌入式UART通信的实现
{"set_tx_buf",set_tx_buf},
{"get_tx_buf", get_tx_buf},
{"uart_ok_del", uart_ok_de},
{NULL, NULL}
};
③ 调用以下函数对C函数库进行注册:luaL_register(L, "ied", uartLib );其中,参数L即为创建虚拟机时的函数返回值(以下同),字符串"ied"为注册到虚拟机中的库名称。第3个参数uartLib即为前面声明的结构数组,对应需要注册的库函数表。
通过以上步骤,即可完成Lua脚本中需要调用的3个C函数的注册过程,从而就可以在Lua脚本中通过"库名称。库函数"的形式来对其进行调用,如"ied.set_tx_buf(函数参数)"。
脚本文件本身的加载则相对简单,只需通过如下函数调用即可:
luaL_dofile(L, "uart_script.lua");
其中,参数L和以上的函数调用相同,第2个参数则为脚本文件在Flash中的具体存储路径。
至此,就成功建立了一个Lua与C的交互环境。
3.2 提取脚本中的串口配置数据
要正确地进行Lua和C的交互过程,首先必须对Lua和C交互时所采用虚拟栈的作用和操作有比较深入的了解。在Lua和C的交互中,它们彼此之间函数参数以及返回值都将由该栈来负责传递。Lua和C在栈的操作方式上稍有不同,在Lua中采用严格的LIFO方式,而C则还可以通过索引的方式进行。以3个参数为例,参数1首先入栈,参数2、3随后顺次入栈,Lua虚拟栈存储结构及索引对应关系如图3所示。
图3 Lua虚拟栈结构示例图
如需在C中访问参数1,则既可以通过索引号1进行,也可通过索引号-3进行。其中,正索引按入栈顺序从1依次递增,负索引按出栈顺序从-1依次递减。
通常情况下,串口的配置主要有以下几项:是否使能、数据位数、停止位数、奇偶校验标志位和波特率。因此,在Lua脚本中,本文采用Lua的表结构对其进行设置,示例如下(本文中斜体代码表示为Lua脚本,以下同):
uart_p0={
enable=1,--使能位
dataBits=8 , --数据位数
stopBits=1 , --停止位数
parityBit=2 , --奇偶校验
baudRate=9600 --波特率
};
该例表示对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个元素出栈。
通过以上操作,就可以正确地取出脚本中p0口参数设置表中enable属性字段的值。其他属性字段的提取与其相同。虚拟栈中的内容变化如图4所示。
图4 提取表中属性值时的虚拟栈操作示意图
3.3 调用Lua函数设置发送缓冲区
为通过Lua脚本对串口发送缓冲区进行设置,在脚本中定义了如下函数:
data ={0x11, 0x22, 0x33, 0x44, 0x55 };
function uart_p0_set_txBuf()
local port=0;
local p0_send_num=5;
for i=1, p0_send_num do
ied.set_tx_buf(port,i-1, data[i])
end
return p0_send_num
end
从脚本内容可以看出,在此采用了一个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所示。
图5 函数调用时的虚拟栈示例
- 基于嵌入式系统的USBtoUART通信设计方案(12-16)
- 51单片机UART通信程序(11-30)
- 51单片机UART通信[发送接收数字字母中文,控制LED亮灭](11-20)
- 51单片机UART通信发送接收数字字母中文,控制LED亮灭(11-19)
- MIPS架构下PIC单片机的UART通信(11-22)