商城网站建设专业公司,如何从零开始学室内设计,软件开发专业专升本都考什么,小红书官方推广平台一、前言
TCP/IP是干啥的#xff1f;它跟SPI、IIC、CAN有什么区别#xff1f;它如何实现stm32的通讯#xff1f;如何去配置#xff1f;为了搞懂这些问题#xff0c;查询资料可解决如下疑问#xff1a;
1.为什么要用以太网通信? 以太网(Ethernet) 是指遵守 IEEE 802.3 …一、前言
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层。
3IP层发现有数据就拆掉IP首部交给传输层
4传输层发现目的地是送往是QQ端口于是拆掉TCP首部交给应用层
5应用层QQ页面显示“周末出来玩吗”
4.LwIP是什么和TCP/IP有什么关系
1LWIP的定义:
Light weight IP,顾名思义是一个轻量化的TCP/IP协议由瑞典计算机科学院SICS的ADam Dunkels开发的一个小型开源的TCP/IP协议栈
2LWIP设计目的用少量的资源消耗实现一个较为完整的TCP/IP协议栈。能用于云台接入、无线网关、远程模块、工控控制器、路由器、摄像头
3LWIP与TCP/IP的区别
【1】LWIP并没有实现TCP/IP的全部功能
【2】极大地减少了对RAM的占用
【3】LWIP既可以移植到操作系统上运行也可以在无操作系统的情况下独立运行
【4】LWIP并没有采用很明确的分层结构它假设各层之间的部分数据和结构体和实现原理在其他层是可见的简单来说就传输层知道IP层是如何封装数据、传递数据的IP层知道链路层是怎么封装数据的等等可以实现内存区域共用极大避免数据拷贝尽可能减少占用。
4LWIP的特点
【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 PADDRPHY地址
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.原理图
1STM32引脚 2EARTHNET 3RJ45: 4PCF8574
io扩展芯片 2.LAN8920说明
1PHY地址
上文有说MAC可以通过SML接口连接32个PHY芯片那如何识别这32个PHY呢就是通过PHY地址来区别的。 由于三2的原理图中第10号引脚浮空默认为地址0x00 2RMII模式设置
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_SR0X1F 指的是第31位的寄存机也就是上图寄存器
PHY_SPEED_STATUS0X0004 指的是PHY的速度为100Mbit/s根据上图寄存器配置而成
PHY_DUPLEX_STATUS0X0010 指的是半双工传输模式根据上图寄存器配置而成
4.以太网DMA描述符
学过STM32-DMA内容的同学们都应该知道DMA是不需要CPU的参与就可以实现内存和外设之间的数据交换。同样的对于STM32互联型单片机的以太网DMA的作用也是如此它的作用就是在不需要CPU的参与下实现内存和以太网外设的数据交换。通俗来说就是我们将要发送的数据放在一片内存去告诉以太网DMA我已经将数据放过去了你去取出来发送到网络中去当网络数据来的时候以太网DMA自动将数据拷贝到一片内存中通过中断的方式告诉CPU数据来了你去取出来吧。
发送不需要CPU的参与下把描述符指向的缓冲区数据传输到TX FIFO当中
接收不需要CPU的参与下将RX FIFO的数据传输到描述符指向的缓冲区当中
描述符分为 常规描述符管理缓冲区 增强描述符在常规描述符基础上开启时间戳和IPV4内容不讲
描述符不是实际存在的物理结构而是在程序中通过软件实现的其实就是一个结构体。
常规描述符的结构体代码 TX DMA描述符成员变量 TDES0[31]置0CPU可将数据拷贝到描述符中拷贝完成之后把该位置为1告诉DMA可以发送出去了 TDES0[20]置1描述符中的第二个地址是下一个描述符地址【ST以太网驱动库是TDES0[20]置1】 TDES0[2816]如果TDES0[20]位置为1则该字段无效 TDES0[310]取决于TDES0[20]的值为1则指向下一个描述符地址
RX DMA描述符成员变量 RDES0[31]置0MAC将数据从RX FIFO传输到RX描述符中拷贝完成之后将该位置0告诉CPU可以接收数据
RDES0[14]置1描述符中的第二个地址是下一个描述符地址【ST以太网驱动库是RDES0[14]置1】
RDES0[2816]如果RDES0[14]位置为1则该字段无效
RDES0[310]取决于RDES0[14]为1则指向下一个描述符地址 STM32 ETH-DMA描述符只用到了常规描述符而未用到增强型描述符 ETH为发送接收申请内存 发送网络层下达pbuf-拷贝到TXFIFO-MAC-PHY(光电信号)
接收外部-PHY-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 retry0;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(retry5) {retry0;return 3;} //LAN8720初始化失败}lwip_init(); //初始化LWIP内核
#if LWIP_DHCP //使用动态IPipaddr.addr 0;netmask.addr 0;gw.addr 0;
#else //使用静态IPIP4_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]);
#endifNetif_Init_Flagnetif_add(lwip_netif,ipaddr,netmask,gw,NULL,ethernetif_init,ethernet_input);//向网卡列表中添加一个网口#if LWIP_DHCP //如果使用DHCP的话lwipdev.dhcpstatus0; //DHCP标记为0dhcp_start(lwip_netif); //开启DHCP服务
#endifif(Netif_Init_FlagNULL)return 4;//网卡添加失败 else//网口添加成功后,设置netif为默认值,并且打开netif网口{netif_set_default(lwip_netif); //设置netif为默认网口netif_set_up(lwip_netif); //打开netif网口}return 0;//操作OK.
} 1ETH_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抽象了一个虚拟网卡来管理这些各种硬件网络接口。
1ethernetif_init
网卡初始化设置虚拟网卡参数该函数在ethernetif.c文件中已经帮我们实现好了整体框架。它会调用low_level_init函数该函数初始化发送和接收描述符并开启ETH中断。 2err_t low_level_init
初始化发送和接收描述符并开启ETH中断。 3ethernetif_input
以太网数据包输入这里LwIP默认已经帮我们实现好了框架。开启虚拟网卡通过low_level_input接收再用netif结构体中的input字段(一个函数)来处理数据包 3.虚拟网卡控制块 4.发送流程 5.接收流程
接收有两种方式接收数据包一种是查询式接收数据包一种是中断方式接收数据包。