⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 etherdev.c

📁 单片机数据通讯典型应用(光盘内容)
💻 C
字号:



#include "etherdev.h"

/***************************基本宏定义***********************************/
#define ETH_CPU_CLOCK      ETH_CPU_XTAL / 12    // 8051 clock rate (X1 mode)

// Delay routine timing parameters
#define ETH_DELAY_CONST    9.114584e-5          // Delay routine constant
#define ETH_DELAY_MULTPLR  (unsigned char)(ETH_DELAY_CONST * ETH_CPU_CLOCK)

// X1 CPU mode timing parameters
#define ETH_T0_CLOCK             ETH_CPU_XTAL / 12 // Timer 0 mode 1 clock rate
#define ETH_T0_INT_RATE          24                // Timer 0 intrupt rate (Hz)
#define ETH_T0_RELOAD            65536 - (ETH_T0_CLOCK / ETH_T0_INT_RATE)

// Packet transmit & receive buffer configuration
#define ETH_TX_PAGE_START  0x40    // 0x4000 Tx buffer is  6 * 256 = 1536 bytes
#define ETH_RX_PAGE_START  0x46    // 0x4600 Rx buffer is 26 * 256 = 6656 bytes
#define ETH_RX_PAGE_STOP   0x60    // 0x6000

#define ETH_ADDR_PORT_MASK 0x0F                 // 00001111y
#define ETH_DATA_PORT_MASK 0xFF                 // 11111111y

#define ETH_MIN_PACKET_LEN 0x3C


/************************私有函数*****************************/
static void etherdev_reg_write(unsigned short reg, unsigned short wr_data);
static unsigned short etherdev_reg_read(unsigned short reg);
static void etherdev_delay_ms(unsigned int count);
static unsigned int etherdev_poll(void);
static void cs8900_reset (void);
static void cs8900_reginit (void);
//static void etherdev_timer0_isr(void) interrupt 1 using 1;


/***********************全局变量********************************/
static unsigned char tick_count = 0;


/*************CS8900A寄存器写函数 I/O空间模式********************************/
static void etherdev_reg_write(unsigned short regno, unsigned short wr_data)
{

	unsigned char regnol,regnoh,pdatah;    unsigned short pdatal;
    //写寄存器低八位地址    regnol=regno&0xff;		  
    ETH_ADDR_PORT= CS8900_PPTRL;
	IOW = 0;
	ETH_DATA_PORT= regnol;
	IOW = 1;	//写寄存器高八位地址	regnoh=regno>>8;
	ETH_ADDR_PORT= CS8900_PPTRH;
	IOW = 0;
	ETH_DATA_PORT= regnoh;
	IOW = 1;
	//写低八位数据	pdatal=wr_data&0xff;
	ETH_ADDR_PORT= CS8900_PDATAL;
	IOW = 0;
	ETH_DATA_PORT= pdatal;
	IOW = 1;
	//写高八位数据    pdatah=wr_data>>8;
	ETH_ADDR_PORT= CS8900_PDATAH;
	IOW = 0;    ETH_DATA_PORT= pdatah;	  
	IOW = 1;
		
	ETH_DATA_PORT = ETH_DATA_PORT_MASK;
    return;	  
	
	

} 

/***********************CS8900A寄存器读函数  I/O空间模式******************/
static unsigned short etherdev_reg_read(unsigned short regno)
{
    unsigned char regnol,regnoh;    unsigned short pdatal,pdatah,ppdata;
	//写寄存器低八位地址
	regnol=regno&0xff;		  
    ETH_ADDR_PORT= CS8900_PPTRL;
	IOW = 0;
	ETH_DATA_PORT= regnol;
	IOW = 1;	//写寄存器高八位地址	regnoh=regno>>8;
	ETH_ADDR_PORT= CS8900_PPTRH;
	IOW = 0;
	ETH_DATA_PORT= regnoh;
	IOW = 1;
    //读寄存器低八位数据
	ETH_ADDR_PORT= CS8900_PDATAL;
	IOR = 0;	pdatal=ETH_DATA_PORT;
	IOR = 1;
	//读寄存器高八位数据
	ETH_ADDR_PORT= CS8900_PDATAH;
	IOR = 0;	pdatah=ETH_DATA_PORT;
	IOR = 1;
	ppdata=(pdatah<<8)|pdatal;

	ETH_DATA_PORT = ETH_DATA_PORT_MASK;	return (unsigned short) ppdata;

} 


