二、ESP8266之GPIO 定时器 以及串口(基于LUA开发)

来源:互联网 发布:高性能网络编程5 编辑:程序博客网 时间:2024/06/08 05:27

、> CSDN的编辑器,简直无FUCK可说,快写好的文章,只是一不小心点开另一篇文章编辑,直接崩了,重新写。。。。

1、关于GPIO

“做中学”,一直秉持的学习思路,希望能对你有所帮助。

先模仿,再创造!

从实战中开始吧,就让我们利用GPIO2点亮8266的一个板载小灯吧。

gpio.mode(4, gpio.OUTPUT)gpio.write(4, 0)

这里写图片描述
原理图上是GPIO2,为什么对应程序要写4呢?
emmmmm,对应的封装和原理图是不一样的。(这样理解?)

这里写图片描述

2、有关定时器
先看API文档
这里写图片描述

第一个参数 一共可以同时使用7个定时器,,id号呢是0-6
第二个参数是延时多少ms执行最后面的函数
第三个参数是设置是只执行一次,,还是调用启动函数时执行一下,还是一直间隔第二个参数的时间执行最后面的函数

我们就写个程序,让它隔一秒打印一次hello world吧、

tmr.alarm(1, 1000, 1, function()                    print("Hello world!")                    end)

print本质上还是把数据送到串口,不过还是慎用的好。
因为遇到’\0’就默认发送’\0’以前的数据,所以对于 byte类型的 0
它认为是 ‘\0’,用它打印字符串还是蛮不错的!

3、继续来看串口
其实串口真是把双刃剑,割伤我们,也造福我们。
如果你曾自己亲身经历过,或者看过我的ESP8266入门1以及uart之坑,你也许能些许感受到。
这里写图片描述
典型程序:

uart.on("data", 0, function(Rec)                    uart.write(Rec)                    end,0)

emmmm,可以这样来学习,但是千万别烧进去。否则,,,GG了,你去慢慢体会吧。(解救传送门)

第一个参数只有”data”,,说明是接收串口的数据
第二个参数写0就是说串口接收的数据存在了Revdata里面,,,说一下哈Revdata是一个字符串变量,,接着看后面也会提及…写小于255的数就代表,接收到这个数目才执行uart.write(0,Revdata) ,,,,如果写别的”X” ,就代表接收到字符X后就执行uart.write(0,Revdata)
第三个参数是函数,串口接收到数据就会调用这个函数,并把接收到的数据存到Revdata里面然后调用uart.write(0,Revdata) 把数据再传回串口,,,参数0是说用串口0,,当然咱们使用的就是串口0,,,.其实还有串口1,,不过呢串口1只有TX引脚引了出来,还有串口2,不过呢
即使uart.write(2,Revdata) 写上串口2,信息还会默认发给串口0
第四个参数写0吧

更好更安全的写法,应该配合定时器,留下2s的准备时间。。

tmr.alarm(1, 2000, 1, function()            uart.on("data", 0, function(Rec)                                uart.write(0, Rec)                               end, 0)end)

实例:
1、H控制继电器开,L控制继电器关

gpio.mode(2, gpio.OUTPUT)tmr.alarm(1, 2000, 0, function()//只启动一次就行            uart.on("data", 0, function(Rec)                    if Rec == 'H' then                         gpio.write(2, 1)                        print("High")                    end                    if Rec == 'L' then                        gpio.write(2, 0)                        print("LOW")                    end                    uart.write(0, Rec)//注意要加串口号!                    end, 0)end)

2、++H控制继电器

gpio.mode(2, gpio.OUTPUT)tmr.alarm(1, 2000, 0, function()//只启动一次就行            uart.on("data", 0, function(Rec)                    if Rec == '++H' then                         gpio.write(2, 1)                        print("High")                    end                    if Rec == '++L' then                        gpio.write(2, 0)                        print("LOW")                    end                    uart.write(0, Rec)//注意要加串口号!                    end, 0)end)

注意注意

这次似乎直接发送++H不行了,注意不要用ESPlorer自带的串口助手,可以用XCOM串口助手(但是不要勾选发送新行
串口回显的是

++H

似乎都没有进入判断,直接进入了uart.write…..说明Rec中的数据似乎不是++H?。。。。

但是接着你似乎可以这样试试,发送+++H呢?发送三个+号,似乎起作用了,并且串口回显的是。。。

+High++H

似乎进去if判断了,然后uart.write!
卧槽,这是神马情况?!!!

其实是这样的,
对应一串完整的数据,串口接收到一个字节后(这个对应uart.on的第二个参数),就触发中断,
比如发送++H
第一个+就触发了中断,进入了中断函数,此时Rec为’+’,所以条件都不满足. 然后uart.write
注意这个函数时用了空闲中断的!!!
跟print有区别,print是直接把数据送到串口*,而uart.write是有空闲检测的。*
所以接下来的+H就放到了Rec中,此时也谁都不满足。
因为是先把+送到串口数据缓冲区,然后再把+H送到串口缓冲区,所以打印出来为++H

如果发送+++H,那么回显也能解释的通了,第一个+触发中断函数,接下来,uart.wirte录入 ++H,刚好符合条件,进入print打印,而print没有什么空闲检测,一股脑的把串口缓冲区中的数据全部打印出来,所以打印出来”+High”最开始的加号也出来了!

就是这样,,(其实我以前还是很雾的,今天写着写着竟然想通了啊,,啊嘎嘎嘎嘎,,高兴!!!)

再来个实验验证下猜想。。

gpio.mode(2, gpio.OUTPUT)tmr.alarm(1, 2000, 0, function()            uart.on("data", 0, function(Rec)                    if Rec == '++H' then                         gpio.write(2, 1)                        print("High")                    else                        print(Rec)                    end                    uart.write(0, Rec)                    end, 0)end) 

这里写图片描述

emmm, 上面的结果,自己也能分析个八九不离十了吧。。。
还有一点,根据实验结果,,不管用print或者uart.write 似乎都自动会在最后加一个回车换行。。。。

再来解释一遍吧,
输入++H,后,第一个+触发中断,进入中断函数直接else输出了一个+并回车换行,然后uart.write空闲等待,把第二次录入的+H,以及第一次录入的+,全部输出了,对应的第二次Rec为+H 在else中再次输出。。

再看:

gpio.mode(2, gpio.OUTPUT)tmr.alarm(1, 2000, 0, function()            uart.on("data", 0, function(Rec)                    if Rec == '++H' then                         gpio.write(2, 1)                        print("High")                    else                        uart.write(0,Rec)                    end                    uart.write(0, Rec)                    end, 0)end)                 

这里写图片描述

我有点不知所措了。。。。???

mmp,,,有毒吧。。。。。

吐血。。。。
数据的回显有毒吧。。。。。mmp

 uart.on("data", 0, function(Rec)

第二个参数0,就表示串口接受到1个数据就进入中断函数 function(Rec)

最后再来一个终极版的!
借鉴杨大神的空闲中断写法!

gpio.mode(2, gpio.OUTPUT)ReadData = ""ReadDataCopy = ""ReadCnt = 0tmr.alarm(2, 5, 1, function()        if ReadCnt ~= 0 then            if ReadCnt == ReadCntCopy then//一开始并没有定义ReadCntCopy,所以直接跳到else进行赋值                ReadCnt = 0                ReadCntCopy = 0                ReadDataCopy = ReadData                ReadData = ""                if ReadDataCopy == "++H" then                    gpio.write(2, 1)                end                if ReadDataCopy == "++L" then                    gpio.write(2, 0)                end            else                ReadCntCopy = ReadCnt//只要一赋值就变成了全局变量            end        endend)tmr.alarm(1, 2000, 0, function()            uart.on("data", 0, function(Rec)                ReadData = ReadData..Rec//这是连接字符串                ReadCnt = ReadCnt + 1//不能连加            end, 0)                              end)