2025年4月8日 星期二 乙巳(蛇)年 正月初九 设为首页 加入收藏
rss
您当前的位置:首页 > 电子 > 电子器件

ENC28J60 简介

时间:11-20来源:作者:点击数:51
CDSY,CDSY.XYZ

单片机以太网方案

单片机想要使用以太网的话,通常有以下几种方案:

  1. 如果 MCU 内部集成 MAC 控制器,则只需外接一个 PHY 芯片就可以了
  2. 如果 MCU 内部没有 MAC 控制器,需要外接 MAC 芯片和 PHY 芯片,这两颗芯片可以分立也可以集成在一颗芯片中

以上两种方案,MAC + PHY 完成了 TCP/IP 五层模型的最低两层,即物理层和数据链路层。上面几层,如网络层、传输层、应用层则需要在 MCU 中实现。当然,普通程序员要想实现 IP 层、TCP/UDP 层还是有一定难度的。不过不用担心,我们可以使用成熟的开源 TCP/IP 协议栈,如 uIP、LwIP。它们都是轻量级的 TCP/IP 协议栈,适用于资源受限的单片机。

  1. 使用硬件 TCP/IP 协议栈,MCU 只需要实现应用层代码就可以了

例如,使用 W5500 芯片,传输层及其以下全部由外部这颗芯片完成,MCU 只需要配置 W5500,从 W5500 收发数据,完成应用层逻辑就可以了。还有一种方案是 MCU 外接一个串口转以太网模块,原理和使用 W5500 方案类似。

ENC28J60

ENC28J60 属于上面介绍的方案 2,ENC28J60 单颗芯片集成了 MAC 和 PHY,提供 SPI 接口用来和 MCU 通信。

寄存器 —— 硬件的灵活性体现

在方案 2 中,网络层、传输层、应用层 是以软件的形式在 CPU 中实现的,而物理层、数据链路层则是以硬件的形式在 ENC28J60 中实现的,虽然 ENC28J60 是一个硬件,我们无法对其进行编程修改功能,但其仍然留有一定的灵活性,那就是可以配置的寄存器。我们可以设置寄存器以达到控制最低两层的目的,也可以读寄存器以达到监控最低两层的目的。

比如我们可以设置 ECON1 寄存器,来控制接收使能、发送请求、DMA、存储区选择等。

还可以设置 PHCON1 寄存器,来控制 PHY 模块复位等功能。

缓冲器 —— 硬件的价值体现

说到底 ENC28J60 的功能是从 IP 层拿数据并发送出去,或者将收到的数据送给 IP 层。这两个方向的操作都需要用到缓冲器,用来暂存数据。

ENC28J60 读写特性

ENC28J60 中有三种类型的存储器:

• 控制寄存器

• 以太网缓冲器

• PHY 寄存器

其中 MCU 可以通过 SPI 接口,使用指令来直接读写 控制寄存器 和 以太网缓冲器。但是不可以通过 SPI 接口直接访问 PHY 寄存器,只可以通过 MAC 中的 MII 访问这些寄存器。

可以理解为 SPI 是和 MAC 相连的,可以直接访问 MAC 的寄存器,但是 PHY 只与 MAC 通过 RMII、MIIM 接口相连,所以想要读取 PHY 寄存器的值,必须要通过 MAC,进一步讲是通过 MAC 的 MIIM 接口,或者说是通过 MAC 的 MII 寄存器。

在这里插入图片描述

ENC28J60 中所有的存取器都是以静态 RAM 的方式实现的。

控制寄存器存储空间分为四个存储区,可用 ECON1 寄存器中的存储区选择位 BSEL1:BSEL0 进行选择。 每个存储区都是 32 字节长,可以用 5 位地址值进行寻址。

所有存储区的最后五个单元 (1Bh 到 1Fh)都指向同一组寄存器:EIE、EIR、ESTAT、ECON2 和 ECON1。 它们是控制和监视器件工作的关键寄存器,由于被映射到同一存储空间,因此可以在不切换存储区的情况下很方便地访问它们。

下图是所有的控制寄存器:

在这里插入图片描述

能够从任意 Bank 访问 ECON1 是有必要的,因为 ECON1 中存有选择 Bank 的两个 bit,倘若 ECON1 只能在 Bank 0 中访问,那么,一旦将访问权切换到 Bank 2,而 Bank 2 又无法访问 ECON1 来选择 Bank,那不就悲催了嘛,只能停留在 Bank 2 了。。😂

读取 PHY 寄存器实例

下面粗略地写一段代码来读取 PHY 的 PHSTAT1 寄存器,此寄存器的 bit2 表示链路状态

在这里插入图片描述

我们就按照步骤一步步写

在这里插入图片描述

