作者共发了6篇帖子。 字体大小:较小 - 100% (默认)▼  内容转换:不转换▼
 
点击 回复
615 5
【驱动程序】ENC28J60网卡芯片驱动程序(不含lwIP协议栈)
一派护法 十九级
1楼 发表于:2017-3-18 22:00
【ENC28J60.h】
#define EIE 0x1b
#define EIR 0x1c
#define ESTAT 0x1d
#define ECON2 0x1e
#define ECON1 0x1f

// Bank 0 registers
#define ERDPTL 0x00
#define ERDPTH 0x01
#define EWRPTL 0x02
#define EWRPTH 0x03
#define ETXSTL 0x04
#define ETXSTH 0x05
#define ETXNDL 0x06
#define ETXNDH 0x07
#define ERXSTL 0x08
#define ERXSTH 0x09
#define ERXNDL 0x0a
#define ERXNDH 0x0b
#define ERXRDPTL 0x0c
#define ERXRDPTH 0x0d
#define ERXWRPTL 0x0e
#define ERXWRPTH 0x0f
#define EDMASTL 0x10
#define EDMASTH 0x11
#define EDMANDL 0x12
#define EDMANDH 0x13
#define EDMADSTL 0x14
#define EDMADSTH 0x15
#define EDMACSL 0x16
#define EDMACSH 0x17

// Bank 1 registers
#define EHT0 0x20
#define EHT1 0x21
#define EHT2 0x22
#define EHT3 0x23
#define EHT4 0x24
#define EHT5 0x25
#define EHT6 0x26
#define EHT7 0x27
#define EPMM0 0x28
#define EPMM1 0x29
#define EPMM2 0x2a
#define EPMM3 0x2b
#define EPMM4 0x2c
#define EPMM5 0x2d
#define EPMM6 0x2e
#define EPMM7 0x2f
#define EPMCSL 0x30
#define EPMCSH 0x31
#define EPMOL 0x34
#define EPMOH 0x35
#define EWOLIE 0x36
#define EWOLIR 0x37
#define ERXFCON 0x38
#define EPKTCNT 0x39

// Bank 2 registers
#define MACON1 0xc0
#define MACON2 0xc1
#define MACON3 0xc2
#define MACON4 0xc3
#define MABBIPG 0xc4
#define MAIPGL 0xc6
#define MAIPGH 0xc7
#define MACLCON1 0xc8
#define MACLCON2 0xc9
#define MAMXFLL 0xca
#define MAMXFLH 0xcb
#define MAPHSUP 0xcd
#define MICON 0xd1
#define MICMD 0xd2
#define MIREGADR 0xd4
#define MIWRL 0xd6
#define MIWRH 0xd7
#define MIRDL 0xd8
#define MIRDH 0xd9

// Bank 3 registers
#define MAADR1 0xe0
#define MAADR0 0xe1
#define MAADR3 0xe2
#define MAADR2 0xe3
#define MAADR5 0xe4
#define MAADR4 0xe5
#define EBSTSD 0x66
#define EBSTCON 0x67
#define EBSTCSL 0x68
#define EBSTCSH 0x69
#define MISTAT 0xea
#define EREVID 0x72
#define ECOCON 0x75
#define EFLOCON 0x77
#define EPAUSL 0x78
#define EPAUSH 0x79

// 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

/* 指令集, 详见数据手册26页 */
#define ENC28J60_READ_CTRL_REG 0x00 // 读控制寄存器
#define ENC28J60_READ_BUF_MEM 0x3a // 读缓冲区
#define ENC28J60_WRITE_CTRL_REG 0x40 // 写控制寄存器
#define ENC28J60_WRITE_BUF_MEM 0x7a // 写缓冲区
#define ENC28J60_BIT_FIELD_SET 0x80 // 位域置位
#define ENC28J60_BIT_FIELD_CLR 0xa0 // 位域清零
#define ENC28J60_SOFT_RESET 0xff // 系统复位

