一、前言
TCP/IP是干啥的?它跟SPI、IIC、CAN有什么区别?它怎样实现stm32的通讯?怎样去配置?为了搞懂这些问题,查询资料可办理如下疑问:
1.为什么要用以太网通讯?
以太网(Ethernet) 是指服从 IEEE 802.3 尺度构成的局域网,是互联网技术的一种,由于它是在组网技术中占的比例最高,很多人直接把以太网明白为互联网。但是,IEEE 另有别的局域网尺度,如 IEEE 802.11 是无线局域网,俗称 Wi-Fi。IEEE802.15 是个人域网,即蓝牙技术,其中的 802.15.4 尺度则是 ZigBee 技术。(想具体相识的可以欣赏这篇博客http://t.csdnimg.cn/3oz5b)
工业以太网是在以太网技术和Tcp/ip技术的底子上开辟出来的一种工业网络,在工业当中,由于以太网的用户培训成本低、产物技术成熟、价格低供应稳定、信息集成容易等上风,应用范围比较广,因此在STM32上使用还是很重要的。
以太网所用的协议则是TCP/IP通讯协议。
2.什么是TCP/IP?
TCP/IP是一个巨大的协议族,是浩繁网络协议的聚集,还包括:ARP、IP、ICMP、UDP、TCP、DNS、DHCP、HTTP、FTP、MQTT等等。TCP/IP 协议栈中差别协议所完成的功能是不一样的, 某些协议的实现要依赖于别的协议,依据这种依赖关系,可以将协议栈分层。低层协议为相邻的上层协议提供服务,是上层协议得以实现的底子。
3.TCP/IP分层模子是什么?
TCP/IP分成四层:应用层、传输层、网络层、网络接口层。分层就是让差别的底层网卡可以独立实现本身的功能,比如物理层提供二进制传输、实现编码为网络层提供尺度的接口,固然内部怎样实现无需在意。
传输过程:举个例子:加入你发送QQ消息给朋侪A,“周末出来玩吗?”,按下“发送”大概回车键时,盘算机怎样将这些信息传输已往呢?
你发送消息:
(1)应用层:发现你传输的数据有一条文字信息,于是做好了标记,加上应用层首部,传送到传输层。
(2) 传输层:由于对方也需要用QQ接收你发来的消息,因此就用到了“端口”(电脑上有很多步伐,差别步伐由差别的端口来辨认),于是做好端口标记,再加上TCP首部,跟之前的部分形成TCP,送往网络层
(3) 网络层:由于网路是由无数的子网层成的,要想把信息发送到对方的电脑中,就得用到IP地点,把数据送到相应的子网中找到对应的IP地点(IP地点包括网络号和主机号,网络号类似则判定在同一个子网下)的电脑。于是做好标记,加上IP首部,与之前的部分形成IP数据包,送到链路层。
(4)数据链路层:连入网络的每个盘算机都会有网卡接口,每个网卡都会有一个唯一的地点,名叫“MAC地点”。盘算机之间的数据传输就是通过MAC地点来唯一寻找并传送的(MAC地点由48位二进制所构成,在网卡生产时就唯一标识了)。所以当我们需要发送数据时,不仅要找到电脑主机,还要知道 MAC地点。假设ARP协议帮我们找到目标主机的MAC地点,但有时候发送的信息有些大,一次发送不出去,这是链路层便会切开成一组一组的,并一次次发送出去。
(5)物理层:收到数据链路层的数据,根据二进制分别为高低电平举行传输。
朋侪A接收消息:
(1)物理层:0101....的电平信号经过,物理层把数据接收给链路层。
(2)链路层:如果MAC地点相匹配,便会排序检察数据是否有问题,没问题就拆掉以太网首部,把剩下的交给IP层。
(3)IP层:发现有数据,就拆掉IP首部,交给传输层
(4)传输层:发现目标地是送往是QQ端口,于是拆掉TCP首部,交给应用层
(5)应用层:QQ页面显示“周末出来玩吗?”
4.LwIP是什么?和TCP/IP有什么关系?
(1)LWIP的定义:
Light weight IP,顾名思义是一个轻量化的TCP/IP协议,由瑞典盘算机科学院(SICS)的ADam Dunkels开辟的一个小型开源的TCP/IP协议栈
(2)LWIP设计目标:用少量的资源消耗实现一个较为完备的TCP/IP协议栈。能用于云台接入、无线网关、远程模块、工控控制器、路由器、摄像头
(3)LWIP与TCP/IP的区别:
【1】LWIP并没有实现TCP/IP的全部功能
【2】极大地减少了对RAM的占用
【3】LWIP既可以移植到操作体系上运行,也可以在无操作体系的环境下独立运行
【4】LWIP并没有采用很明白的分层结构,它假设各层之间的部分数据和结构体和实现原理在其他层是可见的,简单来说就传输层知道IP层是怎样封装数据、通报数据的,IP层知道链路层是怎么封装数据的等等,可以实现内存区域共用,极大制止数据拷贝,尽可能减少占用。
(4)LWIP的特点:
【1】资源开销低,高度可以剪裁,一切不需要的功能都可以通过红变异选项去掉,LWIP的流畅运行需要40KB的代码ROM的几十KB的RAM
【2】支持的协议较为完备
【3】实现了一些常见的应用步伐,DHCP客户端、DNS客户端、HTTP服务器等
【4】提供了三种编程接口:RAW/Callback API(得当少任务、交互数据量少、数据处理惩罚时间开销小的场合)、NETCONN API(就是Sequential API,得当多任务、大数据量、大型应用)和 Socket API(是对NETCONN API的简单封装、更简单、但服从低、功能不完备)
【5】高度可移植。其源代码全部用 C 实现 【6】开源、免费,用户可以不用承担任何商业风险地使用它 【7】发展历史长
5.LwIP协议栈?
协议栈是协议的具体实现形式,通俗来讲就是用代码实现的库函数,从而让开辟职员调用。因此我们在LWIP官网下载最新版,然后把内里的代码文件服战在本身的工程当中,然后用LWIP提供给用户的接口函数在字节的步伐里实现TCP通讯的功能。
6.TCP的“三次握手”和“四次挥手”是什么意思?
TCP是一种面向毗连的传输协议,通俗来讲,UDP就像你妈在楼下扯一嗓子让你下楼帮助,所有人都听得到,而且你也容易听不清;而TCP就像你妈打电话给你,信息传输一对一且稳定。
“三次握手”是确认毗连的方式: 通俗来讲就是用三次发送来让双方确认本身与对方的发送与接收是正常的。 第一次 A:我要和B通讯 第二次 B:好,我可以和你通讯(当A收到这段话时,A已经确认了毗连的可靠性,但B还不能确认A可否听到本身的回话) 第三次:A:我能听到你的回话,可以开始了。(这时候双方都确认了毗连的可靠性) 如果握手尝试5次都没回应,就断开。
“四次挥手”是确认断开毗连的方式: 通俗来讲就是用四次发送来让双方都确认毗连的断开。 第一次 A:我要去忙别的了,不和你说了 第二次 B:我这句话另有一半没讲完呢,你听我说完再走 第三次 B:好的我说完了,你去忙吧 第四次 A:好的,我走了(A发完后会停顿2毫秒,如果收到B的释放报文,说明B已经收到了释放信号,毗连断开) 如果B充公到第四次挥手,就会重复发送第三次的释放信号,A发完后会停顿2毫秒,如果还受到了B的第三次挥手信号,说明B充公到第四次挥手,这时候会A会再次重复第四次挥手。
二、STM32F4以太网MAC简介
以太网MAC存在于TCPIP栈中的数据链路层上。STM32F4自带有10/100Mbit/s的以太网MAC内核,
这个以太网MAC内核有如下特性:
- 支持外部PHY接口实现10M/100Mbit/s数据传输速率
- 通过符合IEEE802.3的MII接口与外界快速以太网PHY举行通讯
- 支持全双工和半双工操作
- 报头和帧起始数据(SFD)在发送路径中插入、在接收员路径中删除
- 可逐帧控制CRC和pad主动生成
- 可编程帧长度,支持高达16kB的巨型帧...
由图中我们可以知道:
数据从芯片出发,通过以太网DMA传输,由FIFO寄存器收发,经过MAC,再通过时钟线MDC和数据线MDIO发送给外部PHY。
以太网接收发送FIFO数据寄存器的大小为2KB(发送的数据不能凌驾1500个字节)以及STM32F4的以太网与外部PHY通过RMII接口和MII接口管理
F4的MAC接口有3个接口:SMI、MII、RMII
1. 站管理接口:SMI
步伐中可以通过这个接口来访问PHY寄存器,SMI接口有两根线:数据线MDIO和时钟线MDC,该接口支持访问多达32个PHY。
MDC:周期性时钟,提供以最大频率2.5Mhz传输数据时的参考时序,在空闲状态下,SMI管理接口将MDC时钟信号驱动为低电平。
MDIO:数据输入/输出比特流,用于通过MDC时钟信号向/从PHY装备同步传输状态信息。
管理帧格式:(STM32F4XX中文参考手册P825)
PADDR:PHY地点
RADDR:寄存器地点
数据位:16位数据位(PHY寄存器都是16位的)
2. 介质独立接口:MII
介质独立接口(MII)定义了10Mbit/s和100Mbit/s的数据传输速率下,以太网内核与PHY装备之间的毗连
TX_CLK和RX_CLK为发送和接收连续时钟,当速率为10Mbit/s时为2.5MHZ,速率为100Mbit/s时为25MHZ
要生成TX_CLK和RX_CLK时钟,必须向外部PHY提供25MHZ时钟,通常我们使用25M的晶振,也可以使用STM32F4xx的MCO的引脚输出25MHZ的时钟
3. 精简介质独立接口:RMII
精简介质独立接口 (RMII) 规范低落了 10/100 Mbit/s 下微控制器以太网外设与外部 PHY 间的引脚数。根据 IEEE 802.3u 尺度,MII 包括 16 个数据和控制信号的引脚。RMII 规范将引脚数减少为 9 个。
MAC和PHY的参考时钟必须都是 50 MHz!
三、PHY层芯片LAN8720
RJ45 <-> PHY芯片 <-> 以太网MAC
是一个低功耗的10/100M以太网PHY层芯片,使用RMII接口和以太网MAC层举行通讯,内置全双工模块,支持10Mbps和100Mbps。可以通过自卸调的方式与目标主机最佳的毗连方式。支持主动翻转功能,无需更换网线即可将毗连更改为直连或交织毗连。
1.原理图
(1)STM32引脚:
(2)EARTHNET:
(3)RJ45:
(4)PCF8574
io扩展芯片
2.LAN8920说明
(1)PHY地点
上文有说MAC可以通过SML接口毗连32个PHY芯片,那怎样辨认这32个PHY呢?就是通过PHY地点来区别的。
由于三(2)的原理图中第10号引脚浮空,默认为地点0x00
(2)RMII模式设置
LAN8720在RMII模式下可以设置两种毗连模式:
REF_CLK输入模式(nINT)和REF_CLK输出模式。
配置模式决定了nINT / REFCLKO引脚的功能。 nINTSEL配置带锁定在POR和nRST的上升沿。默认环境下,通过内部上拉电阻将nINTSEL配置为nINT模式。
表带值模式REF_CLK说明nINT引脚 = 0REF_CLK输出模式作为REF_CLK时钟源nINT引脚 = 1REF_CLK输入模式作为中断引脚 REF_CLK来自外部,必须在XTAL1 / CLKIN引脚上驱动。
i. REF_CLK输入模式
在REF_CLK输入模式下,XTAL1/CLKIN引脚驱动50 MHz REF_CLK。使用该模式时,必须在器件外部提供用于REF_CLK的50 MHz源。如图所示,时钟同时驱动到MAC和PHY。
ii.REF_CLK输出模式
为了低落BOM成本,该器件具有从低成本25 MHz晶体生成RMII REF_CLK信号的功能。与通常需要50 MHz的第三泛音晶体相比,这种类型的晶体自制。 MAC必须可以大概与外部时钟一起使用,才气利用此功能。
从25 MHZ晶体中获取REF_CLK:
在某些体系架构中,可以使用25 MHz的时钟源。该器件可用于为MAC生成REF_CLK,在此特定示例中,只能使用25 MHz的时钟(时钟不能为50 MHz)。与25 MHz晶振模式相似,nINT功能被禁用。
外部25 MHZ源得到REF_CLK:
3.PHY寄存器
LAN8720有32个寄存器,每个寄存器都有16位。
这32个寄存器中分为两类:
类似的寄存器:根据IEEE尺度定义0~15寄存器(重点BCR和BSR寄存器根据用户实现的功能来设置)
自由定义的寄存器:16~31寄存器是由芯片制造商自由定义(一样寻常无需修改)
在正点原子案例代码中
PHY_SR=0X1F 指的是第31位的寄存机(也就是上图寄存器)
PHY_SPEED_STATUS=0X0004 指的是PHY的速度为100Mbit/s(根据上图寄存器配置而成)
PHY_DUPLEX_STATUS=0X0010 指的是半双工传输模式(根据上图寄存器配置而成)
4.以太网DMA形貌符
学过STM32-DMA内容的同砚们都应该知道DMA是不需要CPU的参与就可以实现内存和外设之间的数据互换。同样的,对于STM32互联型单片机的以太网DMA的作用也是云云,它的作用就是在不需要CPU的参与下,实现内存和以太网外设的数据互换。通俗来说,就是我们将要发送的数据放在一片内存去,告诉以太网DMA,我已经将数据放已往了,你去取出来发送到网络中去;当网络数据来的时候,以太网DMA主动将数据拷贝到一片内存中,通过中断的方式告诉CPU,数据来了,你去取出来吧。
发送:不需要CPU的参与下,把形貌符指向的缓冲区数据传输到TX FIFO当中
接收:不需要CPU的参与下,将RX FIFO的数据传输到形貌符指向的缓冲区当中
形貌符分为:
常规形貌符:管理缓冲区
增强形貌符:在常规形貌符底子上开启时间戳和IPV4(内容不讲)
形貌符不是实际存在的物理结构,而是在步伐中通过软件实现的,实在就是一个结构体。
常规形貌符的结构体代码:
TX DMA形貌符成员变量:
- TDES0[31]置0:CPU可将数据拷贝到形貌符中,拷贝完成之后把该位置为1,告诉DMA可以发送出去了
- TDES0[20]置1:形貌符中的第二个地点是下一个形貌符地点【ST以太网驱动库是TDES0[20]置1】
- TDES0[28:16]:如果TDES0[20]位置为1,则该字段无效
- TDES0[31:0]:取决于TDES0[20]的值,为1,则指向下一个形貌符地点
RX DMA形貌符成员变量:
RDES0[31]置0:MAC将数据从RX FIFO传输到RX形貌符中,拷贝完成之后将该位置0,告诉CPU可以接收数据
RDES0[14]置1:形貌符中的第二个地点是下一个形貌符地点【ST以太网驱动库是RDES0[14]置1】
RDES0[28:16]:如果RDES0[14]位置为1,则该字段无效
RDES0[31:0]:取决于RDES0[14],为1,则指向下一个形貌符地点
STM32 ETH-DMA形貌符(只用到了常规形貌符而未用到增强型形貌符):
ETH为发送接收申请内存:
发送:网络层下达pbuf->拷贝到TXFIFO->MAC->HY(光电信号);
接收:外部->HY->mac->RXFIFO->网络层
其中 ETH_TX_BUF_SIZE = ETH_MAX_PACKET_SIZE形貌符最大长度为1524
STM32中提供的以太网驱动库使用的是链接结构:
形貌符留意事项:
1.一个以太网数据包可以凌驾一个或多个DMA形貌符
2.一个DMA形貌符只能用于一个以太网数据包
3.DMA形貌符列表中的最后一个形貌符指向第一个,形成链式结构
四、正点原子重点代码分析
总流程如下所示
1、LWIP初始化
- //LWIP初始化(LWIP启动的时候使用)
- //返回值:0,成功
- // 1,内存错误
- // 2,LAN8720初始化失败
- // 3,网卡添加失败.
- u8 lwip_comm_init(void)
- {
- u8 retry=0;
- struct netif *Netif_Init_Flag; //调用netif_add()函数时的返回值,用于判断网络初始化是否成功
- struct ip_addr ipaddr; //ip地址
- struct ip_addr netmask; //子网掩码
- struct ip_addr gw; //默认网关
-
- if(ETH_Mem_Malloc())return 1; //内存申请失败
- if(lwip_comm_mem_malloc())return 2; //内存申请失败
- lwip_comm_default_ip_set(&lwipdev); //设置默认IP等信
- while(LAN8720_Init()) //初始化LAN8720,如果失败的话就重试5次
- {
- retry++;
- if(retry>5) {retry=0;return 3;} //LAN8720初始化失败
- }
- lwip_init(); //初始化LWIP内核
-
- #if LWIP_DHCP //使用动态IP
- ipaddr.addr = 0;
- netmask.addr = 0;
- gw.addr = 0;
- #else //使用静态IP
- IP4_ADDR(&ipaddr,lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
- IP4_ADDR(&netmask,lwipdev.netmask[0],lwipdev.netmask[1] ,lwipdev.netmask[2],lwipdev.netmask[3]);
- IP4_ADDR(&gw,lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
- printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
- printf("静态IP地址........................%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
- printf("子网掩码..........................%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
- printf("默认网关..........................%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
- #endif
- Netif_Init_Flag=netif_add(&lwip_netif,&ipaddr,&netmask,&gw,NULL,ðernetif_init,ðernet_input);//向网卡列表中添加一个网口
-
- #if LWIP_DHCP //如果使用DHCP的话
- lwipdev.dhcpstatus=0; //DHCP标记为0
- dhcp_start(&lwip_netif); //开启DHCP服务
- #endif
-
- if(Netif_Init_Flag==NULL)return 4;//网卡添加失败
- else//网口添加成功后,设置netif为默认值,并且打开netif网口
- {
- netif_set_default(&lwip_netif); //设置netif为默认网口
- netif_set_up(&lwip_netif); //打开netif网口
- }
- return 0;//操作OK.
- }
复制代码
(1)ETH_Mem_Malloc():
为形貌符及缓冲区申请内存,除了这种用算法实现的内存申请函数可以申请内存之外,ST官方给出的例程是使用简单的使用数组来实现申请内存。
(2)判定是否开启DHCP(动态IP)
未开启则采用静态IP:申请远端IP地点、网卡MAC地点、本地IP地点、子网掩码、默认网关
(3)以太网环境配置
配置以太网环境、并且初始化RMII的IO(通过调用的HAL_ETH_Init函数,它会调用HAL_ETH_MspInit函数初始化相应的接口IO以及复位PHY芯片管脚)、复位PHY芯片(非常重要,不复位以太网通讯不能成功)
(4)初始化LwIP内核
它是LwIP内核源码自带的函数,初始化了一系列函数,如sys_init()、mem_init()、pbuf_init()、netif_init()。
2.添加虚拟网卡
LwIP是软件,怎样管理真正的以太网硬件呢,比如网络接口有多种,如WIFI接口、以太网接口,怎么管理这些实际的网络接口,LwIP抽象了一个虚拟网卡来管理这些各种硬件网络接口。
(1)ethernetif_init:
网卡初始化,设置虚拟网卡参数,该函数在ethernetif.c文件中已经帮我们实现好了整体框架。它会调用low_level_init函数,该函数初始化发送和接收形貌符,并开启ETH中断。
(2)err_t low_level_init:
初始化发送和接收形貌符,并开启ETH中断。
(3)ethernetif_input:
以太网数据包输入,这里LwIP默认已经帮我们实现好了框架。开启虚拟网卡:通过low_level_input接收,再用netif结构体中的input字段(一个函数)来处理惩罚数据包
3.虚拟网卡控制块
4.发送流程
5.接收流程
接收有两种方式接收数据包,一种是查询式接收数据包,一种是中断方式接收数据包。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |