• 设为首页
  • 收藏本站
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    查看: 2457|回复: 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的每日心情
    开心
    2024-10-7 21:17
  • 签到天数: 103 天

    [LV.6]常住居民II

    49

    主题

    1万

    回帖

    7万

    积分

    三级逆天

    积分
    73180

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

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

    使用道具 举报

    该用户从未签到

    24

    主题

    1005

    回帖

    3998

    积分

    二级逆天

    积分
    3998

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

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

    使用道具 举报

    该用户从未签到

    1

    主题

    472

    回帖

    844

    积分

    二级逆天

    积分
    844

    社区居民终身成就奖

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

    使用道具 举报

    该用户从未签到

    24

    主题

    2224

    回帖

    3257

    积分

    二级逆天

    积分
    3257

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

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

    使用道具 举报

  • TA的每日心情
    开心
    2024-10-4 20:48
  • 签到天数: 1 天

    [LV.1]初来乍到

    9

    主题

    3251

    回帖

    2674

    积分

    二级逆天

    孤独的奔跑者

    积分
    2674

    终身成就奖社区居民

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

    使用道具 举报

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

    本版积分规则

    公告:服务器刚移机,
    大家请不要下载东西。
    会下载失败


    QQ 手机版 小黑屋 监管台 遇到问题请联系QQ1308068381 逆天PCB论坛

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表