二,ESP8266 GPIO和SPI和定时器和串口(基于Lua脚
让这个灯亮
我们写lua用这个软件
链接:http://pan.baidu.com/s/1kVN09cr 密码:pfv7
http://www.cnblogs.com/yangfengwu/p/6247048.html这个有点使用说明
![](https://img.haomeiwen.com/i8454753/c90dbc39a681ea6c.png)
这个灯连接到了GPIO2,低电平点亮
[html]view plaincopy
gpio.mode(4,gpio.OUTPUT)--输出模式
gpio.write(4,0)--输出低电平
这两句话就亮了
可能会有疑问,明明是GPIO2为什么填4
看资料
https://nodemcu.readthedocs.io/en/master/en/modules/gpio/#gpio-module
还有一个简介版的资料
链接:http://pan.baidu.com/s/1pL3FHgf密码:l2nm
对照表
![](https://img.haomeiwen.com/i8454753/04a48e8b559d8b57.png)
现在下进去
![](https://img.haomeiwen.com/i8454753/6e33a5342d0e630e.png)
保存到芯片里面
![](https://img.haomeiwen.com/i8454753/7d02ebcdaed3bdac.png)
现在控制板子上的继电器,改一下IO口就可以了
![](https://img.haomeiwen.com/i8454753/23dd5d3be1f019a8.png)
所以呢让继电器吸合
[html]view plaincopy
gpio.mode(2,gpio.OUTPUT)
gpio.write(2,1)
关于
gpio.read()
引脚是低电平返回0,外部引脚是高电平返回1
如果设置的输出高电平,但是如果拉低了引脚,也是返回0,,,,和控制状态没有关系,只与
当前引脚的实际高低电平有关系
现在看定时器函数
![](https://img.haomeiwen.com/i8454753/602ad9dbad5888e2.png)
第一个参数 一共可以同时使用7个定时器,,id号呢是0-6
第二个参数是延时多少ms执行最后面的函数
第三个参数是设置是只执行一次,,还是调用启动函数时执行一下,还是一直间隔第二个参数的时间执行最后面的函数
就让它每隔1s打印一下串口打印111111
[html]view plaincopy
gpio.mode(4,gpio.OUTPUT)
gpio.write(4,1)
function aa()--定义一个函数
print("111111")
end
tmr.alarm(0, 1000, 1, aa)
0代表用的标号为0的定时器
1000代表延时1000ms执行aa
1代表
当然您填tmr.ALARM_AUTO也行,,,,,太长啦.....我还是选择填1
如果填写0,那么会延时1000ms然后打印一下111111,,就是第二个参数
如果还想执行一下就调用tmr.start(0)这个里面的0代表的标号为0的定时器....
当然啦关闭这个定时器tmr.start(0)
感觉第一个参数 tmr.ALARM_SINGLE = -1...只是感觉没有试过
![](https://img.haomeiwen.com/i8454753/9b00ad8ed74a28d9.png)
更方便点呢
[html]view plaincopy
gpio.mode(4,gpio.OUTPUT)
gpio.write(4,1)
tmr.alarm(1, 1000, 1, function()
print("111111")
end)
![](https://img.haomeiwen.com/i8454753/e94c7020cd9310c1.png)
可以看一下我这篇文章
http://www.cnblogs.com/yangfengwu/p/6404695.html
剩余的定时器的方法呢有可能tmr.delay(us) 会用到,,就是延时多少us......
看一下串口....
说一下哈...配置串口是一件及其危险的事情,为什么这样说呢!!
我们烧固件是通过串口,把我们编写的.lua文件保存到模块里面也是通过串口
如果说哈模块一上电就执行了我们配置的串口程序,,,,,那么我们想把新写的程序发给模块就可能写不进去.....造成一个bug了,,,,,
解决方案是
一,重新烧写固件
但是呢也有可能重新烧写固件也不能把以前写的.lua文件清除
二,先烧写别的固件,再烧写现在的
比如:可以先烧写一个AT指令的固件,让它运行一下,然后再重新烧写lua开发版本的,但是也有可能不能把以前写的.lua文件清除
三,修改程序保存的偏移量
![](https://img.haomeiwen.com/i8454753/efc90067232a41b8.png)
您想哈,,我们的.lua程序肯定也在flash里面,,,我烧写固件时把偏移量调大肯定能把我们写的.lua代码给清除掉.要是调整后出现一直发乱码,,恭喜你哈,肯定覆盖到了先前的.lua了...然后呢我再把偏移量调整到0000重新烧写就好啦...
如果出现
等着格式化文件系统,,就等着哈
好现在做一个程序我发给串口什么数据,串口就回给我什么数据
下面的功能可以实现但是别这样写,我只是来解释函数....否则亲们就按照上面的方法刷固件把
![](https://img.haomeiwen.com/i8454753/cdf1fc73f8c4385f.png)
第一个参数只有"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吧
![](https://img.haomeiwen.com/i8454753/367b3d18c141a5e7.png)
第一种方案这样写
![](https://img.haomeiwen.com/i8454753/05744071792b0de8.gif)
gpio.mode(4,gpio.OUTPUT)
gpio.write(4,1)
tmr.alarm(1,2000,0, function()
uart.on("data",0,function(Revdata)
uart.write(0,Revdata)
end,0)
end)
![](https://img.haomeiwen.com/i8454753/1c218c35e8d7fe87.gif)
程序启动以后等待2s执行下面的函数,,定时器第三个参数写的0,所以这个定时器就关闭了
![](https://img.haomeiwen.com/i8454753/312e1ea4fd038332.gif)
1.uart.on("data",0,function(Revdata)2.3. uart.write(0,Revdata)4.5. end,0)
![](https://img.haomeiwen.com/i8454753/219b3af132b9e2f1.gif)
只要一执行这个函数,那么以后串口接收到数据就会执行
uart.write(0,Revdata)
现在用串口助手测试一下
![](https://img.haomeiwen.com/i8454753/74557e141f285c54.png)
现在我假如修改了程序想重新写入芯片
复位芯片后赶紧点击,,当然有两秒时间
![](https://img.haomeiwen.com/i8454753/7c171412d03dbe3f.png)
如果程序小有时候可以直接
![](https://img.haomeiwen.com/i8454753/1dd26c820b1ae171.png)
如果程序大点,,可以再复位一下模块然后再...当然假设下载的时间不会超过两秒
![](https://img.haomeiwen.com/i8454753/2e960aa93fea0dbe.png)
假设程序很大
复位芯片后赶紧点击,,当然有两秒时间
![](https://img.haomeiwen.com/i8454753/93f916915701b884.png)
然后看这里
![](https://img.haomeiwen.com/i8454753/9e7b94d43273bde9.png)
只要移除掉init.lua一切都好办
那我先右击准备好点击,,,,然后呢我复位一下模块,然后在两秒之前点击就移除了init.lua
![](https://img.haomeiwen.com/i8454753/fd07a1c172efd328.png)
还有
![](https://img.haomeiwen.com/i8454753/4863486933a2e812.png)
也是复位后再点击是,,,移除芯片内部所有文件..........这个随时可以用,,不用像上面似的事先编译
当然这只是在自己配置了串口之后的特殊情况下才会遇到的问题哈
做到这里有些人会想,能不能配置收到什么数据就去干点什么
我们就配置收到H 就控制继电器引脚输出高电平,收到L就控制继电器引脚输出低电平
print("Relay=1")
print("Relay=0")
相当于printf,,,,把里面的字符串内容发送到串口
不过呢这个慎用,,因为遇到'\0'就默认发送'\0'以前的数据,,,所以对于 byte类型的 0
它认为是 '\0',,,用它打印字符串还是蛮不错的
[html]view plaincopy
gpio.mode(4,gpio.OUTPUT)
gpio.mode(2,gpio.OUTPUT)
gpio.write(4,1)
tmr.alarm(1, 2000, 0, function()
uart.on("data", 0,function(Revdata)
ifRevdata == "H" then
gpio.write(2,1)
print("Relay=1")
end
ifRevdata == "L" then
gpio.write(2,0)
print("Relay=0")
end
uart.write(0,Revdata)
end, 0)
end)
现在用串口调试助手测试
![](https://img.haomeiwen.com/i8454753/475c5b3bfc2178bb.png)
![](https://img.haomeiwen.com/i8454753/5524da975c08d305.png)
好现在换一下命令,配置收到++H 就控制继电器引脚输出高电平,收到++L就控制继电器引脚输出低电平
如果按照下面写竟然不管来了
[html]view plaincopy
gpio.mode(4,gpio.OUTPUT)
gpio.mode(2,gpio.OUTPUT)
gpio.write(4,1)
tmr.alarm(1, 2000, 0, function()
uart.on("data", 0,function(Revdata)
ifRevdata == "++H" then
gpio.write(2,1)
print("Relay=1")
end
ifRevdata == "++L" then
gpio.write(2,0)
print("Relay=0")
end
uart.write(0,Revdata) -- unregister callback function
end, 0)
end)
![](https://img.haomeiwen.com/i8454753/42548dc4e1868756.png)
现在发送的时候多加一个加号
也就是+++H +++L
用串口调试助手来调试,,ESPlorer 这个软件的串口有些问题
![](https://img.haomeiwen.com/i8454753/b287056042422510.png)
您会发现居然这样可以
告诉您原因
其实是因为串口先接收了一个+ 然后又接收的++H 所以可以控制
所以先前的++H 是串口先接收了一个+ 然后又接收了 +H 所以不能控制了
不信的话可以打印一下,,修改为下面的程序
[html]view plaincopy
gpio.mode(4,gpio.OUTPUT)
gpio.mode(2,gpio.OUTPUT)
gpio.write(4,1)
tmr.alarm(1, 2000, 0, function()
uart.on("data", 0,function(Revdata)
ifRevdata == "++H" then
gpio.write(2,1)
print("Relay=1")
else
print(Revdata)----LOOK LOOK LOOK
end
ifRevdata == "++L" then
gpio.write(2,0)
print("Relay=0")
end
uart.write(0,Revdata) -- unregister callback function
end, 0)
end)
![](https://img.haomeiwen.com/i8454753/869b1e250cc0dfb6.png)
![](https://img.haomeiwen.com/i8454753/c0dd1549940c1a6f.png)
其实
这地方写0,就代表了串口接收到1个数据就会进入中断函数function(Revdata)
解决方法
![](https://img.haomeiwen.com/i8454753/d8afc3af1e04d197.png)
我是不愿意使用控制接收到多少个字节,或者加入一个标志,,,,还记得AT指令要加换行不......那是因为"\r".接收到换行....
我的做法...我用定时器做空闲检测
关于Lua的部分语法可以看,,其实了解就行,,当时自己以为需要把lua学的很好才能用lua开发8266,,,最后才知道只需要了解些语法就好了,,剩下的看8266的API文档看怎么使用那些函数就行.....
http://www.cnblogs.com/yangfengwu/p/6357838.html
http://www.cnblogs.com/yangfengwu/p/6358444.html
http://www.cnblogs.com/yangfengwu/p/6366428.html
http://www.cnblogs.com/yangfengwu/p/6376098.html
[html]view plaincopy
gpio.mode(4,gpio.OUTPUT)
gpio.mode(2,gpio.OUTPUT)
gpio.write(4,1)
ReadData=""
ReadDataCopy=""
ReadCnt=0
ReadCntCopy=0
tmr.alarm(2, 5, 1, function()
if ReadCnt ~= 0 then
ifReadCnt == ReadCntt then
ReadCnt =0
ReadCntt =0
ReadDataCopy =ReadData
ReadData =""
ifReadDataCopy == "++H" then
gpio.write(2,1)
end
ifReadDataCopy == "++L" then
gpio.write(2,0)
end
else
ReadCntt =ReadCnt
end
end
end)
tmr.alarm(1, 2000, 0, function()
uart.on("data", 0,function(Revdata)
ReadData =ReadData..Revdata
ReadCnt =ReadCnt + 1
end, 0)
end)
空闲中断..............
可以先看一下自己51的程序
串口中断接收数据
![](https://img.haomeiwen.com/i8454753/e77f021cebae1a5c.png)
定时器做检测
![](https://img.haomeiwen.com/i8454753/66dd7563b93709aa.png)
可以参考的文章
http://www.cnblogs.com/yangfengwu/p/6746403.html这个较早,后期改进了
http://www.cnblogs.com/yangfengwu/p/7341056.html在文章中找哈
http://www.cnblogs.com/yangfengwu/p/6921832.html在文章中找哈
现在说一下SPI,,其实呢为什么说spi呢,,,,咱的模块最终99.99%都会设计成,发给模块串口的数据自动转发到网络,,,,,模块网络接收的数据自动转发到模块的串口对吧!!!!
那么如果想灵活的配置模块要么通过串口,要么通过其它方式比如说SPI方式....串口刚才说了主要用于用户传输数据使用.....那么我们自己写的灵活配置模块的程序也需要通过一种通信方式告诉模块哈...当然也可以选择IIC,或者自己控制模块的引脚自己编一个
感觉这篇说的够多的了,下一篇再说SPI,关键是自己去做,,自己去做,,自己去做.........