闲言碎语
这回来了解一下nodeMCU的串口模块。串口应该是我们用的最多的一个模块了,lua脚本都是通过串口传到mcu上面的。这部分的内容很少,只有4个函数。文档中提到了默认的波特率是115200,且在上电的前2分钟内启动了自动波特率功能。
模块函数
仅有4个函数,都很简单。
序号 | 函数名 | 参数 | 返回值 |
---|---|---|---|
1 | uart.alt() | on | nil |
2 | uart.on() | method, [number/end_char], [function], [run_input] | nil |
3 | uart.setup() | id, baud, databits, parity, stopbits, echo | number |
4 | uart.write() | id, data1 [, data2, ...] | nil |
- .alt可以重映射串口pin。传入1将pin映射到13、15。
- .on用来设置串口接收回调函数。第一个参数现在只能传入"data"。参数2可以传入数字或者仅有单个字符的字符串,例如传入6就收到6个字符串就产生回调,不能大于255;传入"s"就接收到s的时候就产生回调或者收完255个字符。参数3是回调函数,取消回调就只传入"data"参数。参数4,是否执行lua解析,如果传入0将不解析执行。
- .setup配置串口。id只能传入0。后面的分别是波特率(300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400)、数据位(5, 6, 7, 8)、校验(uart.PARITY_NONE, uart.PARITY_ODD, uart.PARITY_EVEN)、停止位(uart.STOPBITS_1, uart.STOPBITS_1_5, uart.STOPBITS_2)。echo表示回显,0不回显。
- .write是写函数。id只能传入0。
综合小例子
串口模块比较简单,直接来看看例子。把波特率设置38400 8-N-1 不带回显。回调不执行lua代码解析。这里使用1号pin来设别是否切换串口设置。
gpio.mode(1, gpio.INPUT, gpio.PULLUP)
gpio.mode(0, gpio.OUTPUT)
tmr.alarm(0, 10000, tmr.ALARM_SINGLE, function()
gpio.write(0, gpio.LOW)
if(gpio.read(1) == 0) then
print("38400 8-n-1")
uart.setup(0, 38400, 8, uart.PARITY_NONE, uart.STOPBITS_1, 0)
uart.on("data", 8, function(data)
uart.write(0, "rec: ", data)
end, 0)
else
print("115200 8-n-1")
uart.setup(0, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, 1)
uart.on("data")
end
end)
这个例子有个问题,得满8个字符才会产生回调。其实,可以不用设置数量或者采用ascii格式传输,然后用"\n"来触发回调。下面是一个不设置数量的例子,直接透传数据。
gpio.mode(1, gpio.INPUT, gpio.PULLUP)
cnt = 0
tmr.alarm(0, 10000, tmr.ALARM_SINGLE, function()
if(gpio.read(1) == 0) then
uart.setup(0, 38400, 8, uart.PARITY_NONE, uart.STOPBITS_1, 0)
print("38400 8-n-1")
uart.on("data", function(data)
cnt = cnt + 1
tmr.stop(1)
tmr.interval(1, 1)
tmr.start(1)
uart.write(0, data)
end, 0)
else
uart.setup(0, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, 1)
print("115200 8-n-1")
uart.on("data")
end
end)
tmr.register(1, 1, tmr.ALARM_SEMI, function()
print("\n")
print(cnt)
print("\n")
end)
透传
这里加多个定时器来打印回调次数计数值,可以看到并不是每个字符都产生回调。所以,不必太担心频繁回调产生的性能问题。如果,我们把WiFi也加进来,那就可以变成WiFi转串口的透传模块了。如果想知道串口接收到多少字节,可以使用#data或者用string.len(data)
uart.on("data", function(data) print(#data) end, 0)
uart.on("data", function(data) print(string.len(data)) end, 0)
一点问题
以下这段代码和上面的例子基本没什么区别,不过会让nodeMCU重启。如果你把它保存为init.lua,然后传送到MCU。那么,你会看到MCU反复重启。所以,建议在init.lua中加个延时。
我也没搞懂这个代码会让机器重启,bug在哪儿呢?
gpio.mode(1, gpio.INPUT, gpio.PULLUP)
gpio.mode(0, gpio.OUTPUT)
function echoUart(data)
uart.write(0, "rec: ", data)
end
tmr.alarm(0, 10000, tmr.ALARM_SINGLE, function()
gpio.write(0, gpio.LOW)
if(gpio.read(1) == 0) then
print("38400 8-n-1")
uart.setup(0, 38400, 8, uart.PARITY_NONE, uart.STOPBITS_1, 0)
uart.on("data", 8, echoUart(data), 0)
else
print("115200 8-n-1")
uart.setup(0, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, 1)
uart.on("data")
end
end)
网友评论
1、为什么要读一下D1
2、串口的的定时器的延时时间1000,这样会丢数据吧。我上位机的串口给下边发,但是你定时器没执行到1000的时候 串口不会读?
谢谢
2,避免串口映射后,带来传文件的麻烦,做了一下延时,10s后再映射
\
请教这个是为什么?
我试了一下,这类命令不能够直接调用带参数的函数吗,如果是这样就比较麻烦了,
比如把function(data)在别的地方声明,然后直接用函数名(data)这样子的
http://www.jianshu.com/p/c5fc1afb5d42
最后一段代码的效果。
我记得在on里面调用函数是会报错的,最近没时间弄这个。如果找到解决方法在更新文章😂
我本来是想,回调函数如果写那么多行看起来会很乱,如果能在别的地方声明,然后直接调用的话整个代码看起来会舒服一些,谢谢了。
on只是个事件绑定函数。我试过在别的地方声明回调函数,然后在on里面调用,但是会报错,不知道是不是语法问题。
不过既然是回调函数,在on里面声明也合情合理啊
Hello nodeMCU
Hello nodeMCU
stdin:1: '=' expected near 'nodeMCU'
大哥问一下,以上错误是啥意思