代码

  • int main(void)
  • {
  • /* USER CODE BEGIN 1 */
  • uint8_t tx_data = 0x00;
  • uint8_t rx_data = 0x00;
  • uint16_t pyh_data;
  • /* USER CODE END 1 */
  • /* MCU Configuration----------------------------------------------------------*/
  • /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  • HAL_Init();
  • /* Configure the system clock */
  • SystemClock_Config();
  • /* Initialize all configured peripherals */
  • MX_GPIO_Init();
  • MX_SPI1_Init();
  • MX_USART1_UART_Init();
  • /* USER CODE BEGIN 2 */
  • /* 1111111111111111111. */
  • /* select bank 2 begin */
  • tx_data = 0xA0 | 0x1F; // BFC | ECONT1 // BF
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x03; // 清除最低两位 // 03
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); // 拉高 CS 引脚可结束 BFC 命令
  • tx_data = 0x80 | 0x1F; // BFS | ECONT1 // 9F
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x02; // 10h 表示选中 bank2 // 02
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); // 拉高 CS 引脚可结束 BFS 命令
  • /* select bank 2 end */
  • /* MIREGADR(14h) <-- PHSTAT1(01h) begin */
  • tx_data = 0x40 | 0x14; // WCR | MIREGADR(14h) // 地址 // 54
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x01; // PHSTAT1(01h) // 值 // 01
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
  • /* MIREGADR(14h) <-- PHSTAT1(01h) end */
  • /* 2222222222222222222 */
  • /* MICMD(12h) <-- MIIRD(01h) begin */ // 92
  • tx_data = 0x80 | 0x12; // BFS | MICMD(12h) // 地址
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x01; // MIIRD(01h) // 值 // 01
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
  • /* MICMD(12h) <-- MIIRD(01h) end */
  • /* select bank 3 begin */
  • tx_data = 0x80 | 0x1F; // BFS | ECONT1 // 9F
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x03; // 11h 表示选中 bank2 // 03
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); // À­¸ß CS Òý½Å¿É½áÊø BFS ÃüÁî
  • /* select bank 3 end */
  • /* MISTAT(0Ah) <-- BUSY(01h) begin */
  • tx_data = 0x80 | 0x0A; // BFS | MICMD(0Ah) // 地址 // 8A
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x01; // BUSY(01h) // 值 // 01
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
  • /* MISTAT(0Ah) <-- BUSY(01h) end */
  • /* 333333333333333333. */
  • /* 等待 10.24us */
  • // HAL_Delay(1);
  • /* MISTAT(0Ah) */
  • // tx_data = 0x00 | 0x0A; // RCR | MISTAT(0Ah) // µØÖ·
  • // HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • // HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • //
  • // HAL_SPI_Transmit(&hspi1, &rx_data, 1, 10); // ¶ÁÖµ
  • // HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
  • ///* MIREGADR(14h) <-- PHSTAT1(01h) end */
  • // printf("rx_data = 0x%x\r\n", rx_data);
  • /* 4 */
  • /* select bank 2 begin */
  • tx_data = 0xA0 | 0x1F; // BFC | ECONT1
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x03; // Çå³ý×îµÍÁ½Î»
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); // À­¸ß CS Òý½Å¿É½áÊø BFC ÃüÁî
  • tx_data = 0x80 | 0x1F; // BFS | ECONT1
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x02; // 10h ±íʾѡÖÐ bank2
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); // À­¸ß CS Òý½Å¿É½áÊø BFS ÃüÁî
  • /* select bank 2 end */
  • /* MICMD(12h) <-- MIIRD(01h) begin */
  • tx_data = 0xA0 | 0x12; // BFC | MICMD(12h) // µØÖ·
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • tx_data = 0x01; // MIIRD(01h) // Öµ
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
  • /* MICMD(12h) <-- MIIRD(01h) end */
  • /* 5 */
  • /* read MIRDL(18h) begin */
  • tx_data = 0x00 | 0x18; // RCR | MIRDL(18h) // µØÖ·
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_SPI_Receive(&hspi1, &rx_data, 1, 10); // ¶ÁÖµ
  • // printf("rx_data = 0x%x\r\n", rx_data);
  • HAL_SPI_Receive(&hspi1, &rx_data, 1, 10); // ¶ÁÖµ
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
  • // printf("rx_data = 0x%x\r\n", rx_data);
  • pyh_data = rx_data;
  • /* read MIRDH(19h) begin */
  • tx_data = 0x00 | 0x19; // RCR | MIRDH(19h) // µØÖ·
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
  • HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
  • HAL_SPI_Receive(&hspi1, &rx_data, 1, 10);
  • HAL_SPI_Receive(&hspi1, &rx_data, 1, 10); // ¶ÁÖµ
  • HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
  • /* read MIRDH(19h) end */
  • // printf("rx_data = 0x%x\r\n", rx_data);
  • pyh_data = pyh_data + (rx_data << 8);
  • printf("pyh_data = 0x%x\r\n", pyh_data);
  • /* USER CODE END 2 */
  • /* Infinite loop */
  • /* USER CODE BEGIN WHILE */
  • while (1)
  • {
  • /* USER CODE END WHILE */
  • /* USER CODE BEGIN 3 */
  • // printf("helo\r\n");
  • HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
  • HAL_Delay(1000);
  • // printf("0x%X: 0x%x\n", tx_data, rx_data);
  • // cr_addr++;
  • }
  • /* USER CODE END 3 */
  • }

插拔网线

在这里插入图片描述
在这里插入图片描述

读取到的 PHSTAT1 寄存器值

在这里插入图片描述

插上网线,值为 0x1804,即 bit2 = 1;

拔掉网线,值为 0x1800,即 bit2 = 0。

读到的寄存器状态和网线连接状态一致,成功!

CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
上一篇:电阻色环表_色环电阻识别方法 下一篇:很抱歉没有了
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