IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> ENC28J60 简介 -> 正文阅读

[嵌入式]ENC28J60 简介

单片机以太网方案

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

  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 òy???é?áê? 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;	// ??3y×?μíá???
	HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
	HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);		// à-?? CS òy???é?áê? 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 ±íê????D bank2
	HAL_SPI_Transmit(&hspi1, &tx_data, 1, 10);
	HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);		// à-?? CS òy???é?áê? 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。

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-18 11:20:34  更:2021-11-18 11:21:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:48:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码