enc28j60.c
来自「本附件为嵌入式Web的相关资料」· C语言 代码 · 共 1,923 行 · 第 1/4 页
C
1,923 行
MACGetArray(DataBuffer, ChunkLen);
len -= ChunkLen;
// Take care of a last odd numbered data byte
if(((WORD_VAL*)&ChunkLen)->bits.b0)
{
DataBuffer[ChunkLen] = 0x00;
ChunkLen++;
}
// Calculate the checksum over this chunk
DataPtr = (WORD*)&DataBuffer[0];
while(ChunkLen)
{
Checksum.Val += *DataPtr++;
ChunkLen -= 2;
}
}
// Restore old read pointer location
WriteReg(ERDPTL, Start.v[0]);
WriteReg(ERDPTH, Start.v[1]);
// Do an end-around carry (one's complement arrithmatic)
Checksum.Val = (DWORD)Checksum.w[0] + (DWORD)Checksum.w[1];
// Do another end-around carry in case if the prior add
// caused a carry out
Checksum.w[0] += Checksum.w[1];
// Return the resulting checksum
return ~Checksum.w[0];
}
/******************************************************************************
* Function: void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
*
* Input: destAddr: Destination address in the Ethernet memory to
* copy to. If the MSb is set, the current EWRPT
* value will be used instead.
* sourceAddr: Source address to read from. If the MSb is
* set, the current ERDPT value will be used
* instead.
* len: Number of bytes to copy
*
* Output: Byte read from the ENC28J60's RAM
*
* Side Effects: None
*
* Overview: Bytes are asynchrnously transfered within the buffer. Call
* MACIsMemCopyDone() to see when the transfer is complete.
*
* Note: If a prior transfer is already in progress prior to
* calling this function, this function will block until it
* can start this transfer.
*
* If a negative value is used for the sourceAddr or destAddr
* parameters, then that pointer will get updated with the
* next address after the read or write.
*****************************************************************************/
void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
{
WORD_VAL ReadSave, WriteSave;
BOOL UpdateWritePointer = FALSE;
BOOL UpdateReadPointer = FALSE;
if(((WORD_VAL*)&destAddr)->bits.b15)
{
UpdateWritePointer = TRUE;
((WORD_VAL*)&destAddr)->v[0] = ReadETHReg(EWRPTL).Val;
((WORD_VAL*)&destAddr)->v[1] = ReadETHReg(EWRPTH).Val;
}
if(((WORD_VAL*)&sourceAddr)->bits.b15)
{
UpdateReadPointer = TRUE;
((WORD_VAL*)&sourceAddr)->v[0] = ReadETHReg(ERDPTL).Val;
((WORD_VAL*)&sourceAddr)->v[1] = ReadETHReg(ERDPTH).Val;
}
// Handle special conditions where len == 0 or len == 1
// The DMA module is not capable of handling those corner cases
if(len <= 1u)
{
if(!UpdateReadPointer)
{
ReadSave.v[0] = ReadETHReg(ERDPTL).Val;
ReadSave.v[1] = ReadETHReg(ERDPTH).Val;
}
if(!UpdateWritePointer)
{
WriteSave.v[0] = ReadETHReg(EWRPTL).Val;
WriteSave.v[1] = ReadETHReg(EWRPTH).Val;
}
WriteReg(ERDPTL, ((WORD_VAL*)&sourceAddr)->v[0]);
WriteReg(ERDPTH, ((WORD_VAL*)&sourceAddr)->v[1]);
WriteReg(EWRPTL, ((WORD_VAL*)&destAddr)->v[0]);
WriteReg(EWRPTH, ((WORD_VAL*)&destAddr)->v[1]);
while(len--)
MACPut(MACGet());
if(!UpdateReadPointer)
{
WriteReg(ERDPTL, ReadSave.v[0]);
WriteReg(ERDPTH, ReadSave.v[1]);
}
if(!UpdateWritePointer)
{
WriteReg(EWRPTL, WriteSave.v[0]);
WriteReg(EWRPTH, WriteSave.v[1]);
}
}
else
{
if(UpdateWritePointer)
{
WriteSave.Val = destAddr + len;
WriteReg(EWRPTL, WriteSave.v[0]);
WriteReg(EWRPTH, WriteSave.v[1]);
}
len += sourceAddr - 1;
while(ReadETHReg(ECON1).ECON1bits.DMAST);
WriteReg(EDMASTL, ((WORD_VAL*)&sourceAddr)->v[0]);
WriteReg(EDMASTH, ((WORD_VAL*)&sourceAddr)->v[1]);
WriteReg(EDMADSTL, ((WORD_VAL*)&destAddr)->v[0]);
WriteReg(EDMADSTH, ((WORD_VAL*)&destAddr)->v[1]);
if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
len -= RXSIZE;
WriteReg(EDMANDL, ((WORD_VAL*)&len)->v[0]);
WriteReg(EDMANDH, ((WORD_VAL*)&len)->v[1]);
BFCReg(ECON1, ECON1_CSUMEN);
BFSReg(ECON1, ECON1_DMAST);
if(UpdateReadPointer)
{
len++;
if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
len -= RXSIZE;
WriteReg(ERDPTL, ((WORD_VAL*)&len)->v[0]);
WriteReg(ERDPTH, ((WORD_VAL*)&len)->v[1]);
}
}
}
BOOL MACIsMemCopyDone(void)
{
return !ReadETHReg(ECON1).ECON1bits.DMAST;
}
/******************************************************************************
* Function: BYTE MACGet()
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* ERDPT must point to the place to read from.
*
* Input: None
*
* Output: Byte read from the ENC28J60's RAM
*
* Side Effects: None
*
* Overview: MACGet returns the byte pointed to by ERDPT and
* increments ERDPT so MACGet() can be called again. The
* increment will follow the receive buffer wrapping boundary.
*
* Note: None
*****************************************************************************/
BYTE MACGet()
{
BYTE data;
ENC_CS_IO = 0;
data = ByteTransfer(RBM);
data = ByteTransfer(0);
ENC_CS_IO = 1;
return data;
}//end MACGet
/******************************************************************************
* Function: WORD MACGetArray(BYTE *val, WORD len)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* ERDPT must point to the place to read from.
*
* Input: *val: Pointer to storage location
* len: Number of bytes to read from the data buffer.
*
* Output: Byte(s) of data read from the data buffer.
*
* Side Effects: None
*
* Overview: Burst reads several sequential bytes from the data buffer
* and places them into local memory. With SPI burst support,
* it performs much faster than multiple MACGet() calls.
* ERDPT is incremented after each byte, following the same
* rules as MACGet().
*
* Note: None
*****************************************************************************/
WORD MACGetArray(BYTE *val, WORD len)
{
// Debug
#if defined(__18F8722) || \
defined(__18F8627) || \
defined(__18F8622) || \
defined(__18F8572) || \
defined(__18F6722) || \
defined(__18F6627) || \
defined(__18F6622) || \
defined(__18F6527)
WORD i;
BYTE Dummy;
i = len;
Dummy = 0xFF;
while(i--)
{
if(((BYTE_VAL*)&Dummy)->bits.b0)
{
// End bust operation
ENC_CS_IO = 1;
((BYTE_VAL*)&Dummy)->bits.b0 = 0;
// Start the burst operation
ENC_CS_IO = 0;
ByteTransfer(RBM);
}
else
Dummy = 0xFF;
*val++ = ByteTransfer(0);
}
ENC_CS_IO = 1;
return len;
#else
WORD i;
// Start the burst operation
ENC_CS_IO = 0;
ByteTransfer(RBM);
i = 0;
// Read the data
while(i<len)
{
*val++ = ByteTransfer(0);
i++;
};
// Terminate the burst operation
ENC_CS_IO = 1;
return i;
#endif
}//end MACGetArray
/******************************************************************************
* Function: void MACPut(BYTE val)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* EWRPT must point to the location to begin writing.
*
* Input: Byte to write into the ENC28J60 buffer memory
*
* Output: None
*
* Side Effects: None
*
* Overview: MACPut outputs the Write Buffer Memory opcode/constant
* (8 bits) and data to write (8 bits) over the SPI.
* EWRPT is incremented after the write.
*
* Note: None
*****************************************************************************/
void MACPut(BYTE val)
{
ENC_CS_IO = 0;
ByteTransfer(WBM);
ByteTransfer(val);
ENC_CS_IO = 1;
}//end MACPut
/******************************************************************************
* Function: void MACPutArray(BYTE *val, WORD len)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* EWRPT must point to the location to begin writing.
*
* Input: *val: Pointer to source of bytes to copy.
* len: Number of bytes to write to the data buffer.
*
* Output: None
*
* Side Effects: None
*
* Overview: MACPutArray writes several sequential bytes to the
* ENC28J60 RAM. It performs faster than multiple MACPut()
* calls. EWRPT is incremented by len.
*
* Note: None
*****************************************************************************/
void MACPutArray(BYTE *val, WORD len)
{
// Debug
#if defined(__18F8722) || \
defined(__18F8627) || \
defined(__18F8622) || \
defined(__18F8572) || \
defined(__18F6722) || \
defined(__18F6627) || \
defined(__18F6622) || \
defined(__18F6527)
WORD i;
BYTE Dummy;
i = len;
Dummy = 0xFF;
while(i--)
{
if(((BYTE_VAL*)&Dummy)->bits.b0)
{
// End bust operation
ENC_CS_IO = 1;
((BYTE_VAL*)&Dummy)->bits.b0 = 0;
// Start the burst operation
ENC_CS_IO = 0;
ByteTransfer(WBM);
}
else
Dummy = 0xFF;
ByteTransfer(*val++);
}
ENC_SPI_IF = 0;
ENC_CS_IO = 1;
return;
#else
// Select the chip and send the proper opcode
ENC_CS_IO = 0;
ByteTransfer(WBM);
// Send the data
while(len)
{
ByteTransfer(*val++);
len--; // Decrement after writing to ENC_SSPBUF to increase speed
};
// Terminate the burst operation
ENC_CS_IO = 1;
#endif
}//end MACPutArray
/******************************************************************************
* Function: static void SendSystemReset(void)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: SendSystemReset sends the System Reset SPI command to
* the Ethernet controller. It resets all register contents
* (except for ECOCON) and returns the device to the power
* on default state.
*
* Note: None
*****************************************************************************/
static void SendSystemReset(void)
{
ENC_CS_IO = 0;
ByteTransfer(SR);
ENC_CS_IO = 1;
}//end SendSystemReset
/******************************************************************************
* Function: REG ReadETHReg(BYTE Address)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* Bank select bits must be set corresponding to the register
* to read from.
*
* Input: 5 bit address of the ETH control register to read from.
* The top 3 bits must be 0.
*
* Output: Byte read from the Ethernet controller's ETH register.
*
* Side Effects: None
*
* Overview: ReadETHReg sends the 8 bit RCR opcode/Address byte over
* the SPI and then retrives the register contents in the
* next 8 SPI clocks.
*
* Note: This routine cannot be used to access MAC/MII or PHY
* registers. Use ReadMACReg() or ReadPHYReg() for that
* purpose.
*****************************************************************************/
static REG ReadETHReg(BYTE Address)
{
REG r;
// Select the chip and send the Read Control Register opcode/address
ENC_CS_IO = 0;
ByteTransfer(RCR | Address);
r.Val = ByteTransfer(0);
ENC_CS_IO = 1;
return r;
}//end ReadETHReg
/******************************************************************************
* Function: REG ReadMACReg(BYTE Address)
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
* Bank select bits must be set corresponding to the register
* to read from.
*
* Input: 5 bit address of the MAC or MII register to read from.
* The top 3 bits must be 0.
*
* Output: Byte read from the Ethernet controller's MAC/MII register.
*
* Side Effects: None
*
* Overview: ReadMACReg sends the 8 bit RCR opcode/Address byte as well
* as a dummy byte over the SPI and then retrives the
* register contents in the last 8 SPI clocks.
*
* Note: This routine cannot be used to access ETH or PHY
* registers. Use ReadETHReg() or ReadPHYReg() for that
* purpose.
*****************************************************************************/
static REG ReadMACReg(BYTE Address)
{
REG r;
ENC_CS_IO = 0;
ByteTransfer(RCR | Address);
ByteTransfer(0);
r.Val = ByteTransfer(0);
ENC_CS_IO = 1;
return r;
}//end ReadMACReg
/******************************************************************************
* Function: ReadPHYReg
*
* PreCondition: SPI bus must be initialized (done in MACInit()).
*
* Input: Address of the PHY register to read from.
*
* Output: 16 bits of data read from the PHY register.
*
* Side Effects: None
*
* Overview: ReadPHYReg performs an MII read operation. While in
* progress, it simply polls the MII BUSY bit wasting time
* (10.24us).
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?