8266 学习笔记

编译环境 Arduino 1.8.18
芯片ESP8266 模组ESP-12S
其他说明:无

0.项目结构

0.1 setup()

Arduino控制器通电或复位后,即会开始执行setup() 函数中的程序,该部分只会执行一次。
通常我们会在setup() 函数中完成Arduino的初始化设置,如配置I/O口状态,初始化串口等操作。

示例程序

// 给13号引脚连接的设备设置一个别名“led”
int led = 13;

// 在板子启动或者复位重启后, setup部分的程序只会运行一次
void setup()
{
  // 将“led”引脚设置为输出状态
  pinMode(led, OUTPUT);     
}

// setup部分程序运行完后,loop部分的程序会不断重复运行
void loop() 
{
  digitalWrite(led, HIGH);   // 点亮LED
  delay(1000);           // 等待一秒钟
  digitalWrite(led, LOW);   // 通过将引脚电平拉低,关闭LED
  delay(1000);           // 等待一秒钟
}

0.2 loop()

在setup() 函数中的程序执行完后,Arduino会接着执行loop() 函数中的程序。而loop()函数是一个死循环,其中的程序会不断的重复运行。
通常我们会在loop() 函数中完成程序的主要功能,如驱动各种模块,采集数据等。

示例程序

// 给13号引脚连接的设备设置一个别名“led”
int led = 13;

// 在板子启动或者复位重启后, setup部分的程序只会运行一次
void setup()
{
  // 将“led”引脚设置为输出状态
  pinMode(led, OUTPUT);     
}

// setup部分程序运行完后,loop部分的程序会不断重复运行
void loop() 
{
  digitalWrite(led, HIGH);   // 点亮LED
  delay(1000);           // 等待一秒钟
  digitalWrite(led, LOW);   // 通过将引脚电平拉低,关闭LED
  delay(1000);           // 等待一秒钟
}

0.3 Arduino程序main函数结构解析

在进行Arduino开发时,没有像传统C/C++程序使用入口函数main。实际上main函数存在于Arduino核心库中,且仍然是程序的入口。
在Arduino核心库中可见main.cpp文件,其内容如下:

#include <Arduino.h>

// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )()) { return 0; }

// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }

void setupUSB() __attribute__((weak));
void setupUSB() { }

int main(void)
{
    init();

    initVariant();

    #if defined(USBCON)
        USBDevice.attach();
    #endif

    setup();

    for (;;) 
    {
        loop();
        if (serialEventRun) serialEventRun();
    }

    return 0;
}

通过以上程序可见,Arduino程序中编写的setup和loop函数,都在main函数中调用了。
loop的循环执行,是通过for循环实现的,且每次loop结束后,都会进行串口事件判断,也正是因为这种设计,串口事件不能实时响应。

1.数字IO输入输出

1.1 pinMode(pin, mode)

在使用输入或输出功能前,你需要先通过pinMode() 函数配置引脚的模式为输入模式或输出模式。
参数:
        pin                指定配置的引脚编号
        mode            指定的配置模式

1.2 digitalWrite(pin, value)

使用pinMode配置成输出模式后,你还需要使用digitalWrite() 让其输出高电平或者是低电平。
参数:
        pin                指定输出的引脚编号;
        value            指定输出的电平

1.3 digitalRead(pin)

在使用输入或输出功能前,你需要先通过pinMode() 函数配置引脚的模式为输入模式或输出模式。
参数:
        pin                指定读取状态的引脚编号。
返回值:
       返回值为获取到的信号状态,1为高电平,0为低电平。

1.4 示例程序 数字输出

/*
等待一秒钟,点亮LED,再等待一秒钟,熄灭LED,如此循环
*/
 
// ESP-12S板上 ESP8266芯片2号引脚连接了一个LED灯
// 设置一个别名“led”
int led = 2;

// 在板子启动或者复位重启后, setup部分的程序只会运行一次
void setup()
{
  // 将“led”引脚设置为输出状态
  pinMode(led, OUTPUT);     
}
 
// setup部分程序运行完后,loop部分的程序会不断重复运行
void loop() 
{
  digitalWrite(led, HIGH);   // 关闭LED
  delay(1000);           // 等待一秒钟
  digitalWrite(led, LOW);   // 通过将引脚电平拉低,打开LED
  delay(1000);           // 等待一秒钟
}

