Spanish Italian
17436 Users    

Ethernet 3/7

  Download PDF version of the Article

The SPI interface
The communication between ENC28J60 and PIC it happens through the interface SPI; this only supports the 0,0 modality and the controller is a slave, so the PIC provides the clock and manages the transmission.

The maximum admitted frequency is of 10Mhz for the Rev. B1-B4, while is double for the B5. Also, because of a problem in the interface (described in Errata), for the Rev. B1-B4 the clock must necessarily be between 8 and 10Mhz, or the PIC clock must be draw from the pin CLKOUT of the controller (max 25Mhz). So, in the first case the PIC must work at a frequency between 32 and 40Mhz.

SPI Commands
Through the interface is possible to send to the chip 7 various commands (of 8bit), eventuality followed from a dates byte; there are:

Nome 1° byte 2° byte Description
Read Control Register (RCR) 000 AAAAA is useful to read the control register A
Write Control Register (WCR) 010 AAAAA DDDDDDDD to write the byte D inside the registry A (in the selected bank)
Read Buffer Memory (RBM) 00111010 is useful to read the controller RAM memory to the current address.
Write Buffer Memory (WBM) 01111010 DDDDDDDD writes the byte D to the current address of the RAM memory.
Bit Field Set (BFS) 100 AAAAA DDDDDDDD sets in the registry A (just ETH), the bit which in D are at 1 (OR).
Bit Field Set (BFS) 101 AAAAA DDDDDDDD resets in the registry A (just ETH), the bit which in D are at 1 (NOT AND).
System Reset Command (SRC) 11111111 reset the controller.

SPI Commands: implementation
The SPI initialization module is illustrated, let's see some base methods.

#define spiWrite(x)	spiRW(x)
#define spiRead()	spiRW(0)
 ....
u8 spiRW(u8 data){
	SSPBUF = data;
	while(!PIR1bits.SSPIF);
	PIR1bits.SSPIF = 0;
	return SSPBUF;
}

This is a method which permits to read/write in the bus SPI. As far as the writing, the byte for the sending (data) is put in the SSPBUF registry (is part of SPI module), then attend that the transmission is finished observing the SSPIF bit; to read a byte, is necessary to write a zero in the registry SSPBUF (like this are generated 8 impulses of clock), attend the operation end and the read byte it will be in the same SSPBUF registry .
In this case I I have condensed in an only method the reading operations and writing, then, for mental clarity, I have defined spiWrite and spiRead.

#define CS	PORTCbits.RC2 // Chip Select dell'ENC28J60

#define	WCR	(0b01000000)		// Write Control Register command
#define BFS	(0b10000000)		// Bit Field Set command
#define	BFC	(0b10100000)		// Bit Field Clear command
#define	RCR	(0b00000000)		// Read Control Register command
#define RBM	(0b00111010)		// Read Buffer Memory command
#define	WBM	(0b01111010) 		// Write Buffer Memory command
#define	SRC	(0b11111111)		// System Reset command
 ....
void writeReg(u8 reg, u8 data){
	CS = 0;
	spiWrite(WCR | reg);
	spiWrite(data);
	CS = 1;
}

u8 readMAC(u8 reg){
	u8 b;
	CS = 0;
	spiWrite(RCR | reg);
	spiRead();
	b = spiRead();
	CS = 1;
	return b;
}

u8 readETH(u8 reg){
	u8 b;
  	CS = 0;
	spiWrite(RCR | reg);
	b = spiRead();
  	CS = 1;
  	return b;
}

With these three methods we can read and write the control registries ( to read registries MII is used readMAC).
Like you can notice the reading procedure of a MAC and ETH registry is slightly diverse, for the first type must send a bite zero before make the reading.

void BFCReg(u8 reg, u8 data){
  	CS = 0;
	spiWrite(BFC | reg);
	spiWrite(data);
  	CS = 1;
}

void BFSReg(u8 reg, u8 data){
  	CS = 0;
	spiWrite(BFS | reg);
	spiWrite(data);
  	CS = 1;
}

void setBank(u8 bank){
  	BFCReg(ECON1, 0b11);
  	BFSReg(ECON1, bank);
}

Here we see the Bit Set and Bit Clear commands implementation; then the setBank method, with which we can select the memory bank of the control registries, acting on the ECON1 registry (commune at all the baks).

u16  bufSize;
  ....
void encPut(u8 b){
	CS = 0;
	spiWrite(WBM);
	spiWrite(b);
	CS = 1;	
	bufSize++;
}

u8 encGet(){
	u8 b;
	CS = 0;
	spiWrite(RBM);
	b = spiRead();
	CS = 1;	
	return b;
}

void sendReset(){
	CS = 0;
	spiWrite(SRC);
	CS = 1;
}

The remaining three commands are performed by these three methods: the reading and the writing of the RAM, and reset. The variable static bufSize is useful to keep track of the RAM byte number (it will be useful then).

The PHY registers
The PHY registers are a 16bit and are accessible the way of MII registers.
To read a PHY register:

  • it is put the the address in the MIREGADR register;
  • setting the bit MIIRD (1) of the MICMD register, starts the reading;
  • attend the end of the reading observing the BUSY bit of the MISTAT register;
  • resetting the MIIRD bit;
  • the data will be present in the MIRDL and MIRDH registers;

To write in a PHY register:

  • put the register address in MIREGADR;
  • first write the byte less important in MIWRL, then writing the byte more important in MIWRH starts the writing.
  • attend that the module PHY finishes the operation.
u16 readPHY(u8 reg){
	setBank(2);
	writeReg(MIREGADR, reg);
	writeReg(MICMD, 0x01);	

	setBank(3);
	while(readMAC(MISTAT) & 1);

	setBank(2);
	writeReg(MICMD, 0x00);	
	
	return readMAC(MIRDL) | (readMAC(MIRDH) << 8 );
}

void writePHY(u8 reg, u16 data){
	setBank(2);
	writeReg(MIREGADR, reg);
	writeReg(MIWRL, LOW(data));
	writeReg(MIWRH, HIGH(data));

	setBank(3);
	while (readMAC(MISTAT) & 1);
}

Others methods
The following are useful to writing/reading more byte from the controller RAM; the address from where are read is contained in the ERDPT registers, while the writing address is contained in the EWRPT registers (are auto increasing).

void encGetArray(u8* buf, u16 len){
	CS = 0;
	spiWrite(RBM);
	while(len--)
		*buf++ = spiRead();
	CS = 1;
}

void encPutArray(u8* buf,u16 len){
	bufSize += len;
	CS = 0;
	spiWrite(WBM);
	while(len--)
		spiWrite(*buf++);
	CS = 1;
}	

void encPutString(const rom u8 *str){
	CS = 0;
	spiWrite(WBM);
	while(*str) {
    		spiWrite(*str++);
		bufSize++;
	}
	CS = 1;
}

The SPI Initialization
The SPI module initialization it's happen in these two simples instructions:

 void encInit(){
  	TRISB = 0xFF;		// configuration I/O di PORTB
  	TRISC = 0xD1;		// configuration I/O di PORTC
  	PORTC = 0x00;
	
	SSPSTAT = 0x40;	
	SSPCON1 = 0x20;

In particular the module MSSP is enabled and configured in "0,0"modality, with clock equivalent at Fosc/4.

ENC28J60 Initialization
The controller initialization predicts the various registers configurations, as well as the qualification to the reception.

#define RX_BUF_START	0
#define RX_BUF_END	6499	
#define	TX_BUF_START	6500
 ....
setBank(0);
writeReg(ERXSTL,   LOW(RX_BUF_START));		//
writeReg(ERXSTH,   HIGH(RX_BUF_START));		// start buffer of the reading
writeReg(ERXRDPTL, LOW(RX_BUF_END));		//
writeReg(ERXRDPTH, HIGH(RX_BUF_END));		//  buffer punter of the reading
writeReg(ERXNDL,   LOW(RX_BUF_END));		//
writeReg(ERXNDH,   HIGH(RX_BUF_END));		// fine buffer of the reading
writeReg(ETXSTL,   LOW(TX_BUF_START));		//
writeReg(ETXSTH,   HIGH(TX_BUF_START));		// start buffer of the reading

The ENC28J60 buffer can be divided between the transmission memory and the reception.
To do that already si configurano i puntatori del buffer di ricezione; the memory remaining will be the transmission buffer.
The registers ERXST contain the first byte address of the reception buffer, while the ERXND registers the last byte.
In ERXRDPT, instead, resides the reading punter of RX memory, or rather check off a zone (together with ERXWRPT) which must be elaborated from the PIC and so can't be wrote; initially the value of this address is the same with ERXND (must be odd aster a problem described in Errata). The ERXWRPT register is zero at reset and is updated automatically to a packet reception.

setBank(2);
writeReg(MACON1, 0b01101);  		// MARXEN,  TXPAUS,  RXPAUS
writeReg(MACON3, 0b00110000); 		// Half Duplex, Padding 60byte, CRC
writeReg(MAIPGL, 0x12); 		//
writeReg(MAIPGH, 0x0C); 		//
writeReg(MABBIPG,0x12); 		// Inter-Packet Gap

These registers configure the MAC module.Through the MACON1 register is enabled the MAC module and the pause plot reception/transmission.
With the MACON3 register is choice the Duplex (Half or Full) modality of the MAC module that must be imposted in the same mode in the PHY module too; also in this register there are presentes some configurations about Padding automatic and the CRC calculation.
The MAIPG and MABBIPG registers contain the pause values between the packets; those presents in the code are the standard values.

writeReg(MAMXFLL, LOW(1500));
writeReg(MAMXFLH, HIGH(1500));

In the MAXFL (Max Frame Length) registers is salved the maximum dimension allowed for a packet; the controller can be configured that refuses to send a packet which pass this limit.

#define MY_MAC1     0x00
#define MY_MAC2     0x04
#define MY_MAC3     0xA3
#define MY_MAC4     0x00
#define MY_MAC5     0x00
#define MY_MAC6     0x00
  ....
setBank(3);
writeReg(MAADR1, MY_MAC1);
writeReg(MAADR2, MY_MAC2);
writeReg(MAADR3, MY_MAC3);
writeReg(MAADR4, MY_MAC4);
writeReg(MAADR5, MY_MAC5);
writeReg(MAADR6, MY_MAC6);

The MAC address of our device is saved in the MACADR registers; these are used from the filter to reject the packets which aren't destined to the controller, so the address isn't insert automatically in the send packets.

writePHY(PHCON2, 0b0000000100000000);	// disability the loopback
writePHY(PHCON1, 0);			// ability the PHY

setBank(1);
writeReg(ERXFCON, 0b10100001); 		// impost the reception filters
BFSReg(ECON1, 0b100);         		// ability the reception

With this last fragment ends the controller initialization. The PHY module hasn't many options to configure, the only options to configure are the LoopBack disabling (used to make the test) and the module qualification.
The filters are setts to accept just the packets for the configured MAC address and broadcast.

Ethernet 1/7
Ethernet 2/7

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
1 + 5 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.

Who's new

  • pulper
  • mauriss
  • jbares
  • christiank79
  • agabor
  • fabriziopd
  • irenix
  • pepershoe
  • raghun14
  • andreaspousette

Who's online

There are currently 0 users and 44 guests online.