SZ18201 以太网收发器 硬件及驱动程序应用设计
define PHY_BCR_100MBPS((uint16_t)0x2000)// 速度选择 (0=10M, 1=100M)#define PHY_BCR_DUPLEX_MODE((uint16_t)0x0100)// 双工模式 (0=半, 1=全)*buff = (uint8_t *)memp_malloc(MEMP_POOL_BUFFER);#define PHY_BSR_LINK_STAT
一、简介:
SZ18201 是一款集成了 IEEE 802.3 标准以太网物理层 (PHY) 功能的芯片。它负责将 MAC 层(通常在 STM32 内部)的数字信号转换为可以在双绞线上传输的模拟信号,反之亦然。
主要特性:
-
协议兼容: 支持 10/100 Mbps 的传输速率。
-
接口: 通过标准的 MII (Media Independent Interface) 或 RMII (Reduced Media Independent Interface) 与微控制器的以太网 MAC 模块连接。RMII 因其引脚数少,在 STM32 项目中更为常用。
-
物理介质: 支持通过双绞线进行传输和接收。
-
低功耗: 适合 STM32L4 系列这类低功耗应用。
-
自动协商: 支持与对端设备(如交换机、路由器)自动协商速率(10M/100M)和双工模式(半双工/全双工)。
二、功能框图:

三、封装及引脚定义:

四、硬件设计:



五、头文件:
#ifndef SZ18201_H
#define SZ18201_H
#include "stm32l4xx_hal.h"
/* SZ18201 PHY 寄存器地址 (遵循 IEEE 802.3) */
#define PHY_REG_BCR 0x00 // 基本控制寄存器
#define PHY_REG_BSR 0x01 // 基本状态寄存器
#define PHY_REG_ID1 0x02 // PHY 标识符 1
#define PHY_REG_ID2 0x03 // PHY 标识符 2
/* 基本控制寄存器位定义 */
#define PHY_BCR_RESET ((uint16_t)0x8000) // 软件复位
#define PHY_BCR_LOOPBACK ((uint16_t)0x4000) // 环回模式
#define PHY_BCR_100MBPS ((uint16_t)0x2000) // 速度选择 (0=10M, 1=100M)
#define PHY_BCR_AUTONEG ((uint16_t)0x1000) // 自动协商使能
#define PHY_BCR_POWERDOWN ((uint16_t)0x0800) // 电源下行
#define PHY_BCR_ISOLATE ((uint16_t)0x0400) // 电气隔离
#define PHY_BCR_RESTART_AUTONEG ((uint16_t)0x0200) // 重新启动自动协商
#define PHY_BCR_DUPLEX_MODE ((uint16_t)0x0100) // 双工模式 (0=半, 1=全)
/* 基本状态寄存器位定义 */
#define PHY_BSR_LINK_STATUS ((uint16_t)0x0004) // 链接状态 (1=已建立)
#define PHY_BSR_AUTONEG_COMP ((uint16_t)0x0020) // 自动协商完成
/* 函数原型 */
uint32_t SZ18201_Init(ETH_HandleTypeDef *heth);
void SZ18201_GetLinkState(ETH_HandleTypeDef *heth);
uint16_t SZ18201_ReadRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg);
HAL_StatusTypeDef SZ18201_WriteRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint16_t Value);
#endif // SZ18201_H
六、源文件:
#include "sz18201.h"
#include "main.h" // 用于可能的延时函数
/**
* @brief 读取 SZ18201 PHY 寄存器
* @param heth: ETH 句柄
* @param PHYReg: PHY 寄存器地址
* @retval 寄存器的值
*/
uint16_t SZ18201_ReadRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg) {
uint32_t value = 0;
HAL_StatusTypeDef status;
status = HAL_ETH_ReadPHYRegister(heth, SZ18201_PHY_ADDRESS, PHYReg, &value);
if (status != HAL_OK) {
Error_Handler(); // 或者进行其他错误处理
return 0;
}
return (uint16_t)value;
}
/**
* @brief 写入 SZ18201 PHY 寄存器
* @param heth: ETH 句柄
* @param PHYReg: PHY 寄存器地址
* @param Value: 要写入的值
* @retval HAL 状态
*/
HAL_StatusTypeDef SZ18201_WriteRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint16_t Value) {
return HAL_ETH_WritePHYRegister(heth, SZ18201_PHY_ADDRESS, PHYReg, Value);
}
/**
* @brief 初始化 SZ18201 PHY
* @param heth: ETH 句柄
* @retval HAL 状态
*/
uint32_t SZ18201_Init(ETH_HandleTypeDef *heth) {
uint16_t regvalue = 0;
/* 1. 软件复位 PHY */
SZ18201_WriteRegister(heth, PHY_REG_BCR, PHY_BCR_RESET);
HAL_Delay(100); // 等待复位完成
/* 2. 检查 PHY ID (可选,用于验证通信是否正常) */
// uint16_t id1 = SZ18201_ReadRegister(heth, PHY_REG_ID1);
// uint16_t id2 = SZ18201_ReadRegister(heth, PHY_REG_ID2);
// if(id1 != expected_id1 || id2 != expected_id2) { ... }
/* 3. 配置 PHY: 使能自动协商 */
regvalue = PHY_BCR_AUTONEG | PHY_BCR_100MBPS | PHY_BCR_DUPLEX_MODE;
SZ18201_WriteRegister(heth, PHY_REG_BCR, regvalue);
/* 4. 重启自动协商 */
regvalue |= PHY_BCR_RESTART_AUTONEG;
SZ18201_WriteRegister(heth, PHY_REG_BCR, regvalue);
/* 5. 等待自动协商完成 */
uint32_t timeout = 0;
while (!(SZ18201_ReadRegister(heth, PHY_REG_BSR) & PHY_BSR_AUTONEG_COMP)) {
HAL_Delay(100);
timeout += 100;
if (timeout > 5000) { // 5秒超时
return HAL_ERROR;
}
}
/* 6. 检查链接状态 */
SZ18201_GetLinkState(heth);
return HAL_OK;
}
/**
* @brief 获取 PHY 的链接状态
* @param heth: ETH 句柄
*/
void SZ18201_GetLinkState(ETH_HandleTypeDef *heth) {
uint16_t phy_bsr = SZ18201_ReadRegister(heth, PHY_REG_BSR);
if (phy_bsr & PHY_BSR_LINK_STATUS) {
printf("Ethernet Link Up.\r\n");
uint16_t bcr = SZ18201_ReadRegister(heth, PHY_REG_BCR);
if (bcr & PHY_BCR_100MBPS) {
printf("Speed: 100Mbps, ");
} else {
printf("Speed: 10Mbps, ");
}
if (bcr & PHY_BCR_DUPLEX_MODE) {
printf("Duplex: Full.\r\n");
} else {
printf("Duplex: Half.\r\n");
}
} else {
printf("Ethernet Link Down.\r\n");
}
}
七、应用:
/* 在私有变量区添加 */
ETH_HandleTypeDef heth;
ETH_TxPacketConfig TxConfig;
/* 在 main() 函数中 */
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ETH_Init(); // CubeMX 生成的 ETH 初始化
MX_LWIP_Init(); // CubeMX 生成的 LwIP 初始化
/* 初始化 SZ18201 PHY */
if (SZ18201_Init(&heth) != HAL_OK) {
Error_Handler();
}
/* 设置 TxConfig */
TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
while (1) {
/* LwIP 需要定期被轮询 */
MX_LWIP_Process();
/* 可以定期检查链接状态 */
// SZ18201_GetLinkState(&heth);
// HAL_Delay(10000);
}
}
/* CubeMX 生成的 ETH 初始化函数 */
void MX_ETH_Init(void) {
heth.Instance = ETH;
heth.Init.MACAddr = (uint8_t *)&MACAddr; // MAC地址需要定义
heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
heth.Init.TxDesc = DMATxDscrTab;
heth.Init.RxDesc = DMARxDscrTab;
heth.Init.RxBuffLen = 1524;
HAL_ETH_Init(&heth);
}
/* 用户必须提供的回调函数:ETH_RX_PMP_IRQHandler */
void HAL_ETH_RxAllocateCallback(uint8_t **buff) {
*buff = (uint8_t *)memp_malloc(MEMP_POOL_BUFFER); // LwIP 内存分配
if(*buff == NULL) {
LWIP_DEBUGF(NETIF_DEBUG, ("HAL_ETH_RxAllocateCallback: No memory\\r\\n"));
}
}
void HAL_ETH_RxLinkCallback(void **pStart, void *pEnd, uint8_t *buff, uint16_t Length) {
struct pbuf_custom *p = (struct pbuf_custom *)buff;
p->next = NULL;
p->payload = (void *)((uint8_t *)p + LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF));
*pStart = p;
}
void HAL_ETH_TxFreeCallback(uint32_t * buff) {
memp_free(MEMP_POOL_BUFFER, (void *)buff);
}
void HAL_ETH_RxFreeCallback(void *buff) {
memp_free(MEMP_POOL_BUFFER, (void *)buff);
}
更多推荐



所有评论(0)