1.5 示例程序 数字输入输出

/*
通过13号引脚连接的按键,控制2号引脚连接的LED
*/

// 设置各引脚别名
const int buttonPin = 13;     // 连接按键的引脚
const int ledPin =  2;      // 连接LED的引脚
// ESP-12S板上 ESP8266芯片2号引脚连接了一个LED灯
// 设置一个别名“ledPin”
// 变量定义
int buttonState = 0;         // 存储按键状态的变量

void setup() {
  // 初始化LED引脚为输出状态
  pinMode(ledPin, OUTPUT);      
  // 初始化按键引脚为输入状态
  pinMode(buttonPin, INPUT);     
}

void loop(){
  // 读取按键状态并存储在变量中
  buttonState = digitalRead(buttonPin);

  // 检查按键是否被按下
  // 如果按键按下,那buttonState应该为高电平
  if (buttonState == HIGH) {     
    // 点亮LED
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // 熄灭LED
    digitalWrite(ledPin, LOW); 
  }
}

2.串口通讯

使用串口与计算机通信,需要先使用Serial.begin() 初始化Arduino的串口通信功能

2.1 Serial.begin(speed, config)

初始化串口,可配置串口的各项参数        
语法:
        Serial.begin(speed)
        Serial.begin(speed, config)
参数:
        speed:波特率
        config:数据位、校验位、停止位配置

2.2 Serial.print(val, format)

将数据输出到串口。
数据会以ASCII形式输出。如果要以字节形式输出数据,你需要使用write() 函数。

语法:
        Serial.print(val)
        Serial.print(val, format)
参数:
        val: 需要输出的数据
        format: 输出的进制形式
        BIN(二进制)
        DEC(十进制)
        OCT(八进制)
        HEX(十六进制)
        或者指定输出的float数据带有小数的位数(默认输出两位),例如:
        Serial.print(1.23456)输出为"1.23";
        Serial.print(1.23456, 0) 输出为"1";
        Serial.print(1.23456, 2) 输出为"1.23";
        Serial.print(1.23456, 4) 输出为"1.2345"。
返回值:
        输出的字节数

Serial.println(data)
从串行端口输出数据,跟随一个回车(ASCII 13, 或 'r')和一个换行符(ASCII 10, 或 'n')。这个函数所取得的值与 Serial.print()一样。

2.2 示例程序 串口通讯

int counter=0;//计数器

void setup() {
//初始化串口
  Serial.begin(115200);
}

void loop() {
//每loop循环一次,计数器变量加1
counter = counter+1;
// 输出变量
Serial.print(counter);
// 输出字符
Serial.print(":");
// 输出字符串;
Serial.println("Hellow World");
delay(1000);

if(counter == 10)
ESP.restart();  //复位esp8266
}

3.软件复位

ESP.restart();  //复位esp8266

int counter=0;//计数器

void setup() {
//初始化串口
  Serial.begin(115200);
}

void loop() {
//每loop循环一次,计数器变量加1
counter = counter+1;
// 输出变量
Serial.print(counter);
// 输出字符
Serial.print(":");
// 输出字符串;
Serial.println("Hellow World");
delay(1000);

if(counter == 10)
ESP.restart();  //复位esp8266
}

4.ADC模拟量采集

5.时间控制

5.1 delay( ms)

此函数为毫秒级延时。
参数为时长,类型unsigned long

5.2 delayMicroseconds( us )

此函数为微秒级延时。
参数为时长,类型unsigned int

5.3 示例程序

/*
  Blink
等待一秒钟,点亮LED,再等待一秒钟,熄灭LED,如此循环
*/

// 在大多数Arduino控制板上 13号引脚都连接了一个标有“L”的LED灯
// 给13号引脚连接的设备设置一个别名“led”
int led = 13;

// 在板子启动或者复位重启后, setup部分的程序只会运行一次
void setup(){
  // 将“led”引脚设置为输出状态
  pinMode(led, OUTPUT);     
}

// setup部分程序运行完后,loop部分的程序会不断重复运行
void loop() 
{
  digitalWrite(led, HIGH);   // 点亮LED
  delay(1000);           // 等待一秒钟
  digitalWrite(led, LOW);   // 通过将引脚电平拉低,关闭LED
  delay(1000);           // 等待一秒钟
}

