WIFI模块(ESP8266)学习2


一、ESP8266与EEPROM

1、写数据:

/*
 * 功能描述:该代码向EEPROM写入100字节数据
 */
#include <EEPROM.h>
int addr = 0; //EEPROM数据地址
void setup() 
{
  Serial.begin(9600);
  Serial.println("");
  Serial.println("Start write");

  EEPROM.begin(100);  //申请size大小的内存大小
  for(addr = 0; addr<100; addr++)
  {
    int data = addr;
    EEPROM.write(addr, data); //写数据
  }
  EEPROM.end(); //写入flash并释放内存空间  保存更改的数据

  Serial.println("End write");
}
void loop() 
{
}

2、读数据:

/*
 * 功能描述:该代码从EEPROM读取100字节数据
 */
#include <EEPROM.h>

int addr = 0;

void setup() 
{
  Serial.begin(9600);
  Serial.println("");
  Serial.println("Start read");

  EEPROM.begin(100); 
  for(addr = 0; addr<100; addr++)
  {
    int data = EEPROM.read(addr); //读数据
    Serial.print(data);
    Serial.print(" ");
    delay(2);
  }
  //释放内存
  EEPROM.end();
  Serial.println("End read");
}
void loop() 
{
}

3、清除数据:

/*
   EEPROM Clear
   Sets all of the bytes of the EEPROM to 0.
   This example code is in the public domain.
*/
#include <EEPROM.h>
void setup() {
  EEPROM.begin(100);
  // write a 0 to all 100 bytes of the EEPROM
  for (int i = 0; i < 100; i++) {
    EEPROM.write(i, 0);
  }
  //释放内存
  EEPROM.end();
}
void loop() {
}

4、结构体操作:

/*
 * 功能描述:eeprom结构体操作
 */
#include <EEPROM.h>

#define DEFAULT_STASSID "danpianjicainiao"
#define DEFAULT_STAPSW  "boge"

struct config_type
{
  char stassid[32];
  char stapsw[64];
};

config_type config;

/*
 * 保存参数到EEPROM
*/
void saveConfig()
{
  Serial.println("Save config!");
  Serial.print("stassid:");
  Serial.println(config.stassid);
  Serial.print("stapsw:");
  Serial.println(config.stapsw);

  EEPROM.begin(1024);
  uint8_t *p = (uint8_t*)(&config);
  for (int i = 0; i < sizeof(config); i++)
  {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
}

/*
 * 从EEPROM加载参数
*/
void loadConfig()
{
  EEPROM.begin(1024);
  uint8_t *p = (uint8_t*)(&config);
  for (int i = 0; i < sizeof(config); i++)
  {
    *(p + i) = EEPROM.read(i);
  }
  EEPROM.commit();
  Serial.println("-----Read config-----");
  Serial.print("stassid:");
  Serial.println(config.stassid);
  Serial.print("stapsw:");
  Serial.println(config.stapsw);
}

/*
*初始化
*/
void setup() {
  ESP.wdtEnable(5000);
  strcpy(config.stassid, DEFAULT_STASSID);
  strcpy(config.stapsw, DEFAULT_STAPSW);
  saveConfig();
}
/*
*主循环
*/
void loop() {
  ESP.wdtFeed();
  loadConfig();
}

二、SPI通信:

1、概述:

​ 串行外设接口(Serial Peripheral Interface),高速、全双工、同步通信总线(同一时刻只有一主一从进行通信),四线(MISO:主入从出;MOSI:主出从入;SCK:同步时钟信号;SS或CS:片选使能)。(Quad SPI=2Dual SPI=4标准SPI)。

2、ESP8266 SPI类库成员函数:

SPI.h头文件中,该类库只提供主设备API

  1. SPI.begin() 初始化SPI通信;无参,无返回值;
  2. SPI.end()关闭SPI通信;无参,无返回值;
  3. SPI.setBitOrder(order)设置数据传输顺序;
    • 参数(order):
      • ~ LSBFIRST,低位在前;
      • ~ MSBFIRST,高位在前;
    • 无返回值;
  4. SPI.setClockDivider(divider)设置通信时钟(由系统时钟分频)
    • 参数(divider):
      • ~ SPI_CLOCK_DIV2, 2分频;
      • ~ SPI_CLOCK_DIV4, 4分频;
      • ~ SPI_CLOCK_DIV8, 8分频;
      • ~ SPI_CLOCK_DIV16, 16分频;
      • ~ SPI_CLOCK_DIV32, 32分频;
      • ~ SPI_CLOCK_DIV64, 64分频;
      • ~ SPI_CLOCK_DIV128, 128分频;
    • 无返回值;
  5. SPI.setDataMode(mode)设置数据模式
    • 参数(mode):
      • ~ SPI_MODE0; 即:CPOL=0,CPHA=0
      • ~ SPI_MODE1; 即:CPOL=0,CPHA=1
      • ~ SPI_MODE2; 即:CPOL=1,CPHA=0
      • ~ SPI_MODE3; 即:CPOL=1,CPHA=1
    • 无返回值
    • 补充:四种模式,即SPI相位(CPHA)和极性(CPOL)分别为0或1;
      • CPOL:即SPI空闲时,SCLK的电平(1高,0低);
      • CPHA:即SPI在SCLK的第几个边沿开始采样(0第一个,1第二个);
  6. SPI.transfer(val)传输1B的数据。全双工,发1B收1B数据
  7. SPI.transfer16(val)传输2B数据,从机返回2B作为返回值;
  8. SPI.transferBuf(buf,count)传输一个缓冲区数据,参数为发送的缓冲区buf(uint8_t*数据),count位缓冲区大小,无返回值(但从机传输来的数据会替换掉buf缓冲区的数据)
  9. SPI.pins(sck,miso,mosi,ss)切换SPI引脚映射,需在SPI.begin()前调用

3、SPI寄存器:

所有SPI设置都是由Arduino SPI控制寄存器(SPCR)决定。该寄存器就是MCU内存的一个字节,可读写。寄存器提供服务:控制、数据、状态。

  1. 控制寄存器(SPCR):

    8位,(如单片机的中断允许控制寄存器IE、中断优先级控制寄存器IP、定时器/计数器控制寄存器)

    fFaWEn.png

  2. 数据寄存器(SPDR):

    (如串行口锁存器SBUF,仅hold住一个字节)

  3. 状态寄存器(SPSR):

    ​ 根据多种微控制器的条件改变其状态

三、Ticker —ESP8266定时库

1、概述:

  • 用于规定时间后调用函数;

fAfIxg.png

  • 一个方法的示例(为了说明三个参数时的意义,两个参数时好理解)
/**
 * 每隔xx毫秒周期性执行
 * @param seconds 秒数
 * @param callback 回调函数
 */
void attach_ms(float seconds, callback_function_t callback);

/**
 * 每隔xx毫秒周期性执行
 * @param seconds 秒数
 * @param callback 回调函数
 * @param arg 回调函数的参数
 */
void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
  • 不建议使用Ticker回调函数来阻塞IO操作(网络、串口、文件);可以在Ticker回调函数中设置一个标记,在loop函数中检测这个标记;
  • 对于arg,必须时char, short, int, float, void* , char* 之一;

2、示例:

/**
 * 代码功能:板载LED开始0.3秒闪,闪20次开始以0.1秒快闪,总共闪120次后最后常亮 
 */
#include <Ticker.h>
Ticker flipper;
int count = 0;
void flip() {
  int state = digitalRead(LED_BUILTIN);  // get the current state of GPIO1 pin
  digitalWrite(LED_BUILTIN, !state);     // set pin to the opposite state
  ++count;
  // 当翻转次数达到20次的时候,切换led的闪烁频率,每隔0.1s翻转一次
  if (count == 20) {
    flipper.attach(0.1, flip);
  }
  // 当次数达到120次的时候关闭ticker
  else if (count == 120) {
    flipper.detach();
  }
}
void setup() {
  //LED_BUILTIN 对应板载LED的IO口
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  //每隔0.3s 翻转一下led状态
  flipper.attach(0.3, flip);
}
void loop() {
}
/**
*板载LED每隔25ms灭,每隔26ms亮
*/
#include <Ticker.h>
Ticker tickerSetHigh;
Ticker tickerSetLow;
void setPin(int state) {
  digitalWrite(LED_BUILTIN, state);
}
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  // 每隔25ms调用一次 setPin(0)
  tickerSetLow.attach_ms(25, setPin, 0);
  // 每隔26ms调用一次 setPin(1)
  tickerSetHigh.attach_ms(26, setPin, 1);
}
void loop() {
}

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