前言
在需要使用lwip以太网功能时,可以选择ST支持以太网互联型芯片,如107或105;
当然也可以选择103 + 网卡驱动芯片(如:ENC28J60、DM9000等);
该文章只介绍107芯片中以太网ETH模块的配置过程;
ETH框图
STM32F107xx支持以太网模块的面纱就是这样,那么我们该如何配置里面的PHY、MAC和以太网专用的DMA以实现底层的配置呢?容许我慢慢道来。
1、网卡结构
网卡是一块被设计用来允许计算机在计算机网络上进行通讯的计算机硬件。由于其拥有MAC地址,因此属于OSI模型的第2层。它使得用户可以通过电缆或无线相互连接。每一个网卡都有一个被称为MAC地址的独一无二的48位串行号,它被写在卡上的一块ROM中。在网络上的每一个计算机都必须拥有一个独一无二的MAC地址。没有任何两块被生产出来的网卡拥有同样的地址。这是因为电气电子工程师协会(IEEE)负责为网络接口控制器(网卡)销售商分配唯一的MAC地址。
以太网卡中数据链路层的芯片一般简称之为MAC控制器,物理层的芯片我们简称之为PHY。
1.1、MAC 802.3
该部分不是两言三语就可以说明白的,《STM32中文参考手册》中有详细的介绍;如果还不够喂饱您,那就自己找吃的;反正网卡没它不行;
1.2、PHY
PHY是物理接口收发器,它实现物理层。包括MII/GMII(介质独立接口)子层、PCS(物理编码子层)、PMA(物理介质附加)子层、PMD(物理介质相关)子层、MDI子层。
100BaseTX采用4B/5B编码。PHY在发送数据的时候,收到MAC过来的数据(对PHY来说,没有帧的概念,对它来说,都是数据而不管什么地址,数据还是CRC),每4bit就增加1bit的检错码,然后把并行数据转化为串行流数据,再按照物理层的编码规则把数据编码,再变为模拟信号把数据送出去。收数据时的流程反之。
PHY还有个重要的功能就是实现CSMA/CD的部分功能。它可以检测到网络上是否有数据在传送,如果有数据在传送中就等待,一旦检测到网络空闲,再等待一个随机时间后将送数据出去。如果两个碰巧同时送出了数据,那样必将造成冲突,这时候,冲突检测机构可以检测到冲突,然后各等待一个随机的时间重新发送数据。这个随机时间很有讲究的,并不是一个常数,在不同的时刻计算出来的随机时间都是不同的,而且有多重算法来应付出现概率很低的同两台主机之间的第二次冲突。
这里说怎么多可能您看不懂,没关系会配就行;
2、配置ETH
void initEthernet()
{
setEthPowerOnOff(ENABLE);//打开ETH的时钟
ethGpioConfiguration();//配置以太网模块引脚
ethMacRegConfiguration();//配置PHY、MAC、DMA(重头戏)
}
①打开或关闭ETH的时钟
//打开或关闭ETH的时钟
void setEthPowerOnOff(FunctionalState state)
{
ethPowerState = state;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx |
RCC_AHBPeriph_ETH_MAC_Rx, state);
}
②配置以太网模块引脚
/*
*以太网RMII引脚定义
*/
#ifdef RMII_MODE
#define RMII_MDIO PA2
#define RMII_MDC PC1
#define RMII_TX_EN PB11
#define RMII_TXD0 PB12
#define RMII_TXD1 PB13
#define RMII_REF_CLK PA1
#define RMII_CRSDV PD8
#define RMII_RXD0 PD9
#define RMII_RXD1 PD10
#define RMII_MDINTR PC5
#endif
//配置以太网模块引脚
void ethGpioConfiguration(void)
{
//GPIO_InitTypeDef GPIO_InitStructure;
#ifdef MII_MODE
#elif defined RMII_MODE//使用RMII接口时
GPIO_Initialize(GpioType(RMII_MDIO), GpioIndex(RMII_MDIO), GPIO_Mode_AF_PP);
GPIO_Initialize(GpioType(RMII_MDC), GpioIndex(RMII_MDC), GPIO_Mode_AF_PP);
GPIO_Initialize(GpioType(RMII_TX_EN), GpioIndex(RMII_TX_EN), GPIO_Mode_AF_PP);
GPIO_Initialize(GpioType(RMII_TXD0), GpioIndex(RMII_TXD0), GPIO_Mode_AF_PP);
GPIO_Initialize(GpioType(RMII_TXD1), GpioIndex(RMII_TXD1), GPIO_Mode_AF_PP)