02.esp8266开发说明


arduino编程代码结构

void setup() {
  // 这里开始写初始化代码,只会执行一次 
}
void loop() {
  //这里写运行代码,重复执行
}
//可以看成如下代码
void main(){
  watchdogEnable();//启动看门狗
  setup();//初始化函数
  while(1){
    loop();//业务代码函数
  }
}

1.在ESP8266 Arduino编程中,默认会开启看门狗功能,也就是对应伪代码的watchdogEnable(),所以我们一般需要关掉这个功能。

2.setup()方法:初始化函数,只会运行一次,所以一般情况下,我们都会在这里配置好初始化参数,比如IO口模式、串口波特率设置等

3.loop()方法:不断重复执行,这里编写我们的业务代码,同时要注意执行喂狗操作。

arduino的延时

    时间控制,基本上可以说存在于每一个项目代码中。目前在Arduino中跟时间控制有关的方法包括以下几个:
    delay(ms)
    暂停一个给定的毫秒数的时间间隔。
    delayMicroseconds(us)
    暂停一个给定的微秒数的时间间隔。
    millis()
    返回重启(reset)后所经过的毫秒数。
    micros()
    返回重启(reset)后所经过的微秒数

提示:通常,我们控制LED灯闪烁都会加上一个delay延时来达到切换亮灭时间长度。但是delay有个缺点就是:在给定的时间间隔内是不能做其他操作,这样对于一些需要响应按键操作的场景就不适用了。那么有没有什么办法既能延时又能不影响其他操作呢?当然,这就是millis()的妙用,通过获取两个时间点的毫秒数,然后计算它们的差值,差值时间间隔内是可以执行其他操作的。

管脚映射图:

NodeMcu上的CLK、SD0、CMD、SD1、SD2引脚,是用于连接外接flash芯片,不应该用于连接其他模块,悬空即可,以防程序崩溃。

下面是管脚介绍

NodeMCU的引脚名称 ESP8266内部GPIO引脚号 可复用功能 备注
D0 GPIO16 可用,只能用作GPIO读/写,不支持特殊功能
D1 GPIO5 I2C总线的SCL 可用
D2 GPIO4 I2C总线的SDA 可用
D3 GPIO0 不可用,烧录固件或者运行模式控制端口
D4 GPIO2 Serial1的TX Serial1没有RX
D5 GPIO14 SPI总线的SCLK 可用
D6 GPIO12 SPI总线的MISO 可用
D7 GPIO13 SPI总线的MOSI、Serial的RX 可用
D8 GPIO15 SPI总线的CS、Serial的TX 可用
D9 GPIO3 Serial的RX 可用
D10 GPIO1 Serial的TX 可用
SD2 GPIO9 尽量不用
SD3 GPIO10 尽量不用

从上面表格可以看出,我们大约11个GPIO引脚可用。而11个中的2个引脚通常被保留用于RX和TX,以便进行串口通信。因此最后,只剩下8个通用I / O引脚,即D0到D8(除开D3特殊用途)。

Arduino中的引脚号直接与ESP8266 GPIO的引脚号对应通信。pinMode/digitalRead/digitalWrite函数不变,所以要读取GPIO2,可调用digitalRead(2)。除了D0可以设置为INPUT(输入)、OUTPUT(输出)或者INPUT_PULLDOWN(输入,默认下拉,也就是低电平),剩余的数字IO引脚可以设置为INPUT(输入)、OUTPUT(输出)或者INPUT_PULLUP(输入,默认上拉,也就是高电平)。

先来一个简单的IO口操作:

(在面包板上看了一下效果,可以使用)

void setup() {
    pinMode(D1, OUTPUT);   // 初始化D1引脚为输出引脚
}
 
void loop() {
    digitalWrite(D1, LOW); // 亮灯
    delay(1000); // 延时1s
    digitalWrite(D1, HIGH);// 灭灯
    delay(1000); // 延时1s
}

中断功能

    该功能用于在将指定引脚设置为响应中断。
    1.函数: attachInterrupt(pin, function, mode);
    参数:
      pin:要设置中断编号,注意,这里不是引脚编号。
      function:中断发生时运行的函数, 这个函数不带任何参数,不返回任何内容。
      Interrupt type/mode:它定义中断被触发的条件方式。
        CHANGE:改变沿,引脚电平从低变为高或者从高变为低时触发中断。
        RISING:上升沿,引脚电平从低变为高时触发中断。
          FALLING:下降沿,引脚电平从高变为低时触发中断。
    返回值: 无;

    该功能用于禁用指定GPIO引脚上的中断。
    2.函数: detachInterrupt(pin)
    参数:
        pin:要禁用的中断的GPIO引脚。
    返回值: 无;

    3.digitalPinToInterrupt()
    该功能用于获取指定GPIO引脚的中断号。
    函数: digitalPinToInterrupt(pin)
    参数:
        pin:要获取中断号的GPIO引脚。
    返回值: 中断号;
这里实现一个例子:

将NodeMcu的D2引脚设置为上升沿中断。在D2上外接一个按键,按键通过电阻下拉到地。当发生中断的时候,我们在串口监视器上打印“Hello ESP8266”。

这个也比较简单

void setup() {
 Serial.begin(115200);//设置串口波特率
 attachInterrupt(digitalPinToInterrupt(D2), InterruptFunc, RISING);//设置中断号、响应函数、触发方式
}
 
void loop() {
}

/**
 * 中断响应函数
 */ 
void InterruptFunc(){
 Serial.println("Hello ESP8266");
}
注意具体接法

模拟输入(ADC)

学过模拟电路或者数字电路的人都会听过ADC,它又叫做模数转换器,用于将模拟信号转换成可视化的数字形式。ESP8266具有内置的10位ADC,只有一个ADC通道,即只有一个ADC输入引脚可读取来自外部器件的模拟电压。
    ESP8266上的ADC通道和芯片供电电压复用,也就是说我们可以将其设置为测量系统电压或者外部电压。

analogRead(A0),用于读取施加在模块的ADC引脚上的外部电压;

输入电压范围:0 - 1.0V之间;由于ADC具有10位分辨率,因此会给出0-1023的值范围;

注意:为了支持外部电压范围(0-3.3v),NodeMcu做了一个电阻分压器,而且他不需要换比例,里面会自己算好然后输出。

比如下面我们测量外部电压:

void setup() {
  Serial.begin(115200);//配置波特率
}
 
void loop() {
  Serial.print("ADC Value: ");
  Serial.println(analogRead(A0));//输出0-1023 对应 外部输入电压 0-1.0v
  //延时1s
  delay(1000);
}

我们还可以测量系统的电压:

相关方法
        ESP.getVcc(),读取NodeMCU模块的VCC电压,单位是mV;
    注意点
        ADC引脚必须保持悬空;在读取VCC电源电压之前,应更改ADC模式以读取系统电压。
要ADC_MODE(mode)在#include行后面改变ADC模式。
模式是ADC_TOUT(对于外部电压),ADC_VCC(对于系统电压)。默认情况下,它读取外部电压。

具体代码如下:

extern "C"  ADC_MODE(ADC_VCC);//设置ADC模式为读取系统电压
//意思是声明一个非C++函数
//这里注意加上extern "C" ,不然会报错。
void setup() {
  Serial.begin(115200);
}
 
void loop() {
  Serial.print("ESP8266当前系统电压(mV): ");
  Serial.println(ESP.getVcc());
  delay(1000);
}
实际效果

还可以模拟输出(pwm)

mode mcu的pwm引脚:

D1,D2,D3,D4,D5,D6,D7,D8,RX,TX都可以作为pwm引脚

注意:基本上数字IO都可以作为PWM复用引脚,除了D0。不过需要注意的是,D3尽量不用,它内部连接ESP8266 GPIO0。

与pwm有关的系统函数:

    1.analogWrite()
    该功能用于在指定的引脚上启用软件PWM。
    函数: analogWrite(pin,val)
    参数:
        pin:要启用软件PWM的GPIO引脚。
        val:数值,一般在0到PWMRANGE范围,默认PWMRANGE是1023。
    返回值: 无;
    注意点:
        analogWrite(pin, 0)用于禁用指定引脚上的PWM。
    2.analogWriteRange()
    该功能用于改变PWMRANGE数值。
    函数: analogWriteRange(new_range)
    参数:
        new_range:新的PWMRANGE数值。
    返回值: 无;
    注意点:
        可以理解为PWM精度范围。同样的PWM频率下,默认占空数值0-123。如果你改变PWMRANGE为2047,那么占空数值就变成0-2047。精度高了一倍。
    3.analogWriteFreq()
    该功能用于改变PWM频率。
    函数: analogWriteFreq(new_frequency)
    参数:
        new_frequency:新PWM频率,默认是1kHZ。
    返回值: 无;

LED呼吸灯例子:

#define PIN_LED D6 
void setup() {
  // 这里开始写初始化代码,只会执行一次
  pinMode(PIN_LED,OUTPUT);
  analogWrite(PIN_LED,0);
}