#define RXSTART_INIT 0 // 接收缓冲区起始地址
#define RXSTOP_INIT (0x1fff - 0x0600 - 1) // 接收缓冲区停止地址
#define TXSTART_INIT (0x1fff - 0x0600) // 发送缓冲区起始地址, 大小约1500字节
#define TXSTOP_INIT 0x1fff // 发送缓冲区停止地址
#define MAX_FRAMELEN 1500 // 以太网报文最大长度

void ENC28J60_BeginSend(void);
void ENC28J60_EndReceive(void);
uint16_t ENC28J60_GetPacketLength(void);
uint8_t ENC28J60_GetPacketNum(void);
void ENC28J60_Init(uint8_t *mac_addr);
void ENC28J60_InitSend(uint16_t len);
uint8_t ENC28J60_Read(uint8_t addr);
void ENC28J60_ReadBuf(uint8_t *p, uint16_t len);
uint8_t ENC28J60_ReadOP(uint8_t op, uint8_t addr);
void ENC28J60_SetBank(uint8_t addr);
void ENC28J60_Write(uint8_t addr, uint8_t data);
void ENC28J60_WriteBuf(uint8_t *p, uint16_t len);
void ENC28J60_WriteOP(uint8_t op, uint8_t addr, uint8_t data);
void ENC28J60_WritePhy(uint8_t addr, uint16_t data);
一派护法 十九级
2楼 发表于:2017-3-18 22:01
【ENC28J60.c】
#include <stm32f10x.h>
#include "ENC28J60.h"

static uint8_t enc28j60_bank; // 存储区Bank编号, ENC28J60具有Bank0~3共4个存储区, 需要通过ECON1寄存器选择
static uint16_t enc28j60_next_pkt; // 下一个数据包指针, 详见数据手册P43图7-3

// 开始发送
void ENC28J60_BeginSend(void)
{
    ENC28J60_WriteOP(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
    if (ENC28J60_Read(EIR) & EIR_TXERIF)
    {
        ENC28J60_SetBank(ECON1);
        ENC28J60_WriteOP(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
    }
}

// 结束读取接收缓冲区过程, 移动接收缓冲区指针
void ENC28J60_EndReceive(void)
{
    // 移动接收缓冲区读指针
    ENC28J60_Write(ERXRDPTL, enc28j60_next_pkt);
    ENC28J60_Write(ERXRDPTH, enc28j60_next_pkt >> 8);
   
    // 数据包递减
    ENC28J60_WriteOP(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
}

// 获得数据包长度
uint16_t ENC28J60_GetPacketLength(void)
{
    uint16_t len = 0;
    uint16_t rxstat;
   
    // 设置接收缓冲器读指针
    ENC28J60_Write(ERDPTL, enc28j60_next_pkt);
    ENC28J60_Write(ERDPTH, enc28j60_next_pkt >> 8);
   
    // 读下一个包的指针
    enc28j60_next_pkt = ENC28J60_ReadOP(ENC28J60_READ_BUF_MEM, 0);
    enc28j60_next_pkt |= ENC28J60_ReadOP(ENC28J60_READ_BUF_MEM, 0) << 8;
   
    // 读包的长度
    len = ENC28J60_ReadOP(ENC28J60_READ_BUF_MEM, 0);
    len |= ENC28J60_ReadOP(ENC28J60_READ_BUF_MEM, 0) << 8;
    len -= 4; // 删除CRC计数
   
    // 读取接收状态
    rxstat = ENC28J60_ReadOP(ENC28J60_READ_BUF_MEM, 0);
    rxstat |= ENC28J60_ReadOP(ENC28J60_READ_BUF_MEM, 0) << 8;
    return len;
}

// 获取数据包个数
uint8_t ENC28J60_GetPacketNum(void)
{
    return ENC28J60_Read(EPKTCNT);
}

// 初始化
void ENC28J60_Init(uint8_t *mac_addr)
{
    ENC28J60_WriteOP(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); // ENC28J60软件复位
    while ((ENC28J60_Read(ESTAT) & ESTAT_CLKRDY) == 0);
    enc28j60_next_pkt = 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);
   
    // 使能单播过滤, 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);
   
    ENC28J60_Write(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); // 使能MAC接收, 允许MAC发送暂停控制帧, 当接收到暂停控制帧时停止发送
    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);
    ENC28J60_Write(MAIPGL, 0x12);
    ENC28J60_Write(MAIPGH, 0x0c);
    ENC28J60_Write(MABBIPG, 0x15);
   
    // 最大帧长度
    ENC28J60_Write(MAMXFLL, MAX_FRAMELEN & 0xff);
    ENC28J60_Write(MAMXFLH, MAX_FRAMELEN >> 8);
   
    // 写入MAC地址
    ENC28J60_Write(MAADR5, mac_addr[0]);
    ENC28J60_Write(MAADR4, mac_addr[1]);
    ENC28J60_Write(MAADR3, mac_addr[2]);
    ENC28J60_Write(MAADR2, mac_addr[3]);
    ENC28J60_Write(MAADR1, mac_addr[4]);
    ENC28J60_Write(MAADR0, mac_addr[5]);
   
    ENC28J60_WritePhy(PHCON1, PHCON1_PDPXMD); // 配置PHY为全双工, LEDB为拉电流
    ENC28J60_WritePhy(PHLCON, 0x0476); // LED状态
    ENC28J60_WritePhy(PHCON2, PHCON2_HDLDIS); // 半双工回环禁止
    ENC28J60_SetBank(ECON1); // 返回BANK0
    ENC28J60_WriteOP(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE | EIE_RXERIE); // 使能中断: 全局中断, 接收中断, 接收错误中断
    ENC28J60_WriteOP(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); // 允许接收
}

void ENC28J60_InitSend(uint16_t len)
{
    while ((ENC28J60_Read(ECON1) & ECON1_TXRTS) != 0); // 查询发送逻辑复位位
   
    // 设置发送缓冲区起始地址
    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);
}

