一、基本介绍
请参考下面的GPIO引脚图以获取索引gpio映射。
IO index | ESP8266 pin | IO index | ESP8266 pin |
---|---|---|---|
0[*] | GPIO16 | 7 | GPIO13 |
1 | GPIO5 | 8 | GPIO15 |
2 | GPIO4 | 9 | GPIO 3 |
3 | GPIO0 | 10 | GPIO1 |
4 | GPIO2 | 11 | GPIO9 |
5 | GPIO14 | 12 | GPIO10 |
6 | GPIO12 |
[*] D0(GPIO16)只能用作gpio读/写。不支持漏极开路/中断/ pwm / i2c / ow。
二、函数介绍
函数 | 功能 |
---|---|
gpio.mode() | 初始化引脚为GPIO模式,设置引脚的进/出方向,以及可选的内部弱上拉电路。 |
gpio.read() | 读取数字GPIO引脚值。 |
gpio.serout() | 根据一系列延迟时间(以µs为单位)对输出进行序列化。 |
gpio.trig() | 建立或清除回调函数以在引脚的中断上运行。 |
gpio.write() | 设置数字GPIO引脚值。 |
-
gpio.mode()
初始化引脚为GPIO模式,设置引脚的进/出方向,以及可选的内部弱上拉电路。- 句法
gpio.mode(pin, mode [, pullup])
- 参数
- pin 引脚进行配置,IO索引
- mode gpio.OUTPUT, gpio.OPENDRAIN,gpio.INPUT或gpio.INT之一(中断模式)
- pullup gpio.PULLUP使能弱上拉电阻;默认为gpio.FLOAT
- 返回
nil
4.例
gpio.mode(0, gpio.OUTPUT)
- 句法
-
gpio.read()
读取数字GPIO引脚值。- 句法
gpio.read(pin)
- 参数
pin 引脚读取,IO索引 - 返回
一个数字,0=低,1=高 - 例
-- read value of gpio 0.
gpio.read(0)
- 句法
-
gpio.trig()
建立或清除回调函数以在引脚的中断上运行。
如果在编译时未定义GPIO_INTERRUPT_ENABLE,则此功能不可用。- 句法
gpio.trig(pin, [type [, callback_function]])
- 参数
- pin 1-12,引脚触发,IO索引。注意,引脚0不支持中断。
- type“ up”,“ down”,“ both”,“ low”,“ high”分别代表上升沿,下降沿,两个沿,低电平和高电平触发模式。如果类型为“ none”或省略,则删除回调函数并禁用中断。
- callback_function(level, when, eventcount)触发发生时的回调函数。中断时指定引脚的电平作为第一个参数传递给回调。事件的时间戳作为第二个参数传递。以微秒为单位,与tmr.now()。此时间戳是在中断级别获取的,比在回调函数中获取时间更一致。此时间戳通常是检测到的第一个中断,但是在过载情况下,可能是后一个。eventcount是此回调消除的中断数。这对于边沿触发的中断最有效,并且可以对边沿进行计数。但是,请注意开关弹跳-单个开关闭合可能会产生多个脉冲。以数字方式生成边缘时,计数效果最佳。如果省略该函数,则将使用前一个回调函数。
- 返回
nil - 例
- 句法
do
-- use pin 1 as the input pulse width counter
local pin, pulse1, du, now, trig = 1, 0, 0, tmr.now, gpio.trig
gpio.mode(pin,gpio.INT)
local function pin1cb(level, pulse2)
print( level, pulse2 - pulse1 )
pulse1 = pulse2
trig(pin, level == gpio.HIGH and "down" or "up")
end
trig(pin, "down", pin1cb)
end
-
gpio.write()
设置数字GPIO引脚值。- 句法
gpio.write(pin, level)
- 参数
- pin 引脚写入,IO索引
- level gpio.HIGH 要么 gpio.LOW
- 返回
nil - 例
- 句法
-- set pin index 1 to GPIO mode, and set the pin to high.
pin=1
gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, gpio.HIGH)
-
gpio,serout()
.serout函数,文档里面写得又长又臭的,只看懂一点,估计使用来让一个Pin翻转产生序列的,还提到了同步和异步(回调)。
三、实操
nodeMCU板子上面刚好有个LED,我们可以拿这个LED来测试。先来看下板子的电路图。其中的R10,板子上面没有焊。
也就是说LED1和GPIO16连接到一起,低电平就可以点亮。而GPIO16对应的编号则是0。先用.mode配置GPIO16为输出模式。使用.write可以设置电平,设置成gpio.LOW会看到板子上的蓝灯亮起了。使用.read可以得到pin状态,这里使用print把读到的值打印出来。lua没有printf函数,用起来真费劲。另外,为了能够看到灯亮,这里用了一下tmr.delay做一下延时。
gpio.mode(0, gpio.OUTPUT)
print(gpio.read(0),"\n")
gpio.write(0, gpio.LOW)
print(gpio.read(0),"\n")
tmr.delay(1000000)
gpio.write(0, gpio.HIGH)
print(gpio.read(0),"\n")
接下来,我们来看看.trig函数是怎么工作的,直接上代码。板子上面的flash按键(接在3号IO上)在上电后是可以用来当做普通按键使用的,不一定要外接按键。
gpio.mode(0, gpio.OUTPUT)
gpio.mode(3, gpio.INT, gpio.PULLUP)
function ledTrg()
local i = gpio.read(0)
if (i == 0) then
gpio.write(0, gpio.HIGH)
else
gpio.write(0, gpio.LOW)
end
end
gpio.trig(3, "low", ledTrg)
.serout函数可以用来让IO输出特定电平。直接看一个例子
time = 0
time = tmr.now()
gpio.mode(1, gpio.OUTPUT, PULLUP)
gpio.serout(1,1,{3,7},8)
print(tmr.now() - time)
time = tmr.now()
gpio.serout(1,1,{5000,5000},8, 1)
print(tmr.now() - time)
不过这个例子,需要示波器来配合,才能看出效果。
或者把后面的5ms改成500ms,接上LED。会看到灯闪了几下。
四、综合例子
结合上一篇的tmr模块,实现呼吸灯效果。函数ledPWM用来改变LED状态,同时,修改高低电平的持续时间。不过.interval的最小单位是ms,所以,效果不是特别好。一个周期的时间不要大于50HZ(20ms),不然会有明显的闪烁。changePWM函数用来调节占空比。最后启动两个静态定时器。把程序send到nodeMCU里面就可以看到效果了~
ledState = 0
pwm = 1
flag = 0
gpio.mode(0, gpio.OUTPUT)
function ledPWM()
if (ledState == 1) then
ledState = 0
gpio.write(0, gpio.HIGH)
tmr.interval(0, 20 - pwm)
else
ledState = 1
gpio.write(0, gpio.LOW)
tmr.interval(0, pwm)
end
end
function changePWM()
if(flag == 0) then
if(pwm == 12) then
pwm = 11
flag = 1
else
pwm = pwm + 1
end
else
if(pwm == 1) then
pwm = 2
flag = 0
else
pwm = pwm - 1
end
end
end
tmr.alarm(0, 1, tmr.ALARM_AUTO, ledPWM)
tmr.alarm(1, 80, tmr.ALARM_AUTO, changePWM)
一个例子,估计你看着不过瘾。上面使用.trig来做按键扫描效果不是特别理想。这里,使用定时器扫描的方式来做按键扫描。
gpio.mode(0, gpio.OUTPUT)
gpio.mode(1, gpio.INPUT, gpio.PULLUP)
keyScanTime = tmr.create()
keyCnt = 0
function ledCtrl()
local i = gpio.read(0)
if(i == 0) then
gpio.write(0, gpio.HIGH)
else
gpio.write(0, gpio.LOW)
end
end
function keyScan()
local key = gpio.read(1)
if (key == 0) then
keyCnt = keyCnt + 1
else
if(keyCnt > 10) then
ledCtrl()
keyCnt = 0
end
end
end
tmr.alarm(keyScanTime, 10, tmr.ALARM_AUTO, keyScan)
keyScan函数以10ms的扫描周期扫描按键的电平状态,当按键按下足够长的时间后松手,则调用ledCtrl函数。赶紧send to esp后,按一下按键看看效果吧,调试过程中,不要重复send代码。可以先按ESPlorer上面的Reset按钮,重启模块。不然可以会导致模块重启。猜测是,重复注册定时器导致的。使用静态定时器,还可以在右边发送tmr.stop(定时器序号)来暂停。动态创建的,估计就比较麻烦了。