6.PWM

7.网络

#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WiFiMulti.h>   //  ESP8266WiFiMulti库
#include <ESP8266WebServer.h>   //  ESP8266WebServer库
 
ESP8266WiFiMulti wifiMulti;     // 建立ESP8266WiFiMulti对象,对象名称是 'wifiMulti'
 
ESP8266WebServer esp8266_server(80);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)
 
void setup(void){
  Serial.begin(115200);   // 启动串口通讯
 
  pinMode(2, OUTPUT); //设置内置LED引脚为输出模式以便控制LED
  
  //通过addAp函数存储  WiFi名称       WiFi密码
  wifiMulti.addAP("wfm", "12345678");  // 这三条语句通过调用函数addAP来记录3个不同的WiFi网络信息。
  wifiMulti.addAP("CMCC-yLaQ", "1123456"); // 这3个WiFi网络名称和密码
  wifiMulti.addAP("taichi-maker3", "13572468");
                                                // 此处WiFi信息只是示例,请在使用时将需要连接的WiFi信息填入相应位置。
                                                // 另外这里只存储了3个WiFi信息,您可以存储更多的WiFi信息在此处。
  Serial.println("正在连接Wifi,请稍等:");  
  int i = 0;                                 
  while (wifiMulti.run() != WL_CONNECTED) {  // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前
    delay(1000);                             // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCU
    Serial.print(i++); Serial.print(' ');    // 将会连接信号最强的那一个WiFi信号。
  }                                          // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是
                                             // 此处while循环判断是否跳出循环的条件。
  
  // WiFi连接成功后将通过串口监视器输出连接成功信息 
  Serial.println('\n');
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID());              // 通过串口监视器输出连接的WiFi名称
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());           // 通过串口监视器输出ESP8266-NodeMCU的IP
 
  esp8266_server.begin();                           // 启动网站服务
  esp8266_server.on("/", HTTP_GET, handleRoot);     // 设置服务器根目录即'/'的函数'handleRoot'
  esp8266_server.on("/LED", HTTP_POST, handleLED);  // 设置处理LED控制请求的函数'handleLED'
  esp8266_server.onNotFound(handleNotFound);        // 设置处理404情况的函数'handleNotFound'
 
  Serial.println("HTTP esp8266_server started");//  告知用户ESP8266网络服务功能已经启动
}
 
void loop(void){
  esp8266_server.handleClient();                     // 检查http服务器访问
}
 
/*设置服务器根目录即'/'的函数'handleRoot'
  该函数的作用是每当有客户端访问NodeMCU服务器根目录时,
  NodeMCU都会向访问设备发送 HTTP 状态 200 (Ok) 这是send函数的第一个参数。
  同时NodeMCU还会向浏览器发送HTML代码,以下示例中send函数中第三个参数,
  也就是双引号中的内容就是NodeMCU发送的HTML代码。该代码可在网页中产生LED控制按钮。 
  当用户按下按钮时,浏览器将会向NodeMCU的/LED页面发送HTTP请求,请求方式为POST。
  NodeMCU接收到此请求后将会执行handleLED函数内容*/
void handleRoot() {       
  esp8266_server.send(200, "text/html", "<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"LED\"></form>");
}
 
//处理LED控制请求的函数'handleLED'
void handleLED() {                          
  digitalWrite(2,!digitalRead(2));// 改变LED的点亮或者熄灭状态
  esp8266_server.sendHeader("Location","/");          // 跳转回页面根目录
  esp8266_server.send(303);                           // 发送Http相应代码303 跳转  
}
 
// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){
  esp8266_server.send(404, "text/plain", "404: Not found"); // 发送 HTTP 状态 404 (未找到页面) 并向浏览器发送文字 "404: Not found"
}

8.IIC

 DS3231 读取时间的例子

#include <Wire.h>

#define SDA        5      // Pin sda (I2C)
#define SCL        4      // Pin scl (I2C)