void loop() {
  //这里写运行代码,重复执行
  for(int val=0;val<1024;val++){
     //占空比不断增大  亮度渐亮
     analogWrite(PIN_LED,val);
     delay(2);
  }
  
  for(int val=1023;val>=0;val--){
     //占空比不断变小  亮度渐暗
     analogWrite(PIN_LED,val);
     delay(2);
  }
}

 串口通信(Serial)

 ESP8266的串口通信与传统的Arduino设备完全一样。除了硬件FIFO(128字节用于TX和RX)之外,硬件串口还有额外的256字节的TX和RX缓存。发送和接收全都由中断驱动。当FIFO/缓存满时,write函数会阻塞工程代码的执行,等待空闲空间。当FIFO/缓存空时,read函数也会阻塞工程代码的执行,等待串口数据进来。
    NodeMcu上有两组串口,Serial和Serial1。
    Serial使用UART0,默认对应引脚是GPIO1(TX)和GPIO3(RX)。在Serial.begin执行之后,调用Serial.swap()可以将Serial重新映射到GPIO15(TX)和GPIO13(RX)。再次调用Serial.swap()将Serial重新映射回GPIO1和GPIO3。不过,一般情况下,默认就好。

串口映射例子:

void setup() {
  // 这里开始写初始化代码,只会执行一次
  Serial.begin(115200);
  Serial.println("GPIO1(TX),GPIO3(RX)");
  //调用映射方法
  Serial.swap();
  Serial.println("GPIO15(TX),GPIO13(RX)");
  //重新映射回来
  Serial.swap();
  Serial.println("GPIO1(TX),GPIO3(RX)");
}

void loop() {
  //这里写运行代码,重复执行
}
//Serial1使用UART1,默认对应引脚是GPIO2(TX)。
//Serial1不能用于接收数据,因为它的RX引脚被用于flash芯片连接。
//要使用Serial1,请调用Serial.begin(baudrate)。代码如下:
void setup() {
  // 这里开始写初始化代码,只会执行一次
  Serial.begin(115200);
  Serial.println("Hello Serial");
  Serial1.begin(115200);
  Serial1.println("Hello Serial1");
}

void loop() {
  //这里写运行代码,重复执行
}

默认情况下,当调用Serial.begin后,将禁用WiFi库的诊断输出。要想再次启动调试输出,请调用Serial.setDebugOutput(true)。要将调试输出映射到Serial1时,需要调用Serial1.setDebugOutput(true)。
    调用Serial.setRxBufferSize(size_t size)允许定义接收缓冲区的大小,默认值是256(缓冲区也是使用内存,意味着不能一味地去增大这个值)。
    Serial和Serial1对象都支持5,6,7,8个数据位,奇数(O)、偶数(E)和无(N)奇偶校验,以及1或者2个停止位。要设置所需的模式,请调用Serial.begin(baudrate, SERIAL_8N1), Serial.begin(baudrate, SERIAL_6E2)等。
    Serial和Serial1都实现了一种新方法用来获取当前的波特率设置。要获取当前的波特率,请调用Serial.baudRate(),Serial1.baudRate()。代码如下:

void setup() {
  // 这里开始写初始化代码,只会执行一次
  // 设置当前波特率为57600
  Serial.begin(57600);
  // 获取当前波特率
  int br = Serial.baudRate();
  // 将打印 "Serial is 57600 bps"
  Serial.printf("Serial is %d bps", br);
}

void loop() {
  //这里写运行代码,重复执行
}

一般来说,串口通信用在两个方面:
    1.与外围串口设备传输数据,比如蓝牙模块、Arduino等等;
    2.开发过程中用来调试代码,通过串口输出Debug信息了解程序运行信息。例程如下:

#include <ESP8266WiFi.h>
#define AP_SSID "xxxxx" //这里改成你的wifi名字
#define AP_PSW  "xxxxx"//这里改成你的wifi密码
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
void setup(){
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时2s 为了演示效果
  delay(2000);
  DebugPrintln("Setup start");
  //启动STA模式,并连接到wifi网络
  WiFi.begin(AP_SSID, AP_PSW);
 
  DebugPrint(String("Connecting to ")+AP_SSID);
  //判断网络状态是否连接上,没连接上就延时500ms,并且打出一个点,模拟连接过程
  //笔者扩展:加入网络一直都连不上 是否可以做个判断,由你们自己实现
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    DebugPrint(".");
  }
  DebugPrintln("");
 
  DebugPrint("Connected, IP address: ");
  //输出station IP地址,这里的IP地址由DHCP分配
  DebugPrintln(WiFi.localIP());
  DebugPrintln("Setup End");
}
void loop() {
}
实际效果
这里大概讲了modemcu的一些基础功能,比较简单。
这里感谢一下博哥写的博客,本笔记都是参考他的。

文章作者: 小游
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小游 !
  目录