ENC28J60 简介

article/2025/11/5 16:32:18

单片机以太网方案

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

  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	// BFHAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);tx_data = 0x03;	// 清除最低两位					// 03HAL_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	// 9FHAL_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		// 02HAL_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) // 地址	// 54HAL_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) // 值										// 01HAL_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 */			// 92tx_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) // 值			// 01HAL_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	// 9FHAL_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		// 03HAL_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) // 地址	// 8AHAL_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) // 值									// 01HAL_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 | ECONT1HAL_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 | ECONT1HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);tx_data = 0x02;	// 10h ±íʾѡÖÐ bank2HAL_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。

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


http://chatgpt.dhexx.cn/article/5LmXE3od.shtml

相关文章

c语言程序设计 国外教材,标准C程序设计(第7版国外计算机科学经典教材)

导语 内容提要 E.巴拉古路萨米著李周芳译的《标准C程序设计(第7版国外计算机科学经典教材)》专门用于满足渴望成为程序员的学生&#xff0c;最新版按照Bloom分类法所定的学习目标来呈现主题&#xff0c;支持基于学习的成果。本书解释了基本概念和高级内容&#xff0c;且主要关注…

学习C语言的教材

作者&#xff1a; 阮一峰 日期&#xff1a; 2011年9月18日 我的C语言是自学的&#xff0c;这些年看过不少教材。 下面&#xff0c;我对其中一些教材做个点评。 1. How to Think Like a Computer Scientist: C version 这是我读过最易懂的C语言教材。 虽然它只讲解最基本的语法&…

新概念c语言周二强07答案,新概念C语言能力教程(普通高等教育十二五规划教材)...

导语 内容提要 周二强编写的《新概念C语言能力教程(普通高等教育十二五规划教材)》以先进的教学理念为指导&#xff0c;以培养编程能力与学习能力为目标&#xff0c;从全新的角度解析了C语言&#xff0c;高屋建瓴地阐释了C语言学习中的诸多难点&#xff0c;对序列点、指针等概念…

计算机程序c语言教材,全国计算机等级考试二级C语言程序设计教材(2018年版)...

2018年计算机二级教材&#xff1a;C语言程序设计 简介 书名&#xff1a;全国计算机等级考试二级教程——C语言程序设计(2018年版) 作者&#xff1a;教育部考试中心 出版社&#xff1a;高等教育出版社 出版时间&#xff1a;2017年11月 ISBN&#xff1a;9787040488524 定价&#…

树莓派(0)C语言教材学习

学习日记的功能主要是记录学习C语言的知识还有难上手的地方&#xff0c;之后会记录配置树莓派环境还有设计linux环境下C语言的实验题目 目前在K&R的《C语言程序设计》教材学习&#xff0c;前面的内容没有难度&#xff0c;基本上和高级程序设计语言的学习思路一样&#xff0…

国内C语言教材中几种值得商榷的说法

作者&#xff1a;巨同升 “C语言程序设计”这门课程在国内高校普遍开设已有近三十年&#xff0c;课程的建设和研究取得了长足的进步&#xff0c;涌现出了数量众多、各具特色的C语言教材。尽管如此&#xff0c;在许多C语言教材中还或多或少地存在着一些不准确甚至是值得商榷的说…

既然谭浩强的C语言教材不好,那应该选什么书作C语言教材?

易道云学院C语言/C语法学习不在于你看了多少书&#xff0c;而在于你实实在在写了多少有效代码。易道云学院 回到这个问题&#xff0c;其实我个人认为&#xff0c;看什么样的书&#xff0c;也是需要应对不一样的场景易道云学院去有目的地涉猎。我暂时想到了几种情况&#xff0c;…

c语言课本答案解析宋士银,c语言教材

22.40定价&#xff1a;28.00(8折) /2007-02-01 根据教育部高等学校计算机科学与技术教学指导委员会提出的《关于进一步加强高等学校计算机基础教学的意见暨计算机基础课程教学基本要求》的有关要求&#xff0c;编者组织了一批多年工作在教学一线且有丰富教学经验的教师编写了《…

C语言的环境变量配置