// 读取寄存器值
uint8_t ENC28J60_Read(uint8_t addr)
{
    ENC28J60_SetBank(addr);
    return ENC28J60_ReadOP(ENC28J60_READ_CTRL_REG, addr);
}

// 读缓冲区
void ENC28J60_ReadBuf(uint8_t *p, uint16_t len)
{
    uint8_t data;
    uint8_t first = 1;
    if (len == 0)
        return;
    SPI1->CR1 |= SPI_CR1_SPE;
    SPI1->DR = ENC28J60_READ_BUF_MEM; // 通过SPI发送读取缓冲区命令
    while ((SPI1->SR & SPI_SR_TXE) == 0);
   
    // 循环读取
    while (len--)
    {
        SPI1->DR = 0xff; // 送入下一次要发送的数据
        while ((SPI1->SR & SPI_SR_RXNE) == 0); // 等待本次数据发送完毕
        data = SPI1->DR; // 接收本次数据
        if (first)
            first = 0; // 忽略第一次数据
        else
            *p++ = data;
        while ((SPI1->SR & SPI_SR_TXE) == 0);
    }
    while ((SPI1->SR & SPI_SR_RXNE) == 0);
    *p = SPI1->DR; // 接收最后一次数据
    while (SPI1->SR & SPI_SR_BSY);
    SPI1->CR1 &= ~SPI_CR1_SPE;
}

