📄 main.c
字号:
/******************************************************************************
*
* Copyright:
* (C) 2000 - 2006 Embedded Artists AB
*
* Description:
* Sample application that implements ICMP (Ping) functionality.
*
*****************************************************************************/
/******************************************************************************
* Includes
*****************************************************************************/
#include "general.h"
#include "ethapi.h"
#include <ea_init.h>
#include <printf_P.h>
#include <string.h>
#include <lpc2xxx.h>
/******************************************************************************
* Defines
*****************************************************************************/
#define INBUF_LEN 1500
#define ARP_REQUEST 1 /* Operation ARP request */
#define ARP_REPLY 2 /* Operation ARP reply */
#define CRYSTAL_FREQUENCY FOSC
#define PLL_FACTOR PLL_MUL
#define VPBDIV_FACTOR PBSD
#define SPI_SLAVE_CS 0x00002000 //pin P0.13
#define ENC_RESET 0x00001000 //pin P0.12
#define FAILSAFE_VALUE 5000
/******************************************************************************
* Local variables
*****************************************************************************/
/*
* The IP address assigned to the local host.
*/
static tU8 localIP[4] = {192,168,1,230};
/*
* The Ethernet address (MAC) assigned to the local host
*/
static tU8 mac[6] = {0x60, 0x06, 0x98, 0x01, 0x16, 0x34};
static tU8 inBuf[INBUF_LEN];
static tU8 bank = 0;
tU8 encReadReg(tU8 regNo);
/*****************************************************************************
*
* Description:
* Delay execution by a specified number of milliseconds by using
* timer #1. A polled implementation.
*
* Params:
* [in] delayInMs - the number of milliseconds to delay.
*
****************************************************************************/
static void
delayMs(tU16 delayInMs)
{
/*
* setup timer #1 for delay
*/
TIMER1_TCR = 0x02; //stop and reset timer
TIMER1_PR = 0x00; //set prescaler to zero
TIMER1_MR0 = delayInMs * ((CRYSTAL_FREQUENCY * PLL_FACTOR)/ (1000 * VPBDIV_FACTOR));
TIMER1_IR = 0xff; //reset all interrrupt flags
TIMER1_MCR = 0x04; //stop timer on match
TIMER1_TCR = 0x01; //start timer
//wait until delay time has elapsed
while (TIMER1_TCR & 0x01)
;
}
/*****************************************************************************
*
* Description:
* Sends and received one byte over the SPI serial channel.
* A polled implementation.
*
* Params:
* [in] byte - the byte to send.
*
* Return:
* The received byte.
*
****************************************************************************/
static tU8
sendSpi(tU8 byte)
{
tU32 failsafe;
tU8 receivedByte;
SPI_SPDR = byte;
failsafe = 0;
while(((SPI_SPSR & 0x80) == 0) && (failsafe < FAILSAFE_VALUE))
failsafe++;
receivedByte = SPI_SPDR;
//reinitialize SPI if timeout
if (failsafe >= FAILSAFE_VALUE)
{
printf("\nSPI-error: SSEL signal must be high!\n");
receivedByte = 0x00;
SPI_SPCCR = 0x08;
SPI_SPCR = 0x20; //no irq, MSB first, master, cpol=0, cpha=0
}
return receivedByte;
}
/*****************************************************************************
*
* Description:
* Low-level routine to write a register in ENC28J60
*
****************************************************************************/
void
encWriteReg(tU8 regNo, tU8 data)
{
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0x40 | regNo); //write in regNo
sendSpi(data);
IOSET0 = SPI_SLAVE_CS; //deactivate SP
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0x1f); //read reg 0x1f
IOSET0 = SPI_SLAVE_CS; //deactivate SP
}
/*****************************************************************************
*
* Description:
* Low-level routine to read a register in ENC28J60
*
****************************************************************************/
tU8
encReadReg(tU8 regNo)
{
tU8 rxByte;
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0x1f); //read reg 0x1f
bank = sendSpi(0) & 0x3;
IOSET0 = SPI_SLAVE_CS; //deactivate SP
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(regNo); //read reg i
rxByte = sendSpi(0);
//check if MAC or MII register
if (((bank == 2) && (regNo <= 0x1a)) ||
((bank == 3) && (regNo <= 0x05 || regNo == 0x0a)))
//ignore first byte and read another byte
{
rxByte = sendSpi(0);
printf("\nRead MAC or MII reg = %x value=%x", regNo, rxByte);
}
IOSET0 = SPI_SLAVE_CS; //deactivate SP
return rxByte;
}
/*****************************************************************************
*
* Description:
* Low-level routine to read a received frame in the ENC28J60
*
****************************************************************************/
void
encReadBuff(tU16 length, tU8 *pBuff)
{
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0x20 | 0x1a); //read buffer memory
while(length--)
{
if(pBuff != NULL)
*pBuff++ = sendSpi(0);
else
sendSpi(0);
}
IOSET0 = SPI_SLAVE_CS; //deactivate SP
}
/*****************************************************************************
*
* Description:
* Low-level routine to write a frame to be transmitted in the ENC28J60
*
****************************************************************************/
void
encWriteBuff(tU16 length, tU8 *pBuff)
{
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0x60 | 0x1a); //write buffer memory
while(length--)
sendSpi(*pBuff++);
IOSET0 = SPI_SLAVE_CS; //deactivate SP
}
/*****************************************************************************
*
* Description:
* Low-level routine to set a bit in one register in the ENC28J60
*
****************************************************************************/
void
encBitSet(tU8 regNo, tU8 data)
{
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0x80 | regNo); //bit field set
sendSpi(data);
IOSET0 = SPI_SLAVE_CS; //deactivate SP
}
/*****************************************************************************
*
* Description:
* Low-level routine to clear a bit in one register in the ENC28J60
*
****************************************************************************/
void
encBitClr(tU8 regNo, tU8 data)
{
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0xA0 | regNo); //bit field clear
sendSpi(data);
IOSET0 = SPI_SLAVE_CS; //deactivate SP
}
/*****************************************************************************
*
* Description:
* Low-level routine to reset the ENC28J60
*
****************************************************************************/
void
encReset(void)
{
IOCLR0 = SPI_SLAVE_CS; //activate SPI
sendSpi(0xff); //soft reset
IOSET0 = SPI_SLAVE_CS; //deactivate SP
}
/*****************************************************************************
*
* Description:
* Initialize the SPI channle #0
*
****************************************************************************/
void
initSpi(void)
{
//connect SPI bus to IO-pins
PINSEL0 |= 0x00005500;
//initialize SPI interface
SPI_SPCCR = 0x08;
SPI_SPCR = 0x20; //no irq, MSB first, master, cpol=0, cpha=0
//make SPI slave chip select an output and set signal high
IODIR |= SPI_SLAVE_CS;
IOSET = SPI_SLAVE_CS;
//reset ENC28J60
IODIR |= ENC_RESET;
IOSET = ENC_RESET;
IOCLR = ENC_RESET;
delayMs(1); //reset pulse width > 2 us
IOSET = ENC_RESET;
delayMs(1); //wait >300us after reset
}
/*****************************************************************************
*
* Description:
* Checksum calculation. 16-bit one's complement.
*
* Params:
* [in] pStartAddress - pointer to beginning of data
* [in] len - length of data
* [in] initialValue - precalculated checksum (e.g. pseudo header)
*
* Returns:
* calculated checksum
*
****************************************************************************/
static tU16
checksum(tU8* pStartAddress,
tU16 len,
tU16 initialValue)
{
tU32 csum = ~initialValue & 0x0000ffff;
tU8 *p8bit = NULL;
tU16 val16 = 0;
tU32 aWordCount = len / 2;
p8bit = pStartAddress;
while (aWordCount-- > 0)
{
val16 = *p8bit++;
val16 |= *p8bit << 8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -