填坑
上一年学校开了门IOT的课程,看了下ESP8266相关的信息,当时候由于赶时间,就把里面的固件刷成了MicroPython,然后在里面随便调用了几个传感器的库,然后定时上报给服务器就拿去答辩了
然后最近去买电子原件顺手买了两片来玩,顺便把Lua简单语法过了一遍,填上了Lua的坑。ESP8266的社区生态挺完善的,很多的传感器直接调库就好了,但是有一些传感器需要自己写驱动来控制和读取。
又一坑
我在写驱动GP2Y1010AU0F的时候,需要产生一个0.32ms的高电平,但是我试了一下Nodemcu最短只能延时1ms……所以需要自己编写C语言库来实现更加短的延时和其他更底层的控制
编写C语言库:
本文基于ESP8266芯片的nodemcu-firmware
头文件
在源码中添加如下头文件:
#include "lualib.h"
#include "lauxlib.h" //导入lua相关数据类型
#include "platform.h" //导入Nodemcu的gpio相关操作(uart,i2c,spi,pwd,adc...)
#include "module.h" //用于导出C语言函数
#include "c_types.h"
#include "c_string.h" //移植到ESP8266的C语言标准库
自定义函数
Lua 使用一个 虚拟栈 来和 C 互传值。 栈上的的每个元素都是一个 Lua 值 (nil,数字,字符串,等等)。
自定义的函数返回值必须为整型,并且返回的数字等于函数返回到Lua的返回值的个数
自定义函数参数列表只需要定义一个lua_State *L
The L is a Lua State and you can read about it in the Extending your Application,
Calling C from Lua, and Manual。
int example_function(lua_State *L)
{
//从栈中获取函数参数
double a=luaL_checknumber(L,1); //从栈中取出一个double
int b=(int)luaL_checkinteger(L,2);
const char *c=luaL_checklstring(L,3,NULL); //从栈中取出一个字符串
os_printf("From C Library:%s\n",c); //esp8266_non_os_sdk_api
char rc[100];
int index=0;
for(int i=c_strlen(c)-1;i>=0;i--)
rc[index++]=c[i];
rc[index]='\0';
//压栈传返回值到Lua
lua_pushnumber(L,(a+b)/(a-b)); //往栈中压入一个浮点型数
lua_pushstring(L,rc); //往栈中压入一个字符串
return 2; //返回了一个浮点数,一个字符串,所以应该返回2
}
导出函数
导出函数根据官方样例的格式,把自定义的函数导出以便Lua调用:
const LUA_REG_TYPE example_map[]=
{
{LSTRKEY("calc"),LFUNCVAL(example_function)},
{LNILKEY,LNILVAL}
};
NODEMCU_MODULE(EXAMPLE,"example",example_map,NULL);
整合C模块到Nodemcu
在app/include/user_modules.h
中插入:#define LUA_USE_MODULES_EXAMPLE
编译&烧写
$ make
$ sudo make flash4m //根据不同ESP8266版本而定
测试
{% asset_img 1.png %}