esp32arduino应用教程 (arduino开发esp32芯片)

esp32arduino环境搭建,esp32arduino应用教程

ESP32除了可以使用无线网络外还可以通过外接PHY模块来使用有线网络(Ethernet:以太网)

下面是ESP32与LAN8720间RMII PHY的连接定义,用于以太网通信,下面几个针脚必须按定义连接:

esp32arduino环境搭建,esp32arduino应用教程

下面是ESP32与LAN8720间RMII PHY SMI的连接定义,用于ESP32读写LAN8720的寄存器,下面的针脚理论上可以连接到ESP32任何支持输出的针脚上:

esp32arduino环境搭建,esp32arduino应用教程

使用步骤

引用以太网库#include <ETH.h>;

声明一个对象ETHClass myETH,默认的已经声明了一个名为ETH的对象;

使用begin()方法启动以太网连接;

常用方法说明

bool begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t type, eth_clock_mode_t clock_mode)

启用以太网连接,参数说明如下:

phy_addr:LAN8720写0或1、TLK110写31;

power:设置ESP32某管脚,该管脚可以用来管理LAN8720供电,使能时输出高电平,失能时为低电平,写-1则不使用;

mdc:mdc管脚编号,写-1则不使用;

mdio:mdio管脚编号,写-1则不使用;

type:PHY类型,ETH_PHY_LAN8720或ETH_PHY_TLK110;

clock_mode:时钟模式,可选值ETH_CLOCK_GPIO0_IN、ETH_CLOCK_GPIO0_OUT、ETH_CLOCK_GPIO16_OUT、ETH_CLOCK_GPIO17_OUT,详细介绍见后文;

bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000)

设置IP地址、网关地址、子网掩码、dns地址;

const char * getHostname()

获取主机名字;

bool setHostname(const char * hostname)

设置主机名字;

bool fullDuplex()

检查是否为全双工通讯;

uint8_t linkSpeed()

获取传输速度,单位Mbps;

IPAddress localIP()

获取IP地址;

IPAddress subnetMask()

获取子网掩码;

IPAddress gatewayIP()

获取网关地址;

IPAddress dnsIP(uint8_t dns_no = 0)

获取dns服务器地址;

String macAddress()

获取mac地址;

使用演示

数据通讯

使用下面代码进行以太网通讯演示:

#include <ETH.h> //引用以使用ETH
#include <WiFiUdp.h>
#define ETH_ADDR 1
#define ETH_POWER_PIN -1
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18
#define ETH_TYPE ETH_PHY_LAN8720
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
WiFiUDP Udp; //创建UDP对象
unsigned int localUdpPort = 2333; //本地端口号
void setup()
{
 Serial.begin(115200);
 Serial.println();
 ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); //启用ETH
 while(!((uint32_t)ETH.localIP())) //等待获取到IP
 {
 }
 Serial.println("Connected");
 Serial.print("IP Address:");
 Serial.println(ETH.localIP());
 Udp.begin(localUdpPort); //启用UDP监听以接收数据
}
void loop()
{
 int packetSize = Udp.parsePacket(); //获取当前队首数据包长度
 if (packetSize) //如果有数据可用
 {
 char buf[packetSize];
 Udp.read(buf, packetSize); //读取当前包数据
 Serial.println();
 Serial.print("Received: ");
 Serial.println(buf);
 Serial.print("From IP: ");
 Serial.println(Udp.remoteIP());
 Serial.print("From Port: ");
 Serial.println(Udp.remotePort());
 Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //准备发送数据
 Udp.print("Received: "); //复制数据到发送缓存
 Udp.write((const uint8_t*)buf, packetSize); //复制数据到发送缓存
 Udp.endPacket(); //发送数据
 }
}

esp32arduino环境搭建,esp32arduino应用教程

上面例子中启用以太网等待获取到IP,然后用UDP进行了通讯测试;

事件响应

使用下面代码进行以太网事件演示:

#include <ETH.h> //引用以使用ETH
#define ETH_ADDR 1
#define ETH_POWER_PIN -1
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18
#define ETH_TYPE ETH_PHY_LAN8720
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
void printETHInfo(void) //打印基本信息
{
 Serial.print("ETH MAC: ");
 Serial.print(ETH.macAddress());
 Serial.print(", IPv4: ");
 Serial.print(ETH.localIP());
 if (ETH.fullDuplex())
 {
 Serial.print(", FULL_DUPLEX");
 }
 Serial.print(", ");
 Serial.print(ETH.linkSpeed());
 Serial.println("Mbps");
}
void WiFiEvent(WiFiEvent_t event)
{
 switch (event)
 {
 case SYSTEM_EVENT_ETH_START: //启动ETH成功
 Serial.println("ETH Started");
 break;
 case SYSTEM_EVENT_ETH_CONNECTED: //接入网络
 Serial.println("ETH Connected");
 break;
 case SYSTEM_EVENT_ETH_GOT_IP: //获得IP
 Serial.println("ETH GOT IP");
 printETHInfo();
 break;
 case SYSTEM_EVENT_ETH_DISCONNECTED: //失去连接
 Serial.println("ETH Disconnected");
 break;
 case SYSTEM_EVENT_ETH_STOP: //关闭
 Serial.println("ETH Stopped");
 break;
 default:
 break;
 }
}
void setup()
{
 Serial.begin(115200);
 Serial.println();
 
 WiFi.onEvent(WiFiEvent); //注册事件
 ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); //启用ETH
}
void loop()
{
 delay(10000);
 esp_eth_disable(); //关闭eth
}

esp32arduino环境搭建,esp32arduino应用教程

上面演示时在获取到IP地址后我将网线拔了,手动触发了SYSTEM_EVENT_ETH_DISCONNECTED事件;

有事件的话其实上个例子中while(!((uint32_t)ETH.localIP())){} //等待获取到IP这句就可以用事件来处理了;

PHY地址

PHY地址LAN8720写0或1、TLK110写31,LAN8720使用0还是1由芯片复位时RXER引脚电平决定,当该引脚接下拉电阻或者浮空(芯片内部下拉)时,地址就为0,当引脚接上拉电阻时地址为1;

上文使用的模块电路中RXER脚外接了上拉电阻,所以地址写1;

时钟

理论上LAN8720和ESP32需要有同一个时钟源用于以太网通讯,ESP32提供了四种方式来处理时钟:

esp32arduino环境搭建,esp32arduino应用教程

第一种方式是外部输入,LAN8720和ESP32接入同一个外部50Mhz时钟;

第二种方式由ESP32(GPIO0)提供时钟给LAN8720,信号质量可能不怎么样;

第三种方式由ESP32(GPIO16)提供时钟给LAN8720;

第四种方式由ESP32(GPIO17)提供时钟给LAN8720,最合适用于LAN8720;

上文使用的模块并没有引出时钟到外部针脚,也没法选择使用时钟来源,所以上面使用时相当于LAN8720使用了模块自带的时钟,而ESP32虽然设置为时钟输出模式,但其实没有真正输出给LAN8720,这种情况下虽然能够正常通讯,但是不是那么符合理论设计。

另外如果使用外部时钟连接到GPIO0时还需要特别注意电路设计:

通讯应用

除UDP外,Ethernet也可以使用WiFiClient和WiFiServer等通讯功能;