5、nodeMCU学习笔记--uart(附透传例子)

作者: 谢mingmin | 来源:发表于2016-10-27 20:23 被阅读7770次

    闲言碎语

    这回来了解一下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
    1. .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)
    

    相关文章

      网友评论

      • b66d6e8580a3:您好,我有几个问题请教一下。
        1、为什么要读一下D1
        2、串口的的定时器的延时时间1000,这样会丢数据吧。我上位机的串口给下边发,但是你定时器没执行到1000的时候 串口不会读?
        谢谢
        谢mingmin:@1531400516 我文章里面说了吧,1,要通过按键状态来做串口重映射。
        2,避免串口映射后,带来传文件的麻烦,做了一下延时,10s后再映射
      • ReCclay:"。其实,可以不用设置数量或者采用ascii格式传输,然后用"\n"来触发回调。"
        \

        请教这个是为什么?
        谢mingmin: @ReCclay 什么都不设置的话,也会有回调,而且不是单字节回调,不用担心性能问题
      • 6b04d255d5c7:uart.on("data", function(data) print(#data) end, 0)
        我试了一下,这类命令不能够直接调用带参数的函数吗,如果是这样就比较麻烦了,
        比如把function(data)在别的地方声明,然后直接用函数名(data)这样子的
        谢mingmin: @klzw43 你要的应该是这里
        http://www.jianshu.com/p/c5fc1afb5d42
        最后一段代码的效果。

        我记得在on里面调用函数是会报错的,最近没时间弄这个。如果找到解决方法在更新文章😂
        6b04d255d5c7:@谢mingmin
        我本来是想,回调函数如果写那么多行看起来会很乱,如果能在别的地方声明,然后直接调用的话整个代码看起来会舒服一些,谢谢了。
        谢mingmin: @klzw43 没看到你表达的意思。

        on只是个事件绑定函数。我试过在别的地方声明回调函数,然后在on里面调用,但是会报错,不知道是不是语法问题。

        不过既然是回调函数,在on里面声明也合情合理啊
      • Zszen:uart在stm8上用过, 总之是用来调试的, 比如温度传感器, 光感器等, 不过nodemcu有这么强大的调试, 总感觉uart已经没必要了. 另外想问这个uart的波特率各种设置后会不会影响到原有usb沟通
        谢mingmin: @Zszen 会
      • 77e04bb26cbc:>
        Hello nodeMCU
        Hello nodeMCU
        stdin:1: '=' expected near 'nodeMCU'
        大哥问一下,以上错误是啥意思
        77e04bb26cbc:@谢mingmin 只有二四行有=和==,还是不知道哪里错了,还有下面的timer在串口没显示出来
        谢mingmin: @77e04bb26cbc 缺个=号,看看代码
        77e04bb26cbc:烧的综合小例子的第二个

      本文标题:5、nodeMCU学习笔记--uart(附透传例子)

      本文链接:https://www.haomeiwen.com/subject/mrqjuttx.html