/*************延时函数**********************************/
static void etherdev_delay_ms(unsigned int count)
{

    for(count *= ETH_DELAY_MULTPLR; count > 0; count--) continue;

    return;
}


/*************************定时器0****************************/
static void etherdev_timer0_isr(void) interrupt 1 using 1
{
    // Reload timer/ counter 0 for 24Hz periodic interrupt.   
    TH0 = ETH_T0_RELOAD >> 8;
    TL0 = ETH_T0_RELOAD;

    // Increment 24ths of a second counter.
    tick_count++;

    return;
}
/****************************CS8900A***********************/
static void cs8900_reset (void){	unsigned short us;	//网卡重启	etherdev_reg_write (PP_SelfCTL, etherdev_reg_read (PP_SelfCTL) |0x0040);	//延时200ms 	etherdev_delay_ms (200000);	//等待网卡重启结束    while (((us = etherdev_reg_read (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0)
       /* NOP*/;
}/***************寄存器初始化**************************************/
 static void cs8900_reginit (void)
{
	//初始化RxCTL寄存器
	etherdev_reg_write (PP_RxCTL, 0x1c00);
	//初始化RxCFG寄存器	
    etherdev_reg_write (PP_RxCFG, 0);
	//初始化TxCFG寄存器	
    etherdev_reg_write (PP_TxCFG, 0);
	//初始化BufCFG寄存器	
    etherdev_reg_write (PP_BufCFG, 0);
	//初始化RxCTL寄存器,允许接收和发送数据帧	
    etherdev_reg_write (PP_LineCTL, 0x00c0);
}

/**************公用函数接口******************************************/

/***************CS8900A初始化 返回值 1 成功 返回值0 失败************/
bit etherdev_init(void)
{
    // Set IOR & IOW as they're active low.
    IOR = 1;
    IOW = 1;

    // Set register data port as input.
    ETH_DATA_PORT = ETH_DATA_PORT_MASK;

#ifdef ETH_DEBUG
    init_sio_poll();
#endif /* ETH_DEBUG */

  	//验证网卡ID
	if (etherdev_reg_read (PP_ChipID) != 0x630e) {
		return 0;
	}
    //网卡重启
	cs8900_reset ();
	//写入网卡MAC地址
	etherdev_reg_write (PP_IA + 0, UIP_ETHADDR0 | (UIP_ETHADDR1 << 8));
	etherdev_reg_write (PP_IA + 2, UIP_ETHADDR2 | (UIP_ETHADDR3 << 8));
	etherdev_reg_write (PP_IA + 4, UIP_ETHADDR4 | (UIP_ETHADDR5 << 8));
    //初始化寄存器
	cs8900_reginit ();

    // Initialize Timer 0 to generate a periodic 24Hz interrupt. 

    // Stop timer/ counter 0.                                         
    TR0  = 0;          

    // Set timer/ counter 0 as mode 1 16 bit timer.      
    TMOD &= 0xF0;
    TMOD |= 0x01;

    // Preload for 24Hz periodic interrupt.    
    TH0 = ETH_T0_RELOAD >> 8; 
    TL0 = ETH_T0_RELOAD;

    // Restart timer/ counter 0 running.
    TR0 = 1;

    // Enable timer/ counter 0 overflow interrupt.            
    ET0 = 1;

    // Enable global interrupt.
    EA = 1;

    return 1;
}