一、编辑器选择与安装 这边选用的编辑器是比较常见的devc&#xff0c;当然vscode和vc也都可以用来学习C语言&#xff0c;要软件和C语言环境变量的话可以加QQ群&#xff1a;373270625 第一步全部默认勾选就行无脑下一步 第二步选择一个放软件的文件夹&#xff0c;我这边选择的…

Jmeter环境变量配置

解压后 电脑桌面----》“计算机”图标----》鼠标右键选择“属性”----》点击高级系统设置----》高级---》环境变量页面 1.在系统变量框&#xff0c;点击“新建”&#xff0c;建立一个变量&#xff1a;JMETER_HOME,值为你解压的jmeter安装路径 2.配置classpath变量&#xff0c…

java设置环境变量jre_JRE环境变量配置图解

JRE(Java Runtime Environment,Java运行环境),运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。如果大家需要查看JRE环境变量配置图解过程,看完本文你的问题也就迎刃而解了。 我们这里使用jre-7u67-windows-i586的32位JRE安装包,大小只有20多M,比JDK7小了…

Anaconda环境变量配置

Anaconda Anaconda环境变量配置 学习自用 解决问题 例如在VSCode中使用虚拟环境运行python代码导致的问题 *ImportError: DLL load failed while importing win32gui*新建系统变量&#xff0c;添加Anaconda安装路径 以后想用其他环境直接修改变量值就可以了 新建环境变量 变…

npm环境变量配置

NPM 使用介绍 NPM是随同NodeJS一起安装的包管理工具&#xff0c;能解决NodeJS代码部署上的很多问题&#xff0c;常见的使用场景有以下几种&#xff1a; 允许用户从NPM服务器下载别人编写的第三方包到本地使用。允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。…

windows 10中R的环境变量配置

创建于&#xff1a;20221113 修改于&#xff1a;20221113 文章目录 1、情况介绍2、环境变量配置3、参考资料 1、情况介绍 win10 64bit系统中&#xff0c;已经安装好了R&#xff0c;Rtools &#xff0c;Rstudio&#xff0c;并且已经配置了java开发环境。 上述两个链接讲述的非…

SVN环境变量配置

1、环境变量配置 2、复制地址 3、环境变量配置&#xff1a; 步骤: 右击电脑属性、高级系统设置、高级、环境变量、 系统变量、找到Path、双击进入、新建粘贴到刚刚复制的地址&#xff0c;确定即可。

Mac环境变量配置(Java)

1.打开终端&#xff1a; 2.输入命令&#xff1a;【/usr/libexec/java_home -V】,查看默认的jdk下载地址&#xff08;绿色下划线的就是jdk默认路径&#xff09;&#xff08;注意⚠️&#xff1a;命令行终端是区分大小写的【-v 是不对的&#xff0c;必须是大写 -V】&#xff09; …

adb环境变量配置

关于adb 什么ADB如何配置CMD命令窗口的使用 什么是adb 首先&#xff0c;我们先说说&#xff0c;adb是什么&#xff0c;他的全称叫安卓调试桥&#xff0c;也就是Android debug bridge &#xff0c;它是连接Windows平台和安卓手机之间的软件调试工具&#xff0c;很适合软件开发…

Android环境变量配置

1 先再到本地SDK位置&#xff0c;C:\Users\27322\AppData\Local\Android\Sdk ​ 本地SDK路径&#xff0c;android studio安装默认路径 2 新建环境变量&#xff1a;ANDROID_HOME&#xff0c;值&#xff1a;C:\Users\27322\AppData\Local\Android\Sdk ​ 右键我的电脑&#xff0…

node环境变量配置

首先&#xff0c;node被我安装在D盘 我下一步需求是&#xff0c;将系统默认的全局包下载路径&#xff08;C:\Users\Administrator\AppData\Roaming&#xff09;换到D盘下面&#xff0c;以减少C盘存储压力。 具体实施&#xff1a; 第一&#xff1a;在nodejs文件夹下&#xff0c…

python环境变量配置

python现在的版本&#xff0c;主要是python2和python3两个大版本&#xff0c;这两个版本有很大的不同。 当我们在自己电脑上同时安装了python2.x和python3.x版本的解释器的时候&#xff0c;就需要对环境变量的配置进行一定的修改。 【大概解释一下&#xff0c;我对环境变量的…