Embedded Ethernet: Part 1

I’m working on a project using Microchip’s ENC28J60 and PIC32MX340F128H.  The ENC controller communicates via SPI to the host microcontroller, just add a few discretes and a mag jack and you’re all set (supposedly).  Microchip provides a HUGE (in my opinion, bloated) stack for all sorts of features (SMTP, Telnet, FTP, HTTP Server) but I don’t need all of that.  I just want a simple device that will obtain an IP (so I need DHCP) and talk with a webpage (send data, maybe via GET method page requests and retrieve data from the page).  Maybe I could implement an interrupt by requesting a certain page on a certain port which wouldn’t return a page (which would require an HTTP server) but would just force the device to check the update page.

Anyway, I’m going to document my progress through working with these two chips, post some code, some things I’ve found helpful, etc. — maybe they’ll be of interest to someone.

I’ll start with the lowest level stuff — the code that controls the SPI Peripheral of the PIC32:

P32_SPI.h

// P32_SPI.h
#ifndef _H_SPI
#define _H_SPI

#include

#include

#include "globals.h"
#include "static.h"

void SPI_Init(unsigned char, unsigned char);

void SPI_Interrupt(unsigned char, unsigned char);

void SPI_Put(unsigned char, unsigned char);

unsigned char SPI_Get(unsigned char);

#endif

P32_SPI.c

// P32_SPI.c
#include "P32_SPI.h"

void SPI_Init(unsigned char port, unsigned char brg)
{	
	unsigned char dummy;
	if(port == 1)
	{		
	
		// Disable SPI Interrupts in IEC0/1
		IEC0bits.SPI1RXIE = 0;
		IEC0bits.SPI1TXIE = 0;
		IEC0bits.SPI1EIE  = 0;
		
		// Stop and Reset the SPI Module by clearing the ON bit
		SPI1CONbits.ON = 0;
		
		// Clear the receive buffer
		dummy = SPI1BUF;
		
		// Clear the SPIx interrupt flags in IFS0/1
		IFS0bits.SPI1RXIF = 0;
		IFS0bits.SPI1TXIF = 0;
		IFS0bits.SPI1EIF  = 0;	
		
		// Write the Baud Rate register, SPIxBRG
		// FSCK = FPB / (2 * (SPIxBRG+1) )
		SPI1BRG = brg;
		
		// Clear the SPIROV bit (SPIxSTAT<6>)
		SPI1STATbits.SPIROV = 0;
		
		// Write the selected configuration settings to the SPIxCON register
		SPI1CONbits.FRMEN = 0;		// Disable Framed SPI Support
		SPI1CONbits.MODE32 = 0;		// 8 bit transfer mode
		SPI1CONbits.MODE16 = 0;
		
		SPI1CONbits.SMP = 0;		// 0: Data sampled at middle, 1: Data sampled at end
		SPI1CONbits.CKE = 1;
		SPI1CONbits.CKP = 0;
		SPI1CONbits.SSEN = 0;		// Relase Slave Select
		SPI1CONbits.MSTEN = 1;		// Master Mode
		
		// Enable SPI operation by setting the ON bit (SPIxCON<15>)
		SPI1CONbits.ON = 1;
	}
		
	if(port == 2)
	{		
	
		// Disable SPI Interrupts in IEC0/1
		IEC1bits.SPI2RXIE = 0;
		IEC1bits.SPI2TXIE = 0;
		IEC1bits.SPI2EIE  = 0;
		
		// Stop and Reset the SPI Module by clearing the ON bit
		SPI2CONbits.ON = 0;
		
		// Clear the receive buffer
		dummy = SPI2BUF;
		
		// Clear the SPIx interrupt flags in IFS0/1
		IFS1bits.SPI2RXIF = 0;
		IFS1bits.SPI2TXIF = 0;
		IFS1bits.SPI2EIF  = 0;	
		
		// Write the Baud Rate register, SPIxBRG
		// FSCK = FPB / (2 * (SPIxBRG+1) )
		SPI2BRG = brg;
		
		// Clear the SPIROV bit (SPIxSTAT<6>)
		SPI2STATbits.SPIROV = 0;
		
		// Write the selected configuration settings to the SPIxCON register
		SPI2CONbits.FRMEN = 0;		// Disable Framed SPI Support
		SPI2CONbits.MODE32 = 0;		// 8 bit transfer mode
		SPI2CONbits.MODE16 = 0;
		
		SPI2CONbits.SMP = 0;		// 0: Data sampled at middle, 1: Data sampled at end
		SPI2CONbits.CKE = 0;
		SPI2CONbits.CKP = 0;		// 0: Idle Low, Active High
		SPI2CONbits.SSEN = 0;		// Relase Slave Select
		SPI2CONbits.MSTEN = 1;		// Master Mode
		
		// Enable SPI operation by setting the ON bit (SPIxCON<15>)
		SPI2CONbits.ON = 1;
	}
	
}	

void SPI_Interrupt(unsigned char port, unsigned char ie)
{
	if(port == 1)
	{
		// Clear / Set the SPIx interrupt enable bits in  IEC0/1
		if(ie)
		{
			IEC0bits.SPI1RXIE = bittest(ie, 0);
			IEC0bits.SPI1TXIE = bittest(ie, 1);
			IEC0bits.SPI1EIE  = bittest(ie, 2);
		}
		else
		{
			IEC0bits.SPI1RXIE = 0;
			IEC0bits.SPI1TXIE = 0;
			IEC0bits.SPI1EIE  = 0;
		}
	}
	if(port == 2)
	{
		// Clear / Set the SPIx interrupt enable bits in  IEC0/1
		if(ie)
		{
			IEC1bits.SPI2RXIE = bittest(ie, 0);
			IEC1bits.SPI2TXIE = bittest(ie, 1);
			IEC1bits.SPI2EIE  = bittest(ie, 2);
		}
		else
		{
			IEC1bits.SPI2RXIE = 0;
			IEC1bits.SPI2TXIE = 0;
			IEC1bits.SPI2EIE  = 0;
		}
	}
}

void SPI_Put(unsigned char port, unsigned char byte)
{
	#ifdef DEBUG_SPI
	printf("SPI%1d PUT: %02x\r\n", port, byte);
	#endif 

	if(port == 2)
	{
		SpiChnPutC(2, byte);
		// Throw out clocked in data
		getcSPI2();
	}

}	

unsigned char SPI_Get(unsigned char port)
{
	unsigned char byte = -1;
	
	if(port == 2)
	{
		SpiChnPutC(2, 0x00);
		byte = getcSPI2();
	}
	
	#ifdef DEBUG_SPI
	printf("SPI%1d GET: %02x\r\n", port, byte);
	#endif 
	
	return byte;
}	
Posted Sunday, March 15th, 2009 under firmware, projects.

Leave a Reply