?? enc28j60.c
字號:
//********************************************************************************************
//
// File : enc28j60.c Microchip ENC28J60 Ethernet Interface Driver
//
//********************************************************************************************
//
// Copyright (C) 2007
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
// This program is distributed in the hope that it will be useful, but
//
// WITHOUT ANY WARRANTY;
//
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin St, Fifth Floor, Boston, MA 02110, USA
//
// http://www.gnu.de/gpl-ger.html
//
//********************************************************************************************#include "includes.h"////#define F_CPU 8000000UL // 8 MHz//struct enc28j60_flag
//{
// unsigned rx_buffer_is_free:1;
// unsigned unuse:7;
//}enc28j60_flag;static BYTE Enc28j60Bank;static WORD_BYTES next_packet_ptr;
//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************BYTE enc28j60ReadOp(BYTE op, BYTE address){
// activate CS CSACTIVE; // issue read command SPDR = op | (address & ADDR_MASK); waitspi(); // read data SPDR = 0x00; waitspi(); // do dummy read if needed (for mac and mii, see datasheet page 29) if(address & 0x80) { SPDR = 0x00; waitspi(); } // release CS CSPASSIVE; return(SPDR);}//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************void enc28j60WriteOp(BYTE op, BYTE address, BYTE data){ CSACTIVE; // issue write command SPDR = op | (address & ADDR_MASK); waitspi(); // write data SPDR = data; waitspi(); CSPASSIVE;}//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************void enc28j60SetBank(BYTE address){ // set the bank (if needed) if((address & BANK_MASK) != Enc28j60Bank) { // set the bank enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); Enc28j60Bank = (address & BANK_MASK); }}//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************BYTE enc28j60Read(BYTE address){ // select bank to read enc28j60SetBank(address);
// do the read return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);}//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************void enc28j60Write(BYTE address, BYTE data){ // select bank to write enc28j60SetBank(address);
// do the write enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);}
//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************
WORD enc28j60_read_phyreg(BYTE address)
{
WORD data;
// set the PHY register address enc28j60Write(MIREGADR, address);
enc28j60Write(MICMD, MICMD_MIIRD);
// Loop to wait until the PHY register has been read through the MII
// This requires 10.24us
while( (enc28j60Read(MISTAT) & MISTAT_BUSY) );
// Stop reading
enc28j60Write(MICMD, MICMD_MIIRD);
// Obtain results and return
data = enc28j60Read ( MIRDL );
data |= enc28j60Read ( MIRDH );
return data;
}//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************void enc28j60PhyWrite(BYTE address, WORD_BYTES data){ // set the PHY register address enc28j60Write(MIREGADR, address); // write the PHY data enc28j60Write(MIWRL, data.byte.low); enc28j60Write(MIWRH, data.byte.high); // wait until the PHY write completes while(enc28j60Read(MISTAT) & MISTAT_BUSY)
{ _delay_us(15); }}//*******************************************************************************************
//
// Function : icmp_send_request
// Description : Send ARP request packet to destination.
//
//*******************************************************************************************
/*
void enc28j60_init( BYTE *avr_mac)
{
// initialize I/O
//DDRB |= _BV( DDB4 );
//CSPASSIVE;
// enable PB0, reset as output /
ENC28J60_DDR |= _BV(ENC28J60_RESET_PIN_DDR);
// enable PD2/INT0, as input /
ENC28J60_DDR &= ~_BV(ENC28J60_INT_PIN_DDR);
// set output to gnd, reset the ethernet chip /
ENC28J60_PORT &= ~_BV(ENC28J60_RESET_PIN);
_delay_ms(10);
// set output to Vcc, reset inactive /
ENC28J60_PORT |= _BV(ENC28J60_RESET_PIN);
_delay_ms(200);
//initialize enc28j60/
//enc28j60Init( avr_mac );
//_delay_ms( 20 );
DDRB |= _BV( DDB4 ) | _BV( DDB5 ) | _BV( DDB7 ); // mosi, sck, ss output
//DDRB &= ~_BV( DDB6 ); // MISO is input
CSPASSIVE;
PORTB &= ~(_BV( PB5 ) | _BV( PB7 ) );
// initialize SPI interface
// master mode and Fosc/2 clock:
SPCR = _BV( SPE ) | _BV( MSTR );
SPSR |= _BV( SPI2X );
// perform system reset
enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
_delay_ms(50);
// check CLKRDY bit to see if reset is complete
// The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
//while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
// do bank 0 stuff
// initialize receive buffer
// 16-bit transfers, must write low byte first
// set receive buffer start address
next_packet_ptr.word = RXSTART_INIT;
// Rx start
enc28j60Write(ERXSTL, RXSTART_INIT&0xFF); enc28j60Write(ERXSTH, RXSTART_INIT>>8); // set receive pointer address enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF); enc28j60Write(ERXRDPTH, RXSTART_INIT>>8); // RX end enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF); enc28j60Write(ERXNDH, RXSTOP_INIT>>8); // TX start enc28j60Write(ETXSTL, TXSTART_INIT&0xFF); enc28j60Write(ETXSTH, TXSTART_INIT>>8); // TX end enc28j60Write(ETXNDL, TXSTOP_INIT&0xFF); enc28j60Write(ETXNDH, TXSTOP_INIT>>8);
// 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);
// do bank 2 stuff
// enable MAC receive
enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
// bring MAC out of reset
//enc28j60Write(MACON2, 0x00);
// enable automatic padding to 60bytes and CRC operations
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
// set inter-frame gap (non-back-to-back)
enc28j60Write(MAIPGL, 0x12);
enc28j60Write(MAIPGH, 0x0C);
// set inter-frame gap (back-to-back)
enc28j60Write(MABBIPG, 0x12);
// Set the maximum packet size which the controller will accept
// Do not send packets longer than MAX_FRAMELEN:
enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);
enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);
// 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, avr_mac[0]); enc28j60Write(MAADR4, avr_mac[1]); enc28j60Write(MAADR3, avr_mac[2]); enc28j60Write(MAADR2, avr_mac[3]); enc28j60Write(MAADR1, avr_mac[4]); enc28j60Write(MAADR0, avr_mac[5]);
// no loopback of transmitted frames
enc28j60PhyWrite(PHCON2, (WORD_BYTES){PHCON2_HDLDIS});
// switch to bank 0
enc28j60SetBank(ECON1);
// enable interrutps
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
// enable packet reception
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
// Magjack leds configuration, see enc28j60 datasheet, page 11 /
// LEDB=yellow LEDA=green
//
// 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -