- #include "includes.h" //包含所需的头文件
- /*************************************************************************************
- ** Function name: Set_System
- ** Descriptions: 封装一些初始化模块
- ** input parameters: count
- ** output parameters: 无
- ** Returned value: 无
- *************************************************************************************/
- void Set_System(void)
- {
- RCC_Configuration(); //配置系统时钟
- GPIO_Configuration(); //配置GPIO
- SPI_Configuration(); //配置SPI1
- }
- /*************************************************************************************
- ** Function name: RCC_Configuration
- ** Descriptions: 系统时钟设置,使用PLL输出50M
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void RCC_Configuration(void)
- {
- int32_t tmp;
- UNLOCKREG();
- DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); // 使能外部12M时钟源
- DrvSYS_SelectPLLSource(E_SYS_EXTERNAL_12M); //选择外部12M时钟源PLL
- DrvSYS_SetPLLMode(0); //PLL 正常模式
- tmp = DrvSYS_GetPLLContent(E_SYS_EXTERNAL_12M, 50000000); //设置PLL输出50M
- DrvSYS_SetPLLContent(tmp);
- DrvSYS_SelectHCLKSource(2); //0:12M;1:32K;2LL;
- tmp = DrvSYS_GetHCLKFreq(); //回读HCLK时钟频率
- LOCKREG();
- }
- /*************************************************************************************
- ** Function name: GPIO_Configuration
- ** Descriptions: GPIO配置
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void GPIO_Configuration()
- {
- DrvGPIO_Open( E_GPA, 13, E_IO_OUTPUT ); // SPI片选
- DrvGPIO_Open( E_GPA, 12, E_IO_OUTPUT ); // SPI复位
- DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT ); // LED灯控制
- }
- /*************************************************************************************
- ** Function name: SPI_Configuration
- ** Descriptions: SPI配置
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void SPI_Configuration()
- {
- uint32_t tmp;
- DrvSPI_Open(eDRVSPI_PORT1, eDRVSPI_MASTER, eDRVSPI_TYPE1, 8,FALSE);
- DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST); //配置SPI1传输比特的顺序:优先发送/接收MSB
- DrvSPI_DisableAutoSS(eDRVSPI_PORT1); //禁止自动片选功能
- DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING); //设定从选择线的激活级别:低电平或者下降沿
- DrvSPI_Set2BitTransferMode(eDRVSPI_PORT1, FALSE); //禁止2比特串行数据I/O 模式
- DrvSPI_SetClockFreq(eDRVSPI_PORT1, 8000000, 0); //设置SPI的时钟频率为8MHz
- tmp = DrvSPI_GetClock1Freq(eDRVSPI_PORT1);
- DISABLE_SPI_CS; //输出高电平
- }
- /*************************************************************************************
- ** Function name: delay_ms
- ** Descriptions: 1ms(晶振为12MHZ)延时子程序
- ** input parameters: count
- ** output parameters: 无
- ** Returned value: 无
- *************************************************************************************/
- void delay_ms(uint32_t count)
- {
- uint32_t i,j;
- for(i=count;i>0;i--)
- for(j=2395;j>0;j--);
- }
- /*************************************************************************************
- ** Function name: SPInet_ReadWrite
- ** Descriptions: SPI读写数据函数
- ** input parameters: 写入数据
- ** output parameters: 无
- ** Returned value: 读出数据
- *************************************************************************************/
- uint8_t SPInet_ReadWrite(uint8_t writedat)
- {
- uint32_t au32SourceData;
- uint32_t au32DestinationData;
- au32SourceData = writedat;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1);
- return (au32DestinationData);
- }
ENC28J60.C- #include "includes.h"
- static u8 Enc28j60Bank;
- static u16 NextPacketPtr;
- u8 enc28j60ReadOp(u8 op, u8 address)
- {
- u8 dat = 0;
- ENC28J60_CSL();
- dat = op | (address & ADDR_MASK);
- SPInet_ReadWrite(dat);
- dat = SPInet_ReadWrite(0x00);
- // do dummy read if needed (for mac and mii, see datasheet page 29)
- if (address & 0x80)
- {
- dat = SPInet_ReadWrite(0x00);
- }
- // release CS
- ENC28J60_CSH();
- return dat;
- }
- void enc28j60WriteOp(u8 op, u8 address, u8 data)
- {
- u8 dat = 0;
- ENC28J60_CSL();
- // issue write command
- dat = op | (address & ADDR_MASK);
- SPInet_ReadWrite(dat);
- // write data
- dat = data;
- SPInet_ReadWrite(dat);
- ENC28J60_CSH();
- }
- void enc28j60ReadBuffer(u16 len, u8* data)
- {
- ENC28J60_CSL();
- // issue read command
- SPInet_ReadWrite(ENC28J60_READ_BUF_MEM);
- while (len--)
- {
- *data++ = (u8) SPInet_ReadWrite(0);
- }
- *data = '\0';
- ENC28J60_CSH();
- }
- void enc28j60WriteBuffer(u16 len, u8* data)
- {
- ENC28J60_CSL();
- // issue write command
- SPInet_ReadWrite(ENC28J60_WRITE_BUF_MEM);
- while (len--)
- {
- SPInet_ReadWrite(*data++);
- }
- ENC28J60_CSH();
- }
- void enc28j60SetBank(u8 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);
- }
- }
- u8 enc28j60Read(u8 address)
- {
- // set the bank
- enc28j60SetBank(address);
- // do the read
- return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
- }
- void enc28j60Write(u8 address, u8 data)
- {
- // set the bank
- enc28j60SetBank(address);
- // do the write
- enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
- }
- void enc28j60PhyWrite(u8 address, u16 data)
- {
- // set the PHY register address
- enc28j60Write(MIREGADR, address);
- // write the PHY data
- enc28j60Write(MIWRL, data & 0x00ff);
- enc28j60Write(MIWRH, data >> 8);
- // wait until the PHY write completes
- while (enc28j60Read(MISTAT) & MISTAT_BUSY)
- {
- }
- }
- void enc28j60clkout(u8 clk)
- {
- enc28j60Write(ECOCON, clk & 0x7);
- }
- void enc28j60Init(u8 * macaddr)
- {
- unsigned char tmp=0;
- unsigned long i;
- ENC28J60_RSTL();
- delay_ms(1000);
- ENC28J60_RSTH();
- delay_ms(1000); //必须延迟一段时间
- // perform system reset
- enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
- // Del_1ms(250);
- // 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
- NextPacketPtr = 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 | MACON3_FULDPX);
- // 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
- enc28j60Write(MAADR5, macaddr[0]);
- enc28j60Write(MAADR4, macaddr[1]);
- enc28j60Write(MAADR3, macaddr[2]);
- enc28j60Write(MAADR2, macaddr[3]);
- enc28j60Write(MAADR1, macaddr[4]);
- enc28j60Write(MAADR0, macaddr[5]);
- // printf("MAADR5 = 0x%x\r\n", enc28j60Read(MAADR5));
- // printf("MAADR4 = 0x%x\r\n", enc28j60Read(MAADR4));
- // printf("MAADR3 = 0x%x\r\n", enc28j60Read(MAADR3));
- // printf("MAADR2 = 0x%x\r\n", enc28j60Read(MAADR2));
- // printf("MAADR1 = 0x%x\r\n", enc28j60Read(MAADR1));
- // printf("MAADR0 = 0x%x\r\n", enc28j60Read(MAADR0));
- enc28j60PhyWrite(PHCON1, PHCON1_PDPXMD);
- // no loopback of transmitted frames
- enc28j60PhyWrite(PHCON2, 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);
- }
- // read the revision of the chip:
- u8 enc28j60getrev(void)
- {
- return(enc28j60Read(EREVID));
- }
- void enc28j60PacketSend(u16 len, u8* packet)
- {
- // Set the write pointer to start of transmit buffer area
- enc28j60Write(EWRPTL, TXSTART_INIT & 0xFF);
- enc28j60Write(EWRPTH, TXSTART_INIT >> 8);
- // Set the TXND pointer to correspond to the packet size given
- enc28j60Write(ETXNDL, (TXSTART_INIT + len) & 0xFF);
- enc28j60Write(ETXNDH, (TXSTART_INIT + len) >> 8);
- // write per-packet control byte (0x00 means use macon3 settings)
- enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
- // copy the packet into the transmit buffer
- enc28j60WriteBuffer(len, packet);
- // send the contents of the transmit buffer onto the network
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
- // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
- if ((enc28j60Read(EIR) & EIR_TXERIF))
- {
- enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
- }
- }
- /*-----------------------------------------------------------------
- Gets a packet from the network receive buffer, if one is available.
- The packet will by headed by an ethernet header.
- maxlen The maximum acceptable length of a retrieved packet.
- packet Pointer where packet data should be stored.
- Returns: Packet length in bytes if a packet was retrieved, zero otherwise.
- -------------------------------------------------------------------*/
- u16 enc28j60PacketReceive(u16 maxlen, u8* packet)
- {
- u16 rxstat;
- u16 len;
- // check if a packet has been received and buffered
- //if( !(enc28j60Read(EIR) & EIR_PKTIF) ){
- // The above does not work. See Rev. B4 Silicon Errata point 6.
- if (enc28j60Read(EPKTCNT) == 0)
- {
- return(0);
- }
- // Set the read pointer to the start of the received packet
- enc28j60Write(ERDPTL, (NextPacketPtr));
- enc28j60Write(ERDPTH, (NextPacketPtr) >> 8);
- // read the next packet pointer
- NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
- // read the packet length (see datasheet page 43)
- len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
- len -= 4; //remove the CRC count
- // read the receive status (see datasheet page 43)
- rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
- // limit retrieve length
- if (len > maxlen - 1)
- {
- len = maxlen - 1;
- }
- // check CRC and symbol errors (see datasheet page 44, table 7-3):
- // The ERXFCON.CRCEN is set by default. Normally we should not
- // need to check this.
- if ((rxstat & 0x80) == 0)
- {
- // invalid
- len = 0;
- }
- else
- {
- // copy the packet from the receive buffer
- enc28j60ReadBuffer(len, packet);
- }
- // Move the RX read pointer to the start of the next received packet
- // This frees the memory we just read out
- enc28j60Write(ERXRDPTL, (NextPacketPtr));
- enc28j60Write(ERXRDPTH, (NextPacketPtr) >> 8);
- // decrement the packet counter indicate we are done with this packet
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
- return(len);
- }
main.c- /*---------------------------------------------------------------------------------------------------------*/
- /* */
- /* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
- /* */
- /*---------------------------------------------------------------------------------------------------------*/
- #include "includes.h" //包含所需的头文件
- /*************************************************************************************
- ** Function name: main
- ** Descriptions: 默认IP地址: 192. 168. 1.100
- ** input parameters: 无
- ** output parameters: 无
- ** Returned value: 无
- *************************************************************************************/
- int main (void)
- {
- unsigned char tmp = 0;
- Set_System(); //系统初始化
- simple_server(); //简单网页服务器
- }
现场图片:
电脑截图:
添加上工程文件: