我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 2453|回复: 5

单片机实现以太网传输程序

[复制链接]

该用户从未签到

19

主题

114

回帖

111

积分

二级逆天

积分
111

社区居民终身成就奖贴图大师奖金点子奖宣传大使奖灌水天才奖幽默大师奖新人进步奖

QQ
发表于 2014-7-7 22:53:41 | 显示全部楼层 |阅读模式
#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;
}
回复

使用道具 举报

  • TA的每日心情
    开心
    4 天前
  • 签到天数: 100 天

    [LV.6]常住居民II

    49

    主题

    1万

    回帖

    7万

    积分

    三级逆天

    积分
    73169

    终身成就奖特殊贡献奖原创先锋奖社区居民忠实会员社区劳模最爱沙发社区明星原创达人优秀斑竹奖宣传大使奖

    QQ
    发表于 2014-7-8 00:02:04 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    24

    主题

    1005

    回帖

    3998

    积分

    二级逆天

    积分
    3998

    社区居民新人进步奖灌水天才奖最爱沙发贴图大师奖幽默大师奖金点子奖终身成就奖宣传大使奖忠实会员

    QQ
    发表于 2014-7-8 07:59:58 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    472

    回帖

    745

    积分

    二级逆天

    积分
    745

    社区居民终身成就奖

    QQ
    发表于 2014-7-8 08:34:09 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    24

    主题

    2221

    回帖

    2832

    积分

    二级逆天

    积分
    2832

    社区居民忠实会员社区劳模最爱沙发优秀斑竹奖终身成就奖

    QQ
    发表于 2014-7-8 09:04:35 | 显示全部楼层
    广告位出租,价格可以商量。
    回复

    使用道具 举报

    该用户从未签到

    9

    主题

    3249

    回帖

    2671

    积分

    二级逆天

    孤独的奔跑者

    积分
    2671

    终身成就奖社区居民

    QQ
    发表于 2014-7-8 14:02:02 | 显示全部楼层
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    论坛开启做任务可以
    额外奖励金币快速赚
    积分升级了


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    平平安安
    TOP
    快速回复 返回顶部 返回列表