uint8_t ENC28J60_ReadOP(uint8_t op, uint8_t addr)
{
    uint8_t data;
    SPI1->CR1 |= SPI_CR1_SPE; // 启动SPI总线, 同时自动拉低片选信号CS
    SPI1->DR = op | (addr & 0x1f); // 操作码和地址 (1)
    while ((SPI1->SR & SPI_SR_TXE) == 0); // TXE置位时数据(1)刚好发完1位, 可以向DR中放入下次要发送的数据
    SPI1->DR = 0xff; // 送入数据 (2)
    while ((SPI1->SR & SPI_SR_RXNE) == 0); // 等待数据(1)发送完毕
    data = SPI1->DR; // 接收 (1)
    while ((SPI1->SR & SPI_SR_TXE) == 0); // TXE置位时数据(2)刚好发完1位
    if (addr & 0x80) // 如果是MAC和MII寄存器, 第一个读取的字节无效, 该信息包含在地址的最高位
        SPI1->DR = 0xff; // 送入数据 (3), 再次通过SPI读取数据
    while ((SPI1->SR & SPI_SR_RXNE) == 0); // 等待数据(2)发送完毕
    data = SPI1->DR; // 接收 (2)
    if (addr & 0x80)
    {
        while ((SPI1->SR & SPI_SR_RXNE) == 0); // 等待数据(3)发送完毕
        data = SPI1->DR; // 接收 (3)
    }
    while (SPI1->SR & SPI_SR_BSY);
    SPI1->CR1 &= ~SPI_CR1_SPE; // 关闭SPI总线, 同时自动拉高片选信号CS
    return data;
}

// 设定寄存器存储区域
void ENC28J60_SetBank(uint8_t addr)
{
    addr &= 0x60;
    if (addr != enc28j60_bank)
    {
        ENC28J60_WriteOP(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_BSEL1 | ECON1_BSEL0);
        ENC28J60_WriteOP(ENC28J60_BIT_FIELD_SET, ECON1, addr >> 5);
        enc28j60_bank = addr;
    }
}

// 写寄存器
void ENC28J60_Write(uint8_t addr, uint8_t data)
{
    ENC28J60_SetBank(addr);
    ENC28J60_WriteOP(ENC28J60_WRITE_CTRL_REG, addr, data);
}

// 写缓冲区
void ENC28J60_WriteBuf(uint8_t *p, uint16_t len)
{
    SPI1->CR1 |= SPI_CR1_SPE;
    SPI1->DR = ENC28J60_WRITE_BUF_MEM; // 发送写取缓冲区命令
    while ((SPI1->SR & SPI_SR_TXE) == 0);
   
    // 循环发送
    while (len--)
    {
        SPI1->DR = *p++;
        while ((SPI1->SR & SPI_SR_TXE) == 0);
    }
    while (SPI1->SR & SPI_SR_BSY);
    SPI1->CR1 &= ~SPI_CR1_SPE;
}

void ENC28J60_WriteOP(uint8_t op, uint8_t addr, uint8_t data)
{
    SPI1->CR1 |= SPI_CR1_SPE;
    SPI1->DR = op | (addr & 0x1f); // 发送操作码和寄存器地址
    while ((SPI1->SR & SPI_SR_TXE) == 0);
    SPI1->DR = data; // 发送数据
    while ((SPI1->SR & SPI_SR_TXE) == 0);
    while (SPI1->SR & SPI_SR_BSY);
    data = SPI1->DR; // 清RxNE
    SPI1->CR1 &= ~SPI_CR1_SPE;
}

// 写物理寄存器
void ENC28J60_WritePhy(uint8_t addr, uint16_t data)
{
    ENC28J60_Write(MIREGADR, addr);
    ENC28J60_Write(MIWRL, data);
    ENC28J60_Write(MIWRH, data >> 8);
    while (ENC28J60_Read(MISTAT) & MISTAT_BUSY);
}
一派护法 十九级
3楼 发表于:2017-3-18 22:03
【网卡端口配置:以STM32F103单片机为例】
// 配置SPI1
RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_SPI1EN;
GPIOA->CRL = 0xb4bb0080;
GPIOA->BSRR = GPIO_BSRR_BS1; // PA1为网卡中断输出
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1; // 主机模式, 时钟至少需要8分频(BR=010), 也就是72MHz/8=9MHz
SPI1->CR2 = SPI_CR2_SSOE; // 开CS片选输出
一派护法 十九级
4楼 发表于:2017-3-18 22:10
【端口连线】
PA1连接外中断端口INT,带上拉电阻输入(CRL=8, 且ODR=1)
PA4连接片选端口CS,复用推挽50MHz输出(CRL=b)
PA5连接时钟端口SCK,复用推挽50MHz输出(CRL=b)
PA6连接端口SO,浮空输入(CRL=4)
PA7连接端口SI,复用推挽50MHz输出(CRL=b)

当SPE=1时SPI总线启动,CS=0;当SPE=0时SPI总线关闭,CS=1。(SSOE=1)
SPI总线的Baud Rate必须至少为8分频(=f_PCLK/8),也就是将BR位设为010。
一派护法 十九级
5楼 发表于:2017-3-19 12:33
【头文件中未引用的宏定义】
ERXWRPTL, ERXWRPTH, EDMASTL, EDMASTH, EDMANDL, EDMANDH, EDMADSTL, EDMADSTH, EDMACSL, EDMACSH, EHT0, EHT1, EHT2, EHT3, EHT4, EHT5, EHT6, EHT7, EPMM2, EPMM3, EPMM4, EPMM5, EPMM6, EPMM7, EPMOL, EPMOH, EWOLIE, EWOLIR, PHSTAT1, PHHID1, PHHID2, PHSTAT2, PHIE, PHIR, ERXFCON_ANDOR, ERXFCON_MPEN, ERXFCON_HTEN, ERXFCON_MCEN, ERXFCON_BCEN, EIE_DMAIE, EIE_LINKIE, EIE_TXIE, EIE_WOLIE, EIE_TXERIE, EIR_PKTIF, EIR_DMAIF, EIR_LINKIF, EIR_TXIF, EIR_WOLIF, EIR_RXERIF, ESTAT_INT, ESTAT_LATECOL, ESTAT_RXBUSY, ESTAT_TXABRT, ECON2_AUTOINC, ECON2_PWRSV, ECON2_VRPS, ECON1_TXRST, ECON1_RXRST, ECON1_DMAST, ECON1_CSUMEN, MACON1_LOOPBK, MACON1_PASSALL, MACON2_MARST, MACON2_RNDRST, MACON2_MARXRST, MACON2_RFUNRST, MACON2_MATXRST, MACON2_TFUNRST, MACON3_PADCFG2, MACON3_PADCFG1, MACON3_PHDRLEN, MACON3_HFRMLEN, MICMD_MIISCAN, MICMD_MIIRD, MISTAT_NVALID, MISTAT_SCAN, PHCON1_PRST, PHCON1_PLOOPBK, PHCON1_PPWRSV, PHSTAT1_PFDPX, PHSTAT1_PHDPX, PHSTAT1_LLSTAT, PHSTAT1_JBSTAT, PHCON2_FRCLINK, PHCON2_TXDIS, PHCON2_JABBER, PKTCTRL_PHUGEEN, PKTCTRL_PPADEN, PKTCTRL_PCRCEN, PKTCTRL_POVERRIDE
一派护法 十九级
6楼 发表于:2017-3-19 12:34
【精简后的ENC28J60.h头文件】
#define EIE 0x1b
#define EIR 0x1c
#define ESTAT 0x1d
#define ECON2 0x1e
#define ECON1 0x1f

// Bank 0 registers
#define ERDPTL 0x00
#define ERDPTH 0x01
#define EWRPTL 0x02
#define EWRPTH 0x03
#define ETXSTL 0x04
#define ETXSTH 0x05
#define ETXNDL 0x06
#define ETXNDH 0x07
#define ERXSTL 0x08
#define ERXSTH 0x09
#define ERXNDL 0x0a
#define ERXNDH 0x0b
#define ERXRDPTL 0x0c
#define ERXRDPTH 0x0d

// Bank 1 registers
#define EPMM0 0x28
#define EPMM1 0x29
#define EPMCSL 0x30
#define EPMCSH 0x31
#define ERXFCON 0x38
#define EPKTCNT 0x39

