#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)
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;
}
uint8_t ENC28J60_ReadOp(uint8_t op, uint8_t address)
{
uint8_t dat = 0;
ENC28J60_CS(0);
dat = op | (address & ADDR_MASK);
SPI_ReadWrite(dat);
dat = SPI_ReadWrite(0xFF);
if(address & 0x80)
{
dat = SPI_ReadWrite(0xFF);
}
ENC28J60_CS(1);
return dat;
}
void ENC28J60_WriteOp(uint8_t op, uint8_t address, uint8_t data)
{
uint8_t dat = 0;
ENC28J60_CS(0);
dat = op | (address & ADDR_MASK);
SPI_ReadWrite(dat);
SPI_ReadWrite(data);
ENC28J60_CS(1);
}
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);
}
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);
}
void ENC28J60_SetBank(uint8_t address)
{
if((address & BANK_MASK) != Enc28j60Bank)
{
ENC28J60_WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0));
ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5);
Enc28j60Bank = (address & BANK_MASK);
}
}
uint8_t ENC28J60_Read(uint8_t address)
{
ENC28J60_SetBank(address);
return ENC28J60_ReadOp(ENC28J60_READ_CTRL_REG, address);
}
void ENC28J60_Write(uint8_t address, uint8_t data)
{
ENC28J60_SetBank(address);
ENC28J60_WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
}
void ENC28J60_PhyWrite(uint8_t address, uint16_t data)
{
uint16_t retry = 0;
ENC28J60_Write(MIREGADR, address);
ENC28J60_Write(MIWRL, data);
ENC28J60_Write(MIWRH, data >> 8);
while(ENC28J60_Read(MISTAT) & MISTAT_BUSY && retry < 0XFFF)
{
retry++;
}
}
uint16_t ENC28J60_PhyRead(uint8_t address)
{
uint16_t retry = 0;
uint16_t data;
ENC28J60_Write(MIREGADR, address);
ENC28J60_Write(MICMD, MICMD_MIIRD);
while((ENC28J60_Read(MISTAT) & MISTAT_BUSY) && retry < 0XFFF)
{
retry++;
}
ENC28J60_Write(MICMD, 0x00);
data = ENC28J60_Read(MIRDH) << 8;
data |= ENC28J60_Read(MIRDL);
return data;
}
void ENC28J60_clkout(uint8_t clk)
{
ENC28J60_Write(ECOCON, clk & 0x7);
}
uint8_t ENC28J60_getrev(void)
{
return ENC28J60_Read(EREVID);
}
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;
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);
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);
ENC28J60_Write(MACON2, 0x00);
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);
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]);
ENC28J60_PhyWrite(PHCON1, PHCON1_PDPXMD);
ENC28J60_PhyWrite(PHCON2, PHCON2_HDLDIS);
ENC28J60_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;
else
return 1;
}
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);
ENC28J60_WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
ENC28J60_WriteBuffer(len, packet);
ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
if( (ENC28J60_Read(EIR) & EIR_TXERIF) )
{
ENC28J60_WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
}
}
uint32_t ENC28J60_PacketReceive(uint32_t maxlen, uint8_t* packet)
{
uint32_t rxstat;
uint32_t len;
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;
len = ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0);
len |= ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
len -= 4;
rxstat = ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0);
rxstat |= ENC28J60_ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
if (len > maxlen - 1)
{
len = maxlen - 1;
}
if ((rxstat & 0x80) == 0)
{
len = 0;
}
else
{
ENC28J60_ReadBuffer(len, packet);
}
ENC28J60_Write(ERXRDPTL, (NextPacketPtr));
ENC28J60_Write(ERXRDPTH, (NextPacketPtr) >> 8);
ENC28J60_WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
return(len);
}
#ifndef __ENC28J60_H
#define __ENC28J60_H
#include "stm32f1xx_hal.h"
#define ADDR_MASK 0x1F
#define BANK_MASK 0x60
#define SPRD_MASK 0x80
#define EIE 0x1B
#define EIR 0x1C
#define ESTAT 0x1D
#define ECON2 0x1E
#define ECON1 0x1F
#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)
#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)
#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)
#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)
#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)
#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
#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
#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
#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
#define ESTAT_INT 0x80
#define ESTAT_LATECOL 0x10
#define ESTAT_RXBUSY 0x04
#define ESTAT_TXABRT 0x02
#define ESTAT_CLKRDY 0x01
#define ECON2_AUTOINC 0x80
#define ECON2_PKTDEC 0x40
#define ECON2_PWRSV 0x20
#define ECON2_VRPS 0x08
#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
#define MACON1_LOOPBK 0x10
#define MACON1_TXPAUS 0x08
#define MACON1_RXPAUS 0x04
#define MACON1_PASSALL 0x02
#define MACON1_MARXEN 0x01
#define MACON2_MARST 0x80
#define MACON2_RNDRST 0x40
#define MACON2_MARXRST 0x08
#define MACON2_RFUNRST 0x04
#define MACON2_MATXRST 0x02
#define MACON2_TFUNRST 0x01
#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
#define MICMD_MIISCAN 0x02
#define MICMD_MIIRD 0x01
#define MISTAT_NVALID 0x04
#define MISTAT_SCAN 0x02
#define MISTAT_BUSY 0x01
#define PHCON1_PRST 0x8000
#define PHCON1_PLOOPBK 0x4000
#define PHCON1_PPWRSV 0x0800
#define PHCON1_PDPXMD 0x0100
#define PHSTAT1_PFDPX 0x1000
#define PHSTAT1_PHDPX 0x0800
#define PHSTAT1_LLSTAT 0x0004
#define PHSTAT1_JBSTAT 0x0002
#define PHCON2_FRCLINK 0x4000
#define PHCON2_TXDIS 0x2000
#define PHCON2_JABBER 0x0400
#define PHCON2_HDLDIS 0x0100
#define PKTCTRL_PHUGEEN 0x08
#define PKTCTRL_PPADEN 0x04
#define PKTCTRL_PCRCEN 0x02
#define PKTCTRL_POVERRIDE 0x01
#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 0x0
#define RXSTOP_INIT (0x1FFF-0x0600-1)
#define TXSTART_INIT (0x1FFF-0x0600)
#define TXSTOP_INIT 0x1FFF
#define MAX_FRAMELEN 1500
uint8_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中文手册.pdf