单片机 STM32 HAL 网络模块 ENC28J60

article/2025/11/5 16:37:50

文章目录

  • 一、 简介
  • 二、特性
  • 三、示例代码

一、 简介

ENC28J60 是带有行业标准串行外设接口(Serial Peripheral Interface,SPI)的独立以太网控制器。它可作为任何配备有 SPI 的控制器的以太网接口。ENC28J60 符合IEEE 802.3的全部规范,采用了一系列包过滤机制以对传入数据包进行限制。它还提供了一个内部DMA模块,以实现快速数据吞吐和硬件支持的IP校验和计算。与主控制器的通信通过两个中断引脚和SPI实现,数据传输速率高达10Mb/s。两个专用的引脚用于连接LED,进行网络活动状态指示。图1-1所示为ENC28J60的简化框图。图1-2所示为使用该器件的典型应用电路。要将单片机连接到速率为 10 Mbps的以太网,只需ENC28J60、两个脉冲变压器和一些无源元件即可。

ENC28J60 由七个主要功能模块组成:

  1. SPI 接口——充当主控制器和 ENC28J60 之间通 信通道。
  2. 控制寄存器——用于控制和监视 ENC28J60。
  3. 双端口RAM缓冲器——用于接收和发送数据包。
  4. 判优器——当DMA、发送和接收模块发出请求时 对 RAM 缓冲器的访问进行控制。
  5. 总线接口——对通过 SPI 接收的数据和命令进行 解析。
  6. MAC(Medium Access Control)模块——实现符合 IEEE802.3 标准的MAC逻辑。
  7. PHY(物理层)模块——对双绞线上的模拟数据 进行编码和译码。该器件还包括其他支持模块,诸如振荡器、片内稳压器、电平变换器(提供可以接受 5V 电压的 I/O 引脚)和系统控制逻辑。
    在这里插入图片描述

二、特性

  1. IEEE 802.3 兼容的以太网控制器
  2. 集成MAC和10 BASE-T PHY
  3. 接收器和冲突抑制电路
  4. 支持一个带自动极性检测和校正的 10BASE-T 端口
  5. 支持全双工和半双工模式
  6. 可编程在发生冲突时自动重发可编程填充和 CRC 生成
  7. 可编程自动拒绝错误数据包
  8. 最高速度可达 10 Mb/s 的 SPI 接口

三、示例代码