/********************数据包发送函数************************************/
void etherdev_send(void)
{
    unsigned int i;
    unsigned char *ptr;
	unsigned short s;
    ptr = uip_buf;

 retry:
	 //写发送命令低八位  
	 ETH_ADDR_PORT= CS8900_TxCMDL;
	 IOW = 0;
	 ETH_DATA_PORT= 0xC0;
	 IOW = 1;
	 //写发送命令高八位
	 ETH_ADDR_PORT= CS8900_TxCMDH;
	 IOW = 0;
	 ETH_DATA_PORT= 0x00;
	 IOW = 1;
	 		
	 //写发送帧长度低八位  
	 ETH_ADDR_PORT= CS8900_TxLENL;
	 IOW = 0;
	 ETH_DATA_PORT= uip_len&0xff;
	 IOW = 1;
	 //写发送帧长度高八位
	 ETH_ADDR_PORT= CS8900_TxLENH;
	 IOW = 0;
	 ETH_DATA_PORT= uip_len>>8;
	 IOW = 1;
	if ((etherdev_reg_read (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {
	    
		etherdev_delay_ms (200000);
		cs8900_reset ();
		cs8900_reginit ();
		goto retry;
	}


    for(i = 0; i < uip_len; i++)
    {
        if(i == 40 + UIP_LLH_LEN) 
        {
            ptr = (unsigned char *)uip_appdata;
        }

		if(i%2==0)
		{
	       ETH_ADDR_PORT= CS8900_RTDATAL;
	       IOW = 0;
	       ETH_DATA_PORT= *ptr++;
	       IOW = 1;			
		}
		else
		{
		   ETH_ADDR_PORT= CS8900_RTDATAH;
	       IOW = 0;
	       ETH_DATA_PORT= *ptr++;
	       IOW = 1;					
		}
    }

    // 等待发送完成
	while ((s = etherdev_reg_read (PP_TER) & ~0x1F) == 0) continue;

    return;
}


/*************************数据包接收函数**************************/
unsigned int etherdev_read(void)
{    
    unsigned int bytes_read;

    /* tick_count threshold should be 12 for 0.5 sec bail-out
       One second (24) worked better for me, but socket recycling
       is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h
       to counter this. Retransmission timing etc. is affected also. */
    while ((!(bytes_read = etherdev_poll())) && (tick_count < 12)) continue;

    tick_count = 0;

    return bytes_read;
}


/*****************CS8900A接受合法数据包*************************/
static unsigned int etherdev_poll(void)
{
    unsigned int len = 0,i;
	unsigned short status,statusl,statush,rxlenl,rxlenh;

	status = etherdev_reg_read (PP_RER);
	if ((status & PP_RER_RxOK) == 0)//读取Receive Event寄存器,RxOk==0?
		return 0;                   //没有数据帧接收,返回
    //读取接收帧状态低八位
   	ETH_ADDR_PORT= CS8900_RTDATAL;
	IOW = 0;
	statusl=ETH_DATA_PORT;
	IOW = 1;			
    //读取接收帧状态高八位
	ETH_ADDR_PORT= CS8900_RTDATAH;
	IOW = 0;
	statush=ETH_DATA_PORT;
	IOW = 1;
    status=(statusl<<8)|statush;

	//读取帧长度低八位
   	ETH_ADDR_PORT= CS8900_RTDATAL;
	IOW = 0;
	rxlenl=ETH_DATA_PORT;
	IOW = 1;			
    //读取帧长度高八位
	ETH_ADDR_PORT= CS8900_RTDATAH;
	IOW = 0;
	rxlenh=ETH_DATA_PORT;
	IOW = 1;
    len=(rxlenh<<8)|rxlenl;//读取帧长度
	if(len>UIP_BUFSIZE)
	   return 0;
          
    for(i = 0; i < len; i++)
    {
		if(i%2==0)
		{
	       ETH_ADDR_PORT= CS8900_RTDATAL;
	       IOW = 0;
	       *(uip_buf + i)= ETH_DATA_PORT;
	       IOW = 1;			
		}
		else
		{
		   ETH_ADDR_PORT= CS8900_RTDATAH;
	       IOW = 0;
	       *(uip_buf + i)= ETH_DATA_PORT;
	       IOW = 1;					
		}
    }

    return len;
}








⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -