使用Arduino开发ESP32(06):Ethernet的使用(基于LAN8720)
文章目录
- 目的
- 基本说明
- 接线定义
- 使用步骤
- 常用方法说明
- 使用演示
- 数据通讯
- 事件响应
- 其他说明
- PHY地址
- 时钟
- 通讯应用
- 总结
目的
ESP32除了可以使用无线网络外还可以通过外接PHY模块来使用有线网络(Ethernet:以太网),本篇将介绍相关内容。
基本说明
本篇中使用常用的PHY芯片LAN8720的模块来来进行有线网络使用演示。
接线定义
下面是ESP32与LAN8720间RMII PHY的连接定义,用于以太网通信,下面几个针脚必须按定义连接:
GPIO | RMII Signal | ESP32 EMAC Function | Notes |
---|---|---|---|
GPIO21
|
TX_EN
|
EMAC_TX_EN
|
|
GPIO19
|
TX0
|
EMAC_TXD0
|
|
GPIO22
|
TX1
|
EMAC_TXD1
|
|
GPIO25
|
RX0
|
EMAC_RXD0
|
|
GPIO26
|
RX1
|
EMAC_RXD1
|
|
GPIO27
|
CRS_DV
|
EMAC_RX_DRV
|
下面是ESP32与LAN8720间RMII PHY SMI的连接定义,用于ESP32读写LAN8720的寄存器,下面的针脚理论上可以连接到ESP32任何支持输出的针脚上:
Default Example GPIO | RMII Signal | Notes1 | Notes2 |
---|---|---|---|
GPIO23
|
MDC
|
输出至LAN8720 | 也可以使用ESP32其他输出脚 |
GPIO18
|
MDIO
|
双向通讯 | 也可以使用ESP32其他双向脚 |
使用步骤
- 引用以太网库
#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_OUTWiFiUDP 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); //启用ETHwhile(!((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(); //发送数据}
}
上面例子中启用以太网等待获取到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_OUTvoid 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: //获得IPSerial.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
}
上面演示时在获取到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提供了四种方式来处理时钟:
Mode | GPIO Pin | Signal name | Notes |
---|---|---|---|
external |
GPIO0
|
EMAC_TX_CLK
|
Input of 50MHz PHY clock |
internal |
GPIO0
|
CLK_OUT1
|
Output of 50MHz APLL clock. Signal quality might be an issue. |
internal |
GPIO16
|
EMAC_CLK_OUT
|
Output of 50MHz APLL clock. |
internal |
GPIO17
|
EMAC_CLK_180
|
Inverted output of 50MHz APLL clock. Found to be best suitable for LAN8720 with long signal lines. |
第一种方式是外部输入,LAN8720和ESP32接入同一个外部50Mhz时钟;
第二种方式由ESP32(GPIO0)提供时钟给LAN8720,信号质量可能不怎么样;
第三种方式由ESP32(GPIO16)提供时钟给LAN8720;
第四种方式由ESP32(GPIO17)提供时钟给LAN8720,最合适用于LAN8720;
上文使用的模块并没有引出时钟到外部针脚,也没法选择使用时钟来源,所以上面使用时相当于LAN8720使用了模块自带的时钟,而ESP32虽然设置为时钟输出模式,但其实没有真正输出给LAN8720,这种情况下虽然能够正常通讯,但是不是那么符合理论设计,有一定概率会导致通讯失败。(可以把模块上的晶振拆了,然后用飞线连接ESP32 GPIO17和LAN8720模块晶振时钟输出脚,可以大大提升通讯稳定性)
另外如果使用外部时钟连接到GPIO0时还需要特别注意电路设计:
Because GPIO0 is a strapping pin for entering UART flashing mode on reset, care must be taken when also using this pin as EMAC_TX_CLK. If the clock output from the PHY is oscillating during reset, the ESP32 may randomly enter UART flashing mode.
One solution is to use an additional GPIO as a “power pin”, which either powers the PHY on/off or enables/disables the PHY’s own oscillator. This prevents the clock signal from being active during a system reset. For this configuration to work, GPIO0 also needs a pullup resistor and the “power pin” GPIO will need a pullup/pulldown resistor - as appropriate in order to keep the PHY clock disabled when the ESP32 is in reset.
通讯应用
除UDP外,Ethernet也可以使用WiFiClient和WiFiServer等通讯功能;
总结
Arduino core for the ESP32中Ethernet的使用主要就上面这些内容,更多内容可以参考如下:
https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFi
https://github.com/espressif/arduino-esp32/tree/master/tools/sdk/include/ethernet
使用Arduino开发ESP32(06):Ethernet的使用(基于LAN8720)相关推荐
- 使用Arduino开发ESP32(八):ESP32的EPROM的写入读取
写入EPROM /* 该代码向EEPROM写入4096字节数据 */ #include <EEPROM.h>void setup() {Serial.begin(115200);Seria ...
- 使用Arduino开发ESP32(11):IO口与相关外设说明与记录
文章目录 目的 数字IO口 基本使用 外部中断 使用示例 参考链接 LEDC(PWM) 常用方法 使用示例 参考链接 SigmaDelta 参考链接 ADC 常用方法 使用示例 参考链接 存在的问题 ...
- 使用Arduino开发ESP32(13):SD卡的使用
文章目录 目的 SDMMC方式 常用方法 使用示例 SPI方式 常用方法 使用示例 注意事项 总结 目的 对于嵌入式设备来说SD卡也是个比较好用的功能,比如用来存放设备的配置文件.日志文件.执行脚本. ...
- Arduino开发遥控小车(三)基于nRF24L01无线模块实现舵机转向和直流电机调速
Arduino开发遥控小车(三)基于nRF24L01无线模块实现舵机转向和直流电机调速 前面和大家分享了通过nRF24L01无线模块实现数据发送和接收的基本方法,本次继续和大家分享最终实现遥控小车转向 ...
- 使用Arduino开发ESP32(07):系统时间和定时任务调度器Ticker
文章目录 目的 系统时间及应用 定时任务调度器Ticker 使用步骤 常用方法 使用事例 事例一 事例二 事例三 总结 目的 开发中经常会用到时间相关操作,主要就是用到系统时间.延时操作.定时任务调度 ...
- 使用Arduino开发ESP32(21):蓝牙基础说明与作为服务器使用
文章目录 目的 蓝牙基础说明 测试工具 作为服务器使用 创建蓝牙设备并广播 创建Server 创建Service并启动 创建Characteristic 读写Characteristic中的Value ...
- 使用Arduino开发ESP32:wifi基本功能使用
1.建立网络(AP) 2.连接网络(STA) 3.扫描网络 1.建立网络(AP) 只需两步:1.引用WiFi库include<WiFi.h> 2.启动AP网络WiFi.softAP(ssi ...
- 基于arduino 开发 esp32 点亮ili9341屏幕
第一次编写csdn文章,也同时做一下笔记方便以后可以快速上手, 内容介绍:用esp32利用arduino点亮ili9341屏幕,本章内容没有触控以及,函数的使用介绍 ili9341引脚介绍: 1 VC ...
- 使用Arduino开发ESP32(16):DeepSleep和RTC Memory的使用
文章目录 目的 基础说明 DeepSleep RTC Memory 使用示例 部分方法说明 总结 目的 ESP32在工作时功耗蛮大的,所以我们可以在不需要时进行休眠,这也是蛮常用的功能. 基础说明 D ...
最新文章
- Jmeter JDBC执行多条SQL
- JAVA_OA管理系统(三)番外篇:Myeclipse导入Spring源码包
- 粤桂粤黔谋定现代农业产业园 林裕豪:从玉农业一县一园签约
- 计算机视觉--Python实现人体姿态估计
- scikit-learn学习笔记(五)Logistic regression(逻辑回归)
- php微信分享接口调用,TP5的微信分享接口和JSSDK使用
- Mybatis3(3)动态 SQL
- STM32F103按键操作的另一种实现——状态机
- 监控开发之用munin来自定义插件监控redis和mongodb
- jsp调用java的数据库连接,初学jsp,javabean连接数据库调用总是报错,疯了,求大神解决方案...
- web页面加载、解析、渲染过程
- Windows Server 2003 Enterprise Edition 下载与安装序列号
- Keli 编译遇到 *** FATAL ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED
- “移除”虚拟机和“从磁盘中删除”虚拟机的区别
- 人工智能轨道交通行业周刊-第44期(2023.5.8-5.14)
- 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java校园新闻发布管理系统574ec
- php公众号用户关注,微信公众号获取用户信息(用户关注公众号)
- Ui设计中常用的6大工具
- [MATLAB] 图像的插值算法1:MATLAB中的插值函数及其原理
- 使用CAS实现SSO.
热门文章
- iOS多线程的初步研究(三)-- NSRunLoop
- “学习金字塔”的真与假
- api存在csrf攻击吗_使用rest api防止单页应用上的csrf攻击
- 牧神记之后,宅猪新书《临渊行》首日八万排第二,不敌《庆余年》
- java页面数值转文本_Java读取Excel表格以及读取数字列转为文本的解决办法
- 家事:庆祝父亲60岁生日
- 去中心化存储项目终极指南 | Filecoin, Storj 和 PPIO 项目技术对比(上)
- snipeit 安装、备份文件恢复
- gophish配合邮件服务器,【CS】Cobalt Strike发送钓鱼邮件
- Ceph学习——客户端读写操作分析