// Bank 2 registers
#define MACON1 0xc0
#define MACON2 0xc1
#define MACON3 0xc2
#define MABBIPG 0xc4
#define MAIPGL 0xc6
#define MAIPGH 0xc7
#define MAMXFLL 0xca
#define MAMXFLH 0xcb
#define MIREGADR 0xd4
#define MIWRL 0xd6
#define MIWRH 0xd7

// Bank 3 registers
#define MAADR1 0xe0
#define MAADR0 0xe1
#define MAADR3 0xe2
#define MAADR2 0xe3
#define MAADR5 0xe4
#define MAADR4 0xe5
#define MISTAT 0xea

// PHY registers
#define PHCON1 0x00
#define PHCON2 0x10
#define PHLCON 0x14

#define ERXFCON_UCEN 0x80
#define ERXFCON_CRCEN 0x20
#define ERXFCON_PMEN 0x10
#define EIE_INTIE 0x80
#define EIE_PKTIE 0x40
#define EIE_RXERIE 0x01
#define EIR_TXERIF 0x02
#define ESTAT_CLKRDY 0x01
#define ECON2_PKTDEC 0x40
#define ECON1_TXRTS 0x08
#define ECON1_RXEN 0x04
#define ECON1_BSEL1 0x02
#define ECON1_BSEL0 0x01
#define MACON1_TXPAUS 0x08
#define MACON1_RXPAUS 0x04
#define MACON1_MARXEN 0x01
#define MACON3_PADCFG0 0x20
#define MACON3_TXCRCEN 0x10
#define MACON3_FRMLNEN 0x02
#define MACON3_FULDPX 0x01
#define MISTAT_BUSY 0x01
#define PHCON1_PDPXMD 0x0100
#define PHCON2_HDLDIS 0x0100

/* 指令集, 详见数据手册26页 */
#define ENC28J60_READ_CTRL_REG 0x00 // 读控制寄存器
#define ENC28J60_READ_BUF_MEM 0x3a // 读缓冲区
#define ENC28J60_WRITE_CTRL_REG 0x40 // 写控制寄存器
#define ENC28J60_WRITE_BUF_MEM 0x7a // 写缓冲区
#define ENC28J60_BIT_FIELD_SET 0x80 // 位域置位
#define ENC28J60_BIT_FIELD_CLR 0xa0 // 位域清零
#define ENC28J60_SOFT_RESET 0xff // 系统复位

#define RXSTART_INIT 0 // 接收缓冲区起始地址
#define RXSTOP_INIT (0x1fff - 0x0600 - 1) // 接收缓冲区停止地址
#define TXSTART_INIT (0x1fff - 0x0600) // 发送缓冲区起始地址, 大小约1500字节
#define TXSTOP_INIT 0x1fff // 发送缓冲区停止地址
#define MAX_FRAMELEN 1500 // 以太网报文最大长度

void ENC28J60_BeginSend(void);
void ENC28J60_EndReceive(void);
uint16_t ENC28J60_GetPacketLength(void);
uint8_t ENC28J60_GetPacketNum(void);
void ENC28J60_Init(uint8_t *mac_addr);
void ENC28J60_InitSend(uint16_t len);
uint8_t ENC28J60_Read(uint8_t addr);
void ENC28J60_ReadBuf(uint8_t *p, uint16_t len);
uint8_t ENC28J60_ReadOP(uint8_t op, uint8_t addr);
void ENC28J60_SetBank(uint8_t addr);
void ENC28J60_Write(uint8_t addr, uint8_t data);
void ENC28J60_WriteBuf(uint8_t *p, uint16_t len);
void ENC28J60_WriteOP(uint8_t op, uint8_t addr, uint8_t data);
void ENC28J60_WritePhy(uint8_t addr, uint16_t data);

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:615 回复数:5
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2017-3-19 12:34
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。