#include "main.h"
#include "enc28j60.h"
#include "cmsis_os.h"static uint8_t Enc28j60Bank;
static uint32_t NextPacketPtr;#define  ENC28J60_CS(N) HAL_GPIO_WritePin(ENC28J60_CS_GPIO_Port,ENC28J60_CS_Pin,(N)?GPIO_PIN_SET:GPIO_PIN_RESET)
/*********Start*************************底层命令*******************************Start*****************/
/*********************************************
函数名:SPI_ReadWrite
功  能:SPI读写1byte数据
形  参:pTxData--要发送的字节
返回值:收到的字节
备  注:CubeMX启动SPI配置,分频根据系统推荐。
!!!如果移植,需要在此填写SPI读写函数!!!
**********************************************/
extern SPI_HandleTypeDef hspi1;
static uint8_t SPI_ReadWrite(uint8_t pTxData)
{uint8_t pRxData;HAL_SPI_TransmitReceive(&hspi1, &pTxData, &pRxData, sizeof(pTxData), 10);return pRxData;
}
/*********************************************
函数名:ENC28J60_ReadOp
功  能:从器件寄存器读取状态
形  参:op--操作码  address--控制寄存器地址
返回值:寄存器状态值
备  注:命令时序图--29页
**********************************************/
uint8_t ENC28J60_ReadOp(uint8_t op, uint8_t address)
{uint8_t dat = 0;ENC28J60_CS(0);dat = op | (address & ADDR_MASK); //重构操作码和地址,参见手册第28页。SPI_ReadWrite(dat);dat = SPI_ReadWrite(0xFF);//如果需要,进行虚拟读取(对于MAC和MII,请参见手册第29页)if(address & 0x80){dat = SPI_ReadWrite(0xFF);}// release CSENC28J60_CS(1);return dat;
}/*********************************************
函数名:ENC28J60_WriteOp
功  能:向器件寄存器写入1byte
形  参:op--操作码  address--控制寄存器地址  data--数据字节
**********************************************/
void ENC28J60_WriteOp(uint8_t op, uint8_t address, uint8_t data)
{uint8_t dat = 0;ENC28J60_CS(0);dat = op | (address & ADDR_MASK);//重构操作码和地址,参见手册第28页。SPI_ReadWrite(dat);SPI_ReadWrite(data);//写入数据ENC28J60_CS(1);
}/*********************************************
函数名:ENC28J60_ReadBuffer
功  能:读取缓冲存储器的数据
形  参:len--长度   data--存放数据的指针
**********************************************/
void ENC28J60_ReadBuffer(uint32_t len, uint8_t* data)
{ENC28J60_CS(0);SPI_ReadWrite(ENC28J60_READ_BUF_MEM);while(len){len--;*data = (uint8_t)SPI_ReadWrite(0);data++;}*data = '\0';ENC28J60_CS(1);
}
/*********************************************
函数名:ENC28J60_WriteBuffer
功  能:向缓冲存储器写入数据
形  参:len--字节长度   data--数据内容的指针
**********************************************/
void ENC28J60_WriteBuffer(uint32_t len, uint8_t* data)
{ENC28J60_CS(0);SPI_ReadWrite(ENC28J60_WRITE_BUF_MEM);while(len){len--;SPI_ReadWrite(*data);data++;}ENC28J60_CS(1);
}
/*********************************************
函数名:ENC28J60_SetBank
功  能:设置块区
备  注:块区编号在寄存器地址的bit6 bit5
**********************************************/
void ENC28J60_SetBank(uint8_t address)
{/*计算本次寄存器地址在存取区域的位置*/if((address & BANK_MASK) != Enc28j60Bank){/*清除ECON1的BSEL1 BSEL0 详见数据手册15页*/ENC28J60_WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0));/*请注意寄存器地址的宏定义,bit6 bit5为寄存器存储区域位置*/ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5);/*重新确定当前寄存器存储区域*/Enc28j60Bank = (address & BANK_MASK);}
}
/*********END*************************底层命令*******************************END*****************//*********Start*************************中层命令*******************************Start*****************/
/*********************************************
函数名:ENC28J60_Read
功  能:向指定块区的寄存器地址读取状态值
形  参:address--寄存器地址
**********************************************/
uint8_t ENC28J60_Read(uint8_t address)
{// 设定寄存器地址区域ENC28J60_SetBank(address);// 读取寄存器值--发送读寄存器命令和地址return ENC28J60_ReadOp(ENC28J60_READ_CTRL_REG, address);
}/*********************************************
函数名:ENC28J60_Write
功  能:向指定块区的寄存器地址写入数据
形  参:address--寄存器地址
返回值:
备  注:
**********************************************/
void ENC28J60_Write(uint8_t address, uint8_t data)
{// 设定寄存器地址区域ENC28J60_SetBank(address);// 写寄存器值--发送写寄存器命令和地址ENC28J60_WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
}
/*********END*************************中层命令*******************************END*****************//*********************************************
函数名:ENC28J60_PhyWrite
功  能:向PHY寄存器地址写入2byte
形  参:address--寄存器地址  data--数据字节
备  注:详见手册21页
**********************************************/
void ENC28J60_PhyWrite(uint8_t address, uint16_t data)
{uint16_t retry = 0;//向MIREGADR写入地址ENC28J60_Write(MIREGADR, address);//写入低8位数据ENC28J60_Write(MIWRL, data);//写入高8位数据ENC28J60_Write(MIWRH, data >> 8);//等待PHY寄存器写入完成while(ENC28J60_Read(MISTAT) & MISTAT_BUSY && retry < 0XFFF){retry++;}
}/*********************************************
函数名:ENC28J60_PhyWrite
功  能:从PHY寄存器地址读取1byte
形  参:address--寄存器地址  data--数据字节
备  注:详见手册21页
**********************************************/
uint16_t ENC28J60_PhyRead(uint8_t address)
{uint16_t retry = 0;uint16_t data;//向MIREGADR写入地址ENC28J60_Write(MIREGADR, address);ENC28J60_Write(MICMD, MICMD_MIIRD);//MII 读使能位//等待PHY寄存器操作完毕while((ENC28J60_Read(MISTAT) & MISTAT_BUSY) && retry < 0XFFF){retry++;}ENC28J60_Write(MICMD, 0x00);//复位data = ENC28J60_Read(MIRDH) << 8;data |= ENC28J60_Read(MIRDL);return data;
}/*********************************************
函数名:ENC28J60_clkout
功  能:将enc28j60第三引脚的时钟输出改为:
备  注:(本例程该引脚NC,没用到) enc28j60clkout(2);//from 6.25MHz to 12.5MHz
**********************************************/
void ENC28J60_clkout(uint8_t clk)
{//setup clkout: 2 is 12.5MHz:ENC28J60_Write(ECOCON, clk & 0x7);
}/*********************************************
函数名:ENC28J60_getrev
功  能:读取器件版本号
形  参:
返回值:版本号
备  注:在EREVID内也存储了版本信息。EREVID 是一个只读控制寄存器。其中包含一个5位标识符,用来标识器件特定硅片的版本号
**********************************************/
uint8_t ENC28J60_getrev(void)
{return ENC28J60_Read(EREVID);
}/*********************************************
函数名:ENC28J60_Init
功  能:初始化
**********************************************/
int ENC28J60_Init(uint8_t* macaddr)
{uint16_t retry = 0;ENC28J60_WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); //软件复位while(!(ENC28J60_Read(ESTAT)&ESTAT_CLKRDY) && retry < 500) //等待时钟稳定{retry++;osDelay(1);};if(retry >= 500)return 1; //ENC28J60初始化失败// 设置接收缓冲区起始地址NextPacketPtr = RXSTART_INIT; //数据包起始位赋值// 设置接收缓冲区 起始指针ENC28J60_Write(ERXSTL, RXSTART_INIT & 0xFF);ENC28J60_Write(ERXSTH, RXSTART_INIT >> 8);// 设置接收缓冲区 读指针ENC28J60_Write(ERXRDPTL, RXSTART_INIT & 0xFF);ENC28J60_Write(ERXRDPTH, RXSTART_INIT >> 8);// 设置接收缓冲区 结束指针ENC28J60_Write(ERXNDL, RXSTOP_INIT & 0xFF);ENC28J60_Write(ERXNDH, RXSTOP_INIT >> 8);/* 设置发送缓冲区 起始指针 */ENC28J60_Write(ETXSTL, TXSTART_INIT & 0xFF);ENC28J60_Write(ETXSTH, TXSTART_INIT >> 8);/* 设置发送缓冲区 结束指针 */ENC28J60_Write(ETXNDL, TXSTOP_INIT & 0xFF);ENC28J60_Write(ETXNDH, TXSTOP_INIT >> 8);// do bank 1 stuff, packet filter:// For broadcast packets we allow only ARP packtets// All other packets should be unicast only for our mac (MAADR)//// The pattern to match on is therefore// Type     ETH.DST// ARP      BROADCAST// 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9// in binary these poitions are:11 0000 0011 1111// This is hex 303F->EPMM0=0x3f,EPMM1=0x30/* 使能单播过滤 使能CRC校验 使能 格式匹配自动过滤*/ENC28J60_Write(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);ENC28J60_Write(EPMM0, 0x3f);ENC28J60_Write(EPMM1, 0x30);ENC28J60_Write(EPMCSL, 0xf9);ENC28J60_Write(EPMCSH, 0xf7);/* 使能MAC接收 允许MAC发送暂停控制帧 当接收到暂停控制帧时停止发送*/ENC28J60_Write(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);// 退出复位状态ENC28J60_Write(MACON2, 0x00);/* 用0填充所有短帧至60字节长 并追加一个CRC 发送CRC使能 帧长度校验使能 MAC全双工使能*//* 提示 由于ENC28J60不支持802.3的自动协商机制, 所以对端的网络卡需要强制设置为全双工 */ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, \MACON3_PADCFG0 | \MACON3_TXCRCEN | \MACON3_FRMLNEN | \MACON3_FULDPX);// 设置帧间间隙 (non-back-to-back)ENC28J60_Write(MAIPGL, 0x12);ENC28J60_Write(MAIPGH, 0x0C);// 设置帧间间隙 (back-to-back)ENC28J60_Write(MABBIPG, 0x15);// 设置控制器将接受的最大数据包大小// 不要发送超过max_framelen的数据包:ENC28J60_Write(MAMXFLL, MAX_FRAMELEN & 0xFF);ENC28J60_Write(MAMXFLH, MAX_FRAMELEN >> 8);// 写入MAC地址// NOTE: ENC28J60中的MAC地址是向后字节ENC28J60_Write(MAADR5, macaddr[0]);ENC28J60_Write(MAADR4, macaddr[1]);ENC28J60_Write(MAADR3, macaddr[2]);ENC28J60_Write(MAADR2, macaddr[3]);ENC28J60_Write(MAADR1, macaddr[4]);ENC28J60_Write(MAADR0, macaddr[5]);//配置PHY为全双工  LEDB为拉电流ENC28J60_PhyWrite(PHCON1, PHCON1_PDPXMD);// 半双工回环禁止ENC28J60_PhyWrite(PHCON2, PHCON2_HDLDIS);// 切换到 bank 0ENC28J60_SetBank(ECON1);// 使能中断 全局中断 接收中断 接收错误中断ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE);// 使能数据包接收位ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);if(ENC28J60_Read(MAADR5) == macaddr[0])return 0; //初始化成功elsereturn 1;}/*********Start********************************以太网层*******************************Start*****************/
/*********************************************
函数名:ENC28J60_PacketSend
功  能:发送一次数据包
形  参:len--字节长度   packet--数据包指针
返回值:
备  注:参见手册42页
**********************************************/
void ENC28J60_PacketSend(uint32_t len, uint8_t* packet)
{// 设置发送缓冲区起始地址ENC28J60_Write(EWRPTL, TXSTART_INIT & 0xFF);ENC28J60_Write(EWRPTH, TXSTART_INIT >> 8);// 设置发送缓冲区结束地址 该值对应发送数据包长度ENC28J60_Write(ETXNDL, (TXSTART_INIT + len) & 0xFF);ENC28J60_Write(ETXNDH, (TXSTART_INIT + len) >> 8);// 发送之前发送控制包格式字 (0x00 表示使用Macon3设置)ENC28J60_WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);// 将数据包发送到ENC28J60传输缓冲区ENC28J60_WriteBuffer(len, packet);// 将传输缓冲区的内容发送到网络层ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);// 重置传输逻辑问题. See Rev. B4 Silicon Errata point 12.if( (ENC28J60_Read(EIR) & EIR_TXERIF) ){ENC28J60_WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);}
}// Gets a packet from the network receive buffer, if one is available.
// The packet will by headed by an ethernet header.
/*********************************************
函数名:ENC28J60_PacketReceive
功  能:读取一次数据包
形  参:maxlen--检索到的数据包的最大可接受长度  packet--存储数据包数据的指针。
返回值:如果检索到数据包,则以字节为单位的数据包长度,否则为零。
备  注:接收数据包结构示例 器件手册45页
**********************************************/
uint32_t ENC28J60_PacketReceive(uint32_t maxlen, uint8_t* packet)
{uint32_t rxstat;uint32_t len;// 检查是否已接收和缓冲数据包//if( !(ENC28J60_Read(EIR) & EIR_PKTIF) ){// 以上不起作用. See Rev. B4 Silicon Errata point 6.if( ENC28J60_Read(EPKTCNT) == 0 ) //收到的以太网数据包长度{return(0);}// 将读取指针设置为接收数据包的起始位置      缓冲器读指针ENC28J60_Write(ERDPTL, (NextPacketPtr));ENC28J60_Write(ERDPTH, (NextPacketPtr) >> 8);// 读取下一个数据包指针NextPacketPtr  = ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0);NextPacketPtr |= ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;/************[接收状态向量-->0-15bit]****************/// 读取数据包长度 (see datasheet page 46)len  = ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0);len |= ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;len -= 4; //删除CRC部分/************[接收状态向量-->16-31bit]****************/// 读取接收状态 (see datasheet page 45)rxstat  = ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0);rxstat |= ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;// 限制检索长度if (len > maxlen - 1){len = maxlen - 1;}// 检查CRC是否错误 (see datasheet page 46, table 7-3):// The ERXFCON.CRCEN is set by default. 通常我们不需要检查这个if ((rxstat & 0x80) == 0) //表示数据包具有有效的 CRC,无符号错误。{len = 0;}else //{ENC28J60_ReadBuffer(len, packet);// 从接收缓冲区复制数据包}// 将RX读取指针移动到下一个接收数据包的开始处// 这会释放我们刚刚读出的内存ENC28J60_Write(ERXRDPTL, (NextPacketPtr));ENC28J60_Write(ERXRDPTH, (NextPacketPtr) >> 8);// 减少数据包计数器表明我们已完成此数据包的处理ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);return(len);
}
/*********END*************************以太网层*******************************END*****************/
#ifndef __ENC28J60_H
#define __ENC28J60_H#include "stm32f1xx_hal.h"// ENC28J60控制寄存器
// 控制寄存器的地址定义是一个组合地址,
// 存器地址、块区编号、[Ethernet/MAC/PHY] 分别在指定bit中,如下
// - 寄存器地址         (bits 0-4)
// - 块区编号           (bits 5-6)
// - MAC/PHY indicator  (bit 7)#define ADDR_MASK        0x1F //寄存器地址掩码
#define BANK_MASK        0x60 //存储区域掩码
#define SPRD_MASK        0x80 //MAC和MII寄存器掩码/*************笔记****************
1、所有块区公用的寄存器地址
2、关键寄存器
***********************************/
#define EIE              0x1B
#define EIR              0x1C
#define ESTAT            0x1D
#define ECON2            0x1E
#define ECON1            0x1F
// Bank 0 registers
#define ERDPTL           (0x00|0x00)
#define ERDPTH           (0x01|0x00)
#define EWRPTL           (0x02|0x00)
#define EWRPTH           (0x03|0x00)
#define ETXSTL           (0x04|0x00)
#define ETXSTH           (0x05|0x00)
#define ETXNDL           (0x06|0x00)
#define ETXNDH           (0x07|0x00)
#define ERXSTL           (0x08|0x00)
#define ERXSTH           (0x09|0x00)
#define ERXNDL           (0x0A|0x00)
#define ERXNDH           (0x0B|0x00)
//ERXWRPTH:ERXWRPTL 寄存器定义硬件向FIFO 中
//的哪个位置写入其接收到的字节。 指针是只读的,在成
//功接收到一个数据包后,硬件会自动更新指针。 指针可
//用于判断FIFO 内剩余空间的大小。
#define ERXRDPTL         (0x0C|0x00)
#define ERXRDPTH         (0x0D|0x00)
#define ERXWRPTL         (0x0E|0x00)
#define ERXWRPTH         (0x0F|0x00)
#define EDMASTL          (0x10|0x00)
#define EDMASTH          (0x11|0x00)
#define EDMANDL          (0x12|0x00)
#define EDMANDH          (0x13|0x00)
#define EDMADSTL         (0x14|0x00)
#define EDMADSTH         (0x15|0x00)
#define EDMACSL          (0x16|0x00)
#define EDMACSH          (0x17|0x00)
// Bank 1 registers
#define EHT0             (0x00|0x20)
#define EHT1             (0x01|0x20)
#define EHT2             (0x02|0x20)
#define EHT3             (0x03|0x20)
#define EHT4             (0x04|0x20)
#define EHT5             (0x05|0x20)
#define EHT6             (0x06|0x20)
#define EHT7             (0x07|0x20)
#define EPMM0            (0x08|0x20)
#define EPMM1            (0x09|0x20)
#define EPMM2            (0x0A|0x20)
#define EPMM3            (0x0B|0x20)
#define EPMM4            (0x0C|0x20)
#define EPMM5            (0x0D|0x20)
#define EPMM6            (0x0E|0x20)
#define EPMM7            (0x0F|0x20)
#define EPMCSL           (0x10|0x20)
#define EPMCSH           (0x11|0x20)
#define EPMOL            (0x14|0x20)
#define EPMOH            (0x15|0x20)
#define EWOLIE           (0x16|0x20)
#define EWOLIR           (0x17|0x20)
#define ERXFCON          (0x18|0x20)
#define EPKTCNT          (0x19|0x20)
// Bank 2 registers
#define MACON1           (0x00|0x40|0x80)
#define MACON2           (0x01|0x40|0x80)
#define MACON3           (0x02|0x40|0x80)
#define MACON4           (0x03|0x40|0x80)
#define MABBIPG          (0x04|0x40|0x80)
#define MAIPGL           (0x06|0x40|0x80)
#define MAIPGH           (0x07|0x40|0x80)
#define MACLCON1         (0x08|0x40|0x80)
#define MACLCON2         (0x09|0x40|0x80)
#define MAMXFLL          (0x0A|0x40|0x80)
#define MAMXFLH          (0x0B|0x40|0x80)
#define MAPHSUP          (0x0D|0x40|0x80)
#define MICON            (0x11|0x40|0x80)
#define MICMD            (0x12|0x40|0x80)
#define MIREGADR         (0x14|0x40|0x80)
#define MIWRL            (0x16|0x40|0x80)
#define MIWRH            (0x17|0x40|0x80)
#define MIRDL            (0x18|0x40|0x80)
#define MIRDH            (0x19|0x40|0x80)
// Bank 3 registers
#define MAADR1           (0x00|0x60|0x80)
#define MAADR0           (0x01|0x60|0x80)
#define MAADR3           (0x02|0x60|0x80)
#define MAADR2           (0x03|0x60|0x80)
#define MAADR5           (0x04|0x60|0x80)
#define MAADR4           (0x05|0x60|0x80)
#define EBSTSD           (0x06|0x60)
#define EBSTCON          (0x07|0x60)
#define EBSTCSL          (0x08|0x60)
#define EBSTCSH          (0x09|0x60)
#define MISTAT           (0x0A|0x60|0x80)
#define EREVID           (0x12|0x60)
#define ECOCON           (0x15|0x60)
#define EFLOCON          (0x17|0x60)
#define EPAUSL           (0x18|0x60)
#define EPAUSH           (0x19|0x60)
// PHY registers
#define PHCON1           0x00
#define PHSTAT1          0x01
#define PHHID1           0x02
#define PHHID2           0x03
#define PHCON2           0x10
#define PHSTAT2          0x11
#define PHIE             0x12
#define PHIR             0x13
#define PHLCON           0x14// ENC28J60 ERXFCON Register Bit Definitions
#define ERXFCON_UCEN     0x80
#define ERXFCON_ANDOR    0x40
#define ERXFCON_CRCEN    0x20
#define ERXFCON_PMEN     0x10
#define ERXFCON_MPEN     0x08
#define ERXFCON_HTEN     0x04
#define ERXFCON_MCEN     0x02
#define ERXFCON_BCEN     0x01
// ENC28J60 EIE Register Bit Definitions
#define EIE_INTIE        0x80
#define EIE_PKTIE        0x40
#define EIE_DMAIE        0x20
#define EIE_LINKIE       0x10
#define EIE_TXIE         0x08
#define EIE_WOLIE        0x04
#define EIE_TXERIE       0x02
#define EIE_RXERIE       0x01
// ENC28J60 EIR Register Bit Definitions
#define EIR_PKTIF        0x40
#define EIR_DMAIF        0x20
#define EIR_LINKIF       0x10
#define EIR_TXIF         0x08
#define EIR_WOLIF        0x04
#define EIR_TXERIF       0x02
#define EIR_RXERIF       0x01
// ENC28J60 ESTAT Register Bit Definitions
#define ESTAT_INT        0x80
#define ESTAT_LATECOL    0x10
#define ESTAT_RXBUSY     0x04
#define ESTAT_TXABRT     0x02
#define ESTAT_CLKRDY     0x01
// ENC28J60 ECON2 Register Bit Definitions
#define ECON2_AUTOINC    0x80
#define ECON2_PKTDEC     0x40
#define ECON2_PWRSV      0x20
#define ECON2_VRPS       0x08
// ENC28J60 ECON1 Register Bit Definitions
#define ECON1_TXRST      0x80
#define ECON1_RXRST      0x40
#define ECON1_DMAST      0x20
#define ECON1_CSUMEN     0x10
#define ECON1_TXRTS      0x08
#define ECON1_RXEN       0x04
#define ECON1_BSEL1      0x02
#define ECON1_BSEL0      0x01
// ENC28J60 MACON1 Register Bit Definitions
#define MACON1_LOOPBK    0x10
#define MACON1_TXPAUS    0x08
#define MACON1_RXPAUS    0x04
#define MACON1_PASSALL   0x02
#define MACON1_MARXEN    0x01
// ENC28J60 MACON2 Register Bit Definitions
#define MACON2_MARST     0x80
#define MACON2_RNDRST    0x40
#define MACON2_MARXRST   0x08
#define MACON2_RFUNRST   0x04
#define MACON2_MATXRST   0x02
#define MACON2_TFUNRST   0x01
// ENC28J60 MACON3 Register Bit Definitions
#define MACON3_PADCFG2   0x80
#define MACON3_PADCFG1   0x40
#define MACON3_PADCFG0   0x20
#define MACON3_TXCRCEN   0x10
#define MACON3_PHDRLEN   0x08
#define MACON3_HFRMLEN   0x04
#define MACON3_FRMLNEN   0x02
#define MACON3_FULDPX    0x01
// ENC28J60 MICMD Register Bit Definitions
#define MICMD_MIISCAN    0x02
#define MICMD_MIIRD      0x01
// ENC28J60 MISTAT Register Bit Definitions
#define MISTAT_NVALID    0x04
#define MISTAT_SCAN      0x02
#define MISTAT_BUSY      0x01
// ENC28J60 PHY PHCON1 Register Bit Definitions
#define PHCON1_PRST      0x8000
#define PHCON1_PLOOPBK   0x4000
#define PHCON1_PPWRSV    0x0800
#define PHCON1_PDPXMD    0x0100
// ENC28J60 PHY PHSTAT1 Register Bit Definitions
#define PHSTAT1_PFDPX    0x1000
#define PHSTAT1_PHDPX    0x0800
#define PHSTAT1_LLSTAT   0x0004
#define PHSTAT1_JBSTAT   0x0002
// ENC28J60 PHY PHCON2 Register Bit Definitions
#define PHCON2_FRCLINK   0x4000
#define PHCON2_TXDIS     0x2000
#define PHCON2_JABBER    0x0400
#define PHCON2_HDLDIS    0x0100// ENC28J60 Packet Control Byte Bit Definitions
#define PKTCTRL_PHUGEEN  0x08
#define PKTCTRL_PPADEN   0x04
#define PKTCTRL_PCRCEN   0x02
#define PKTCTRL_POVERRIDE 0x01// SPI操作代码--ENC28J60_中文手册.pdf--28页
#define ENC28J60_READ_CTRL_REG       0x00 //读控制寄存器 (RCR)
#define ENC28J60_READ_BUF_MEM        0x3A //读缓冲器     (RBM)
#define ENC28J60_WRITE_CTRL_REG      0x40 //写控制寄存器 (WCR)
#define ENC28J60_WRITE_BUF_MEM       0x7A //写缓冲器     (WBM)
#define ENC28J60_BIT_FIELD_SET       0x80 //位域置 1     (BFS)
#define ENC28J60_BIT_FIELD_CLR       0xA0 //位域清零     (BFC)
#define ENC28J60_SOFT_RESET          0xFF //系统命令(软件复位)(SC)// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
// buffer boundaries applied to internal 8K ram
// the entire available packet buffer space is allocated
//
// 接收缓冲区起始地址/
#define RXSTART_INIT     0x0
// 接收缓冲区停止地址
#define RXSTOP_INIT      (0x1FFF-0x0600-1)
// 发送缓冲区起始地址 发送缓冲区大小约1500字节
#define TXSTART_INIT     (0x1FFF-0x0600)
// 发送缓冲区停止地址
#define TXSTOP_INIT      0x1FFF
//
// max frame length which the conroller will accept:
#define        MAX_FRAMELEN        1500        // (note: maximum ethernet frame length would be 1518)
//#define MAX_FRAMELEN     600uint8_t ENC28J60_ReadOp(uint8_t op, uint8_t address);
void    ENC28J60_WriteOp(uint8_t op, uint8_t address, uint8_t data);
void    ENC28J60_ReadBuffer(uint32_t len, uint8_t* data);
void    ENC28J60_WriteBuffer(uint32_t len, uint8_t* data);
void    ENC28J60_SetBank(uint8_t address);
uint8_t ENC28J60_Read(uint8_t address);
void    ENC28J60_Write(uint8_t address, uint8_t data);
void    ENC28J60_PhyWrite(uint8_t address, uint16_t data);
uint16_t ENC28J60_PhyRead(uint8_t address);
void    ENC28J60_clkout(uint8_t clk);
int    ENC28J60_Init(uint8_t* macaddr);
uint8_t ENC28J60_getrev(void);
void    ENC28J60_PacketSend(uint32_t len, uint8_t* packet);
uint32_t ENC28J60_PacketReceive(uint32_t maxlen, uint8_t* packet);#endif /* __ENC28J60_H */

四、笔记

  1. ENC28J60_中文手册.pdf
    ENC28J60中文手册.pdf
  2. 控制寄存器的地址定义是一个组合地址:
    0-4bit 寄存器地址
    5-6bit 块区编号
    7bit MAC/PHY indicator

http://chatgpt.dhexx.cn/article/8gow6oQ9.shtml

相关文章

ENC28J60 简介

单片机以太网方案 单片机想要使用以太网的话&#xff0c;通常有以下几种方案&#xff1a; 如果 MCU 内部集成 MAC 控制器&#xff0c;则只需外接一个 PHY 芯片就可以了如果 MCU 内部没有 MAC 控制器&#xff0c;需要外接 MAC 芯片和 PHY 芯片&#xff0c;这两颗芯片可以分立也…

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…