📄 enc28j60.c
字号:
// enable MAC receive
ENC28J60Write(MACON1, MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN);
// Allow infinite deferals if the medium is continuously busy
// (do not time out a transmission if the half duplex medium is
// completely saturated with other people's data)
ENC28J60Write(MACON4, MACON4_DEFER);
// Set the maximum packet size which the controller will accept
// Do not send packets longer than MAX_FRAMELEN:
ENC28J60Write(MAMXFLL, LOW(MAX_FRAMELEN)); // 网络节点一般被设计为处理不大于1518 字节的数据包
ENC28J60Write(MAMXFLH, HIGH(MAX_FRAMELEN));
// set inter-frame gap (back-to-back)
ENC28J60Write(MABBIPG, 0x12);
// Set non-back-to-back inter-packet gap to 9.6us. The back-to-back
// inter-packet gap (MABBIPG) is set by MACSetDuplex() which is called
// later.
ENC28J60Write(MAIPGL, 0x12);
ENC28J60Write(MAIPGH, 0x0C);
// Late collisions occur beyond 63+8 bytes (8 bytes for preamble/start of frame delimiter)
// 55 is all that is needed for IEEE 802.3, but ENC28J60 B5 errata for improper link pulse
// collisions will occur less often with a larger number.
ENC28J60Write(MACLCON2, 100);
ENC28J60Write(MACLCON2, 63);
// do bank 3 stuff
// write MAC address
// NOTE: MAC address in ENC28J60 is byte-backward
// ENC28J60 is big-endian avr gcc is little-endian
ENC28J60Write(MAADR5, mac[0]);
ENC28J60Write(MAADR4, mac[1]);
ENC28J60Write(MAADR3, mac[2]);
ENC28J60Write(MAADR2, mac[3]);
ENC28J60Write(MAADR1, mac[4]);
ENC28J60Write(MAADR0, mac[5]);
temp.word = 0x0000; //
ENC28J60WritePhy(PHCON1, temp);
temp.word = PHCON2_HDLDIS; // no loopback of transmitted frames
ENC28J60WritePhy(PHCON2, temp);
// Magjack leds configuration, see enc28j60 datasheet, page 11
// 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
temp.word = 0x0122; // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 00 10);
ENC28J60WritePhy(PHLCON, temp);
// do bank 1 stuff, packet filter:
// For broadcast packets we allow only ARP packtets
// All other packets should be unicast only for our mac (MAADR)
// The pattern to match on is therefore
// Type ETH.DST
// ARP BROADCAST
// 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
// in binary these poitions are:11 0000 0011 1111
// This is hex 303F->EPMM0=0x3f,EPMM1=0x30
ENC28J60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
ENC28J60Write(EPMM0, 0x3f);
ENC28J60Write(EPMM1, 0x30);
ENC28J60Write(EPMCSL, 0xf9);
ENC28J60Write(EPMCSH, 0xf7);
ENC28J60WriteOp(ENC28J60_BIT_FIELD_SET,ECON1, ECON1_TXRTS | ECON1_RXEN);
if(0x0000==ENC28J60ReadPhy(PHCON1)&PHCON1_PDPXMD) // 从物理层判断模式
ENC28J60Write(MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); // enable automatic padding to 60bytes and CRC operations
else
ENC28J60Write(MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);
// switch to bank 0
ENC28J60SetBank(ECON1);
ENC28J60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_AUTOINC); //指针自动加一
ENC28J60WriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXIF);
// enable interrutps
ENC28J60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
// enable packet reception
ENC28J60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
VICIntEnable = 1 << 16; //初始化完毕,开启中断
}
/*******************************************************************************
*名称: ENC28J60PacketSend()
*功能: ENC28J60发送以太网包数据
*******************************************************************************/
u8_t IsTxReady(void)
{
return !(ENC28J60Read(ECON1)&ECON1_TXRTS);
}
void ENC28J60PacketSend ( u8_t *buffer, u16_t length )
{
//Set the write pointer to start of transmit buffer area
ENC28J60Write( ETXSTL, LOW(TXSTART_INIT));
ENC28J60Write( ETXSTH, HIGH(TXSTART_INIT));
ENC28J60Write( EWRPTL, LOW(TXSTART_INIT));
ENC28J60Write( EWRPTH, HIGH(TXSTART_INIT));
if(length > 1500)
{
length = 1500;
}
// Set the TXND pointer to correspond to the packet size given
ENC28J60Write( ETXNDL, LOW(TXSTART_INIT+length));
ENC28J60Write( ETXNDH, HIGH(TXSTART_INIT+length));
ENC28J60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x0F); //写控制字节
ENC28J60WriteBuf(buffer,length); // 写缓冲
//UART0_SendByte('L');
//UART0_SendByte(HexToAsc(length/1000));
//UART0_SendByte(HexToAsc((length%1000)/100));
//UART0_SendByte(HexToAsc((length%100)/10));
//UART0_SendByte(HexToAsc(length%10));
// 请求发送 send the contents of the transmit buffer onto the network
ENC28J60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
// 查看是否发送无错误 Reset the transmit logic problem.
if( (ENC28J60Read(EIR) & EIR_TXERIF) )
{
ENC28J60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
}
}
/*******************************************************************************
*名称: ENC28J60PacketReceive()
*功能: ENC28J60接收以太网包数据
*******************************************************************************/
u16_t ENC28J60PacketReceive ( u8_t *buffer, u16_t max_length )
{
WORD_BYTES rx_status, data_length;
// check if a packet has been received and buffered
if( ENC28J60Read(EPKTCNT) == 0 )
{
ENC28J60CheckRxPtr();
return 0;
}
// Set the read pointer to the start of the received packet
ENC28J60Write(ERDPTL, next_packet_ptr.bytes[0]);
ENC28J60Write(ERDPTH, next_packet_ptr.bytes[1]);
// read the next packet pointer
next_packet_ptr.bytes[0] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
next_packet_ptr.bytes[1] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
// read the packet length
data_length.bytes[0] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
data_length.bytes[1] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
data_length.word -=4; //remove the CRC count
// read the receive status
rx_status.bytes[0] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
rx_status.bytes[1] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
OS_ENTER_CRITICAL();
if ( data_length.word > (max_length-1) )
{
data_length.word = max_length-1;
}
// need to check this.
if ( (rx_status.word & 0x80)==0 ) // 接收成功,表示数据包具有有效的CRC,无符号错误。
{
data_length.word = 0; // invalid
}
else
{
// read data from rx buffer and save to rxtx_buffer
ENC28J60ReadBuf(buffer,data_length.word);
}
OS_EXIT_CRITICAL();
// Move the RX read pointer to the start of the next received packet
// 释放缓冲 This frees the memory we just read out
ENC28J60Write(ERXRDPTL, next_packet_ptr.bytes[0]);
ENC28J60Write(ERXRDPTH, next_packet_ptr.bytes[1]);
// decrement the packet counter indicate we are done with this packet
ENC28J60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
return data_length.word;
}
/*******************************************************************************
*名称: ENC28J60PacketReceive()
*功能: ENC28J60接收以太网包数据
*******************************************************************************/
u16_t ENC28J60PacketLength ( u16_t max_length )
{
WORD_BYTES data_length;
// read the packet length
data_length.bytes[0] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
data_length.bytes[1] = ENC28J60ReadOp(ENC28J60_READ_BUF_MEM, 0);
data_length.word -=4; //remove the CRC count
if ( data_length.word > (max_length-1) )
{
data_length.word = max_length-1;
}
return data_length.word;
}
/*******************************************************************************
*名称: ENC28J60CheckRxPtr()
*功能: ENC28J60检查接收指针
*******************************************************************************/
void ENC28J60CheckRxPtr ( void )
{
WORD_BYTES rxwr_ptr;
WORD_BYTES rxrd_ptr;
if( ENC28J60Read(EPKTCNT) == 0 )
{
rxwr_ptr.bytes[0] = ENC28J60Read(ERXWRPTL);
rxwr_ptr.bytes[1] = ENC28J60Read(ERXWRPTH);
rxrd_ptr.bytes[0] = ENC28J60Read(ERXRDPTL);
rxrd_ptr.bytes[1] = ENC28J60Read(ERXRDPTH);
if(rxwr_ptr.word != rxrd_ptr.word)
{
ENC28J60Write(ERDPTL, rxwr_ptr.bytes[0]);
ENC28J60Write(ERDPTH, rxwr_ptr.bytes[1]);
ENC28J60Write(ERXRDPTL, rxwr_ptr.bytes[0]);
ENC28J60Write(ERXRDPTH, rxwr_ptr.bytes[1]);
next_packet_ptr.bytes[0] = rxwr_ptr.bytes[0];
next_packet_ptr.bytes[1] = rxwr_ptr.bytes[1];
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -