文章目录
一.概要
以太网(Ethernet)。指的是由Xerox公司创建并由Xerox,Intel和DEC公司联合开发的基带局域网规范。以太网络使用CSMA/CD(载波监听多路访问及冲突检测技术)技术,并以10M/S的速率运行在多种类型的电缆上。以太网与IEEE802·3系列标准相类似。 它不是一种具体的网络,是一种技术规范。 以太网是当今现有局域网采用的最通用的通信协议标准。该标准定义了在局域网(LAN)中采用的电缆类型和信号处理方法。以太网在互联设备之间以10~100Mbps的速率传送信息包,双绞线电缆10 Base T以太网由于其低成本、高可靠性以及10Mbps的速率而成为应用最为广泛的以太网技术。
以太网是一种广泛应用于各种计算机局域网技术,被普遍用于以下场景:
工业自动化:以太网在工业自动化领域有着广泛的应用。它能够满足工业自动化系统对大量数据传输和实时性的需求,支持多设备连接,适应高温、高湿等恶劣环境,适用于复杂的工业环境。
企业网络:在企业网络中,以太网用于构建高速、稳定的内部网络,支持数据、视频和语音等多业务传输。它广泛应用于大型企业和数据中心,提供高速数据传输支持。
智能交通:在智能交通系统中,以太网连接交通监控设备,实现交通数据的实时传输。这有助于提高交通管理的效率和安全性。
远程监控:在远程监控系统中,以太网用于将监控数据传输到控制中心,提高监控效率。它广泛应用于各种远程监控场景,如环境监测、设备监控等。
数据中心:数据中心使用以太网连接服务器和存储设备,实现高速数据交换。万兆以太网在数据中心的应用尤为广泛,满足高性能计算和大数据处理的需求。
超级计算中心:在超级计算中心,万兆以太网设备提供高密度的端口和快速的交换性能,满足高性能计算机架构和网络的需求,促进计算机科学研究的发展。
二.单片机以太网系统基本结构
1.OSI 七层模型
OSI七层模型是国际标准化组织(ISO)定义的一个网络通信框架,旨在为不同计算机系统之间的通信提供一个标准化的方法。这个模型将网络通信过程划分为七个层次,从物理层到应用层,每一层都有其特定的功能和协议。
2.单片机实现以太网功能组成
一般单片机组成以太网所需部件是:单片机+MAC+PHY+RJ45。
GD32F407VET6内部自带MAC,所以要组成以太网,主要部件就是
GD32F407VET6+PHY+RJ45。
我们常见的以太网PHY芯片是DP83848和LAN8720。
以太网MAC:即媒体访问控制子层协议,位于OSI七层协议中的数据链路层下半部分,主要负责控制与连接物理层的物理介质。MAC协议的主要功能包括在发送数据时判断是否可以发送,如果可以发送,则给数据加上一些控制信息,最终将数据以及控制信息以规定的格式发送到物理层;在接收数据时,MAC协议首先判断输入的信息是否发生传输错误,如果没有错误,则去掉控制信息发送至逻辑链路控制层。
以太网PHY:即物理层接口收发器,是网络通信中的一个重要组成部分,它实现了OSI模型中的物理层。IEEE-802.3标准定义了以太网PHY,包括多个子层,如MII/GMII(介质独立接口)、PCS(物理编码子层)、PMA(物理介质附加子层)、PMD(物理介质相关子层)和MDI子层。这些子层共同定义了数据传送与接收所需要的电与光信号、线路状态、时钟基准、数据编码和电路等,并向数据链路层设备提供标准接口。
三.GD32F407VET6单片机以太网内部结构
以太网在进行数据发送时,单片机首先将数据由系统存储器以 DMA 的方式送至发送 FIFO (Tx FIFO) 进行缓冲,再通过 MAC内核发送,MAC通过RMII或者MII接口与外部PHY进行通讯。
以太网在进行数据接收时,接收 FIFO (Rx FIFO) 则存储通过线路接收的以太网帧,直到这些帧通过 DMA 传送到系统存储器。
1.MII接口介绍
介质独立接口 (MII) 定义了 10 Mbit/s 和 100 Mbit/s 的数据传输速率下 MAC 子层与 PHY 之
间的互连。
MII连接示意图
2.RMII接口介绍
精简介质独立接口 (RMII) 规范降低了 10/100 Mbit/s 下微控制器以太网外设与外部 PHY 间的引脚数。
RMII连接示意图
对比以上两种连接方式,RMII通过减少信号线数量和提高时钟频率,提供了一种在保持或提高数据传输速率的同时简化硬件设计的解决方案。这种接口在需要平衡成本、性能和复杂性的应用中特别有用,所以在GD32开发中,最常见的是RMII连接方式。
四.LWIP TCP/IP协议栈介绍
TCP/IP 协议栈是一系列网络协议的总和,它允许不同电子设备在因特网上进行通信。该协议采用4层结构,分别是应用层、传输层、网络层和网络接口层,每一层都依赖于其下面的层,同时为其上面的层提供服务。
TCP/IP 协议栈和传统的 OSI 模型并不完全对应。TCP/IP 协议是一个简化的模型,强调了实际的协议实现和因特网的实际运作方式。
Light weight IP(LWIP)是轻量化的 TCP/IP 协议,是瑞典计算机科学院(SICS)的 Adam Dunkels 开发的一个小型开源的 TCP/IP 协议栈。 LwIP 的设计初衷是:用少量的资源消耗(RAM)实现一个较为完整的 TCP/IP 协议栈, 在保持 TCP 协议主要功能的基础上减少对 RAM 的占用。
LwIP既可以移植到操作系统上运行,也可以在无操作系统的情况下独立运行。它只需十几KB的RAM和40K左右的ROM就可以运行,这使LwIP协议栈适合在低端的嵌入式系统中使用。
LwIP是符合 TCP/IP 模型架构,规定了数据的格式、传输、路由和接收,以实现端到端的通信。
应用层:lwIP提供了TCP/IP协议栈的实现,包括HTTP,MQTT等协议
传输层:lwIP实现了TCP和UDP协议
网络层:lwIP实现了IP协议
网络接口层:lwIP并没有实现,这一层由硬件来实现
五.PHY收发器LAN8720介绍
LAN8720A是一款低功耗的10/100M以太网PHY芯片,符合EEE802.3-2005标准,支持通过RMII接口与以太网MAC层通信。 它内置了10-BASE-T/100BASE-TX全双工传输模块,支持10Mbps和100Mbps的传输速度。LAN8720A具有自协商功能,能够与目的主机自动选择最佳连接方式(速度和双工模式),并支持HP Auto-MDIX自动翻转功能,无需更换网线即可实现直连或交叉连接。此外,它还支持通过SMI串行管理接口和MAC接口进行配置和管理。
1.LAN8720内部框图
2.LAN8720应用电路
3.LAN8720以太网模块
LAN8720以太网模块是把PHY,RJ45都放在一块小板子上,只要开发板与模块通过RMII连接,就能组成以太网系统。
模块参考原理图
六.配置一个LWIP的TCP/IP通讯协议实验
硬件准备:
STLINK接GD32F407VET6开发板,STLINK接电脑USB口。LAN8720模块接到开发板上,网线接模块的RJ45口跟电脑。
开发板以太网接口定义:
添加代码
查看服务器IP地址配置是否正确
电脑CMD命令界面使用ipconfig /all命令查看电脑以太网的IP地址,注意是以太网的IP地址,不是无线WIFI。
程序中设置的IP地址要与电脑服务器的IP地址,网关匹配。
主要代码如下:
#include "gd32f4xx.h"
#include "netconf.h"
#include "main.h"
#include "lwip/tcp.h"
#include "lwip/lwip_timers.h"
#include "hello_gigadevice.h"
#include "udp_echo.h"
#include "tcp_client.h"
#define SYSTEMTICK_PERIOD_MS 10
__IO uint32_t g_localtime = 0; /* for creating a time reference incremented by 10ms */
uint32_t g_timedelay;
extern struct tcp_pcb *tcp_active_pcbs;
/***********************************************************************
函数名称:Check_TCP_Connect(void)
功 能:检查连接
***********************************************************************/
struct tcp_pcb *Check_TCP_Connect(void)
{
struct tcp_pcb *cpcb = 0;
for(cpcb = tcp_active_pcbs;cpcb != NULL; cpcb = cpcb->next)
{
if(cpcb -> state == ESTABLISHED) //如果得到应答,则证明已经连接上
{
break;
}
}
return cpcb;
}
unsigned char tcp_data[] = "tcp 客户端实验!\n";
struct tcp_pcb *pcb;
int main(void)
{
/* setup ethernet system(GPIOs, clocks, MAC, DMA, systick) */
enet_system_setup();
/* initilaize the LwIP stack */
lwip_stack_init();
tcp_client_init();//tcp连接,对方端口号是8888,IP地址是192.168.1.11
while(1){
delay_10ms(50);
pcb = Check_TCP_Connect();//查询是否连接
if(pcb!=0)
{
tcp_write(pcb, tcp_data,sizeof(tcp_data), 1);//发送数据
}
#ifndef USE_ENET_INTERRUPT
/* check if any packet received */
if(enet_rxframe_size_get()){
/* process received ethernet packet */
lwip_pkt_handle();
}
#endif /* USE_ENET_INTERRUPT */
lwip_periodic_handle(g_localtime);
}
}
/*!
\brief initialize the tcp_client application
\param[in] none
\param[out] none
\retval none
*/
void tcp_client_init(void)
{
struct tcp_pcb *pcb;
struct ip_addr ipaddr;
IP4_ADDR(&ipaddr, IP_S_ADDR0, IP_S_ADDR1, IP_S_ADDR2, IP_S_ADDR3);
/* create a new TCP control block */
pcb = tcp_new();
/* assign to the new pcb a local IP address and a port number */
/* using IP_ADDR_ANY allow the pcb to be used by any local interface */
if(ERR_USE != tcp_bind(pcb, IP_ADDR_ANY, 10260)){
/* Specify the function to be called when a connection is established */
tcp_connect(pcb, &ipaddr, 8888, tcp_client_connected);//连接8888端口
}else{
printf("connect is still alive \r\n ");
memp_free(MEMP_TCP_PCB, pcb);
}
}
/*!
TCP接收数据
*/
static err_t tcp_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct pbuf *q;
struct recev_packet *recev_packet = (struct recev_packet *)arg;
int buf_full;
char *c;
int i;
/* we perform here any necessary processing on the pbuf */
if (p != NULL){
/* we call this function to tell the LwIp that we have processed the data */
/* this lets the stack advertise a larger window, so more data can be received*/
tcp_recved(pcb, p->tot_len);
/* check the name if NULL, no data passed, return withh illegal argument error */
if(!recev_packet){
pbuf_free(p);
return ERR_ARG;
}
buf_full = 0;
for(q=p; q != NULL; q = q->next){
c = q->payload;
for(i=0; i<q->len && !buf_full; i++){
/* if the received data size is larger than the size we want to get */
if(recev_packet->length < MAX_BUF_SIZE){
recev_packet->bytes[recev_packet->length] = c[i];
recev_packet->length++;
}else{
buf_full = 1;
}
}
}
/* send out the message */
tcp_write(pcb, recev_packet->bytes, recev_packet->length, 1);
recev_packet->length = 0;
pbuf_free(p);
}else if(ERR_OK == err){
mem_free(recev_packet);
return tcp_close(pcb);
}
return ERR_OK;
}
调试运行
板子运行起来之后,用CMD命令界面ping板子,可以看到能ping通。
打开电脑上位机服务器,如下图所示,可以在电脑上位机的左下角看到板子的IP地址,说明板子登录电脑服务器成功,同时能收到板子发送的数据。
电脑上位机发送数据,在TCP数据接收函数处设置断点,能查看到板子接收到数据后就能运行到断点处,接收的数据与上位机发送的数据一致,如下图。
七.工程源代码下载
源代码下载链接如下:
CSDN
八.小结
STM32F407开发板加上LAN8720模块可以通过网络连接,实现远程控制、数据传输等功能。