const unsigned char DS3231_ADDRESS = 0x68;
const unsigned char secondREG = 0x00;
const unsigned char minuteREG = 0x01;
const unsigned char hourREG = 0x02;
const unsigned char WTREG = 0x03;                   //weekday
const unsigned char dateREG = 0x04;
const unsigned char monthREG = 0x05;
const unsigned char yearREG = 0x06;
const unsigned char alarm_min1secREG = 0x07;
const unsigned char alarm_min1minREG = 0x08;
const unsigned char alarm_min1hrREG = 0x09;
const unsigned char alarm_min1dateREG = 0x0A;
const unsigned char alarm_min2minREG = 0x0B;
const unsigned char alarm_min2hrREG = 0x0C;
const unsigned char alarm_min2dateREG = 0x0D;
const unsigned char controlREG = 0x0E;
const unsigned char statusREG = 0x0F;
const unsigned char ageoffsetREG = 0x10;
const unsigned char tempMSBREG = 0x11;
const unsigned char tempLSBREG = 0x12;
const unsigned char _24_hour_format = 0;
const unsigned char _12_hour_format = 1;
const unsigned char AM = 0;
const unsigned char PM = 1;

void setup() 
{
  Serial.begin(115200); //设置串口波特率为115200
  rtc_init(SDA, SCL);//RTC数组芯片初始化
}//setup

void loop() 
{
  Serial.println("Hello world!");
  Serial.print(rtc_stunde()); //读时钟芯片秒
  Serial.print(":");
  Serial.print(rtc_minute()); //读时钟芯片秒
  Serial.print(":");
  Serial.print(rtc_sekunde()); //读时钟芯片秒
  Serial.println("");
  delay(1000);
}//loop

//**************************************************************************************************
void rtc_init(unsigned char sda, unsigned char scl) 
{
    Wire.begin(SDA, SCL);
    // Wire初始化, 加入i2c总线
    // 如果未指定,则以主机身份加入总线。
    rtc_Write(controlREG, 0x00);
}
//**************************************************************************************************
// RTC I2C Code
//**************************************************************************************************
unsigned char rtc_Read(unsigned char regaddress) 
{
    Wire.beginTransmission(DS3231_ADDRESS);//发送一个I2C开始字符
    Wire.write(regaddress);
    Wire.endTransmission();//结束一个由beginTransmission()开始的并且由write()排列的从机的传输
    Wire.requestFrom((unsigned char) DS3231_ADDRESS, (unsigned char) 1);//主设备请求从设备一个字节,这个字节可以被主设备用 read()或available()接受
    return (Wire.read());
}
//**************************************************************************************************
void rtc_Write(unsigned char regaddress, unsigned char value) 
{
    Wire.beginTransmission(DS3231_ADDRESS);// 向地址为DS3231_ADDRESS的从机传送数据
    Wire.write(regaddress);
    Wire.write(value);
    Wire.endTransmission();
}
//**************************************************************************************************
unsigned char rtc_sekunde() //读时钟芯片秒
{
    return (bcd2dec(rtc_Read(secondREG)));
}
unsigned char rtc_minute() //读时钟芯片分
{
    return (bcd2dec(rtc_Read(minuteREG)));
}
unsigned char rtc_stunde() //读时钟芯片小时
{
    return (bcd2dec(rtc_Read(hourREG)));
}
unsigned char rtc_wochentag() //读时钟芯片星期
{
    return (bcd2dec(rtc_Read(WTREG)));
}
unsigned char rtc_tag() //读时钟芯片日
{
    return (bcd2dec(rtc_Read(dateREG)));
}
unsigned char rtc_monat() //读时钟芯片月
{
    return (bcd2dec(rtc_Read(monthREG)));
}
unsigned char rtc_jahr() //读时钟芯片年
{
    return (bcd2dec(rtc_Read(yearREG)));
}
unsigned char bcd2dec(unsigned char x) { //value 0...99   BCD TO 10进制
    int z, e;
    e = x & 0x0F;
    z = x & 0xF0;
    z = z >> 4;
    z = z * 10;
    return (z + e);
}

9.读取ID


uint64_t chipid;  
 
void setup() 
{
  Serial.begin(115200);
}
 
void loop() 
{
  chipid=ESP.getChipId();//The chip ID is essentially its MAC address(length: 6 bytes).
  Serial.printf("ESP8266 Chip ID = %04X",(uint16_t)(chipid>>32));//print High 2 bytes
  Serial.printf("%08X\n",(uint32_t)chipid);//print Low 4bytes.
 
  delay(3000);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值