导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→老古,帮忙看看这个udp发送程序啊

* 54231: 老古,帮忙看看这个udp发送程序啊

   wsfeitian 
wsfeitian发表的帖子 

 老古,帮忙看看这个udp发送程序啊
电路参考您的一体化电路,去掉了串口,在P2口接一个液晶显示器.cpu用89s52.

以下仅仅是实现8019发udp数据程序,不用arp协议.

typedef struct
{
  unsigned char dest_hwaddr[6];
  unsigned char source_hwaddr[6];
  unsigned  int  frame_type;
} ETH_HEADER;


typedef struct
{
   unsigned char ver_len;
   unsigned char type_of_service;
   unsigned  int  total_length;
   unsigned  int  identifier;
   unsigned  int  fragment_info;
   unsigned char time_to_live;
   unsigned char protocol_id;
   unsigned  int  header_cksum;
   unsigned  long source_ipaddr;
   unsigned  long dest_ipaddr;
} IP_HEADER;

typedef struct 
{
   unsigned  int  source_port;
   unsigned  int  dest_port;
   unsigned  int  length;
   unsigned  int  checksum;
 unsigned char msg_data;
} UDP_HEADER;


sbit reset=P3^4;

#define reg00   XBYTE[0xc000]   //reg00- 10为isa网卡接口的寄存器地址240-25fh;
#define reg01   XBYTE[0xc100]
#define reg02   XBYTE[0xc200]
#define reg03   XBYTE[0xc300]
#define reg04   XBYTE[0xc400]
#define reg05   XBYTE[0xc500]
#define reg06   XBYTE[0xc600]
#define reg07   XBYTE[0xc700]
#define reg08   XBYTE[0xc800]
#define reg09   XBYTE[0xc900]
#define reg0a   XBYTE[0xca00]
#define reg0b   XBYTE[0xcb00]
#define reg0c   XBYTE[0xcc00]
#define reg0d   XBYTE[0xcd00]
#define reg0e   XBYTE[0xce00]
#define reg0f   XBYTE[0xcf00]
#define reg10   XBYTE[0xd000]
#define reg1f   XBYTE[0xdf00]

/******************************设置网卡地址***********************/

void ReadRtl8019NodeID(void)
{
}

void WriteRtl8019NodeID(void)  //直接设置本机物理地址
{
 page(1);
 reg01=0x00;
 reg02=0x01;
 reg03=0x02;
 reg04=0x03;
 reg05=0x04;
 reg06=0x05;
 page(0);

}

void rtl8019as_rst() //复位网卡
{
        uchar temp;
 reset=1;   
 delay_ms(800);
 reset=0;
 delay_ms(800);
}

/************8019初始化*******************/
void page(unsigned char pagenumber)//选择页面
{
 unsigned char data temp;
 temp=reg00;  
 temp=temp&0x3B ;
 pagenumber=pagenumber   <  <6;
 temp=temp | pagenumber;
 reg00=temp;
}


void init_8019(void)
{
 delay_ms(10);
 rtl8019as_rst();  //复位8019
// R8019_CHIP_SELECT;
 reg00=0x21;    //使芯片处于停止模式,这时进行寄存器设置 停止模式下,将不会发送和接收数据包
 delay_ms(10);   //延时10毫秒,确保芯片进入停止模式
 page(0);
 reg0a=0x00; 
 reg0b=0x00;
 reg0c=0xe0;        //RCR 
 reg0d=0xe2;   //loop back mode 使芯片处于mon和loopback模式,跟外部网络断开 

//使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。
//使用0x4c-0x7f为网卡的接收缓冲区,共52页?
 reg01=0x4C; //Pstart  接收缓冲区范围
 reg02=0x80; //Pstop    接收缓冲区尾地址

 reg04=0x40; //TPSR    发送缓冲区范围

 reg03=0x4C; //BNRY  指向最后一个已经读取的页(读指针)
             //刚开始,网卡没有接收到任何数据包,所以,BNRY设置为指向第一个接收缓冲区的页0x4c)
 

 reg07=0xff;    //清除所有中断标志位
 reg0f=0x00;    //disable all interrupt
 reg0e=0xc8;    //byte dma 8位dma方式

 page(1); //选择页1的寄存器
 reg07=0x4D; //CURR  CURR 当前的接收结束页地址。(写指针)
 reg08=0x00; //MAR0 设置多点播送的参数
 reg09=0x41; //MAR1
 reg0a=0x00; //MAR2
 reg0b=0x80; //MAR3
 reg0c=0x00; //MAR4
 reg0d=0x00; //MAR5
 reg0e=0x00; //MAR6
 reg0f=0x00; //MAR7 

 reg00=0x22;    //这时让芯片开始工作
 ReadRtl8019NodeID(); //读出网卡的物理地址48位  
 WriteRtl8019NodeID(); //将网卡地址写入到mar寄存器 
 
//将网卡设置成正常的模式,跟外部网络连接
 page(0);
 reg0c=0xcc; //RCR       接收配置寄存器,设置为使用接收缓冲区,仅接收自己的地址的数据包(以及广播地址数据包)和多点播送地址包,小于64字节的包丢弃(这是协议的规定,设置成接收是用于网络分析),校验错的数据包不接收
 reg0d=0xe0; //TCR       发送配置寄存器,启用crc自动生成和自动校验,工作在正常模式
 reg00=0x22;    //这时让芯片开始工作
 reg07=0xff;    //清除所有中断标志位
}

/************udp***************/
static ulong code my_ipaddr=0xC0A8000A;//设置ip为192.168.0.10
static uint xdata sender_udpport=1025;//发送端口为1025
static ulong xdata sender_ipaddr=0xCAC1318C;//pc机ip为202.193.49.140

void udp_send(uchar xdata *inbuf, uint port, uint len)
{   
    
 unsigned long idata sum;
   unsigned int idata result;
   unsigned char xdata * outbuf;
   UDP_HEADER xdata * udp;
    IP_HEADER xdata * ip;

 
   // Allocate memory for entire outgoing message including
   // eth & IP headers. Total ethernet message length is:
   // 14 byte eth header + 20 byte IP header + 8 byte UDP header
   // + length of this data 
   outbuf = (uchar xdata *)malloc(42 + len);//malloc返回为一个(42+len)大小对象所分配的内存指针.如果返回
                                           
   
   udp = (UDP_HEADER xdata *)(outbuf + 34);
   ip = (IP_HEADER xdata *)(outbuf + 14);
   
   // Direct message back to the senders port. 
 udp->  dest_port = sender_udpport;
 udp->  source_port = port;
 udp->  length = 8 + len;
 udp->  checksum = 0;
  
 // Fill in data
   // Important do not free receive buffer prior to this
   memcpy(&udp->  msg_data, (inbuf + 42), len); 
 
 
 // Compute checksum including 12 bytes of pseudoheader
 // Must pre-fill 2 items in outbuf to do this
 // Direct message back to senders ip address
 ip->  dest_ipaddr = sender_ipaddr;
 ip->  source_ipaddr = my_ipaddr;
  
 
 // Sum source_ipaddr, dest_ipaddr, and entire UDP message 
 sum = (ulong)cksum(outbuf + 26, 8 + udp->  length);
   
 // Add in the rest of pseudoheader which is
 // zero, protocol id, and UDP length
 sum += (ulong)0x0011;
 sum += (ulong)udp->  length;

 // In case there was a carry, add it back around
 result = (uint)(sum + (sum >  >   16));
 udp->  checksum = ~result;
 
 ip_send(outbuf, sender_ipaddr, UDP_TYPE, udp->  length);
}

/************ip*****************/


void ip_send(uchar xdata * outbuf, ulong ipaddr, uchar proto_id, uint len)
{
   IP_HEADER xdata * ip;
   uchar xdata * hwaddr;
   static uint ip_ident = 0;
   
   ip = (IP_HEADER xdata *)(outbuf + 14);
   ip->  ver_len = 0x45;          // IPv4 with 20 byte header
   ip->  type_of_service = 0;
   ip->  total_length = 20 + len;
   ip->  identifier = ip_ident++;     // sequential identifier
   ip->  fragment_info = 0;           // not fragmented
   ip->  time_to_live = 32;           // max hops
   ip->  protocol_id = proto_id;      // type of payload
   ip->  header_cksum = 0;
   ip->  source_ipaddr = my_ipaddr;
   
   // Outgoing IP address
   ip->  dest_ipaddr = ipaddr;

   // Compute and insert complement of checksum of ip header
   // Outgoing ip header length is always 20 bytes
   ip->  header_cksum = ~cksum(outbuf + 14, 20);
   
   // Use ARP to get hardware address to send this to
   hwaddr = ("0x52","0x54","0xAB","0x4F","0x5E","0x9F");
 
 // Null means that the ARP resolver did not find the IP address
 // in its cache so had to send an ARP request
 if (hwaddr == NULL)
 {
  // Fill in the destination information so ehrn the ARP response
  // arrives we can identify it and know what to do when we get it
      wait.buf = outbuf;
  wait.ipaddr = ip->  dest_ipaddr;
  wait.proto_id = proto_id;
  wait.len = len;
  wait.timer = ARP_TIMEOUT; 
      return;
 } 
 
 eth_send(outbuf, hwaddr, IP_PACKET, 20 + len);
}

/**************EHER******************/

bit txd_buffer_select=0;
extern uchar code my_hwaddr[6]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; 

void send_frame(uchar xdata * outbuf, uint len)/*发送一个数据包的命令,长度最小为60字节,最大1514字节*/
{
uchar i;
uint ii;
 page(0);
 if(len  <60)len=60;
 txd_buffer_select=!txd_buffer_select;
   if (txd_buffer_select)
  reg09=0x40 ; //txdwrite highaddress
 else
        reg09=0x46 ; //txdwrite highaddress
 reg08=0x00;   //read page address low
 reg0b=len>  >  8;  //read count high
 reg0a=len&0xff;  //read count low;
 reg00=0x12;   //write dma, page0
 for (ii=0;ii  <len;ii++) //for (ii=4;ii  <len+4;ii++)  //是否加4有待验证
 {
    reg10=*(outbuf+ii);  
 }

 /* 以下3句为中止dma的操作,可以不要            */
 reg0b=0x00;  //read count high   中止DMA操作
 reg0a=0x00;  //read count low;
 reg00=0x22;  //complete dma page 0

 for(i=0;i  <16;i++) //最多重发16次
 {
  for(ii=0;ii  <1000;ii++) //检查txp为是否为低
  {
   if ((reg00&0x04)==0) break;
  }
  if ((reg04&0x01)!=0) break; //表示发送成功
  reg00=0x3e;
 }

 for(i=0;i  <16;i++) //最多重发16次
 {
  for(ii=0;ii  <1000;ii++) //检查txp为是否为低
  {
   if ((reg00&0x04)==0) break;
  }
  if ((reg04&0x01)!=0) break; //表示发送成功
  reg00=0x3e;
 }

 reg07=0xff;
 if(txd_buffer_select)
  reg04=0x40; //txd packet start; 
 else
  reg04=0x46; //txd packet start; 
 reg06=len>  >  8; //high byte counter
 reg05=len&0xff; //low byte counter
 reg07=0xff;
 reg00=0x3e;  //to sendpacket;  

 
 free(outbuf);//free(p) 释放指针为p所指向的存储器区域,p必须是calloc.malloc或者realloc函数分配的存储器区域
}


void eth_send(uchar xdata * outbuf, uchar * hwaddr, uint ptype, uint len)
{
 ETH_HEADER xdata * eth;
   
   eth = (ETH_HEADER xdata *)outbuf;  //怎么理解指针的含义
   
 // Add 14 byte Ethernet header
 memcpy(eth->  dest_hwaddr, hwaddr, 6);
 memcpy(eth->  source_hwaddr, my_hwaddr, 6); 
   eth->  frame_type = ptype;

   // We just added 14 bytes to length
   send_frame(outbuf, len + 14);
}


/************主程序*****************/

void main(void)
{char bb="abcdedgh";
init_8019();

for(;;)
{udp_send(&bb,1025,8);
}


}


运行后在udpdemo里不能接收到数据,经过测试硬件没有问题,寄存器读写都正常,调试了好久还是没有眉目.




发表时间:2004年5月11日11:47:38

  
回复该帖

本主题共有 1 帖,分页:>>>>>该主题的所有内容[1]条

 *树形目录 只列出部分跟帖的标题以及简单的摘要信息 该主题的部分跟帖如下:

[上一篇帖子]:after语句的困惑小弟使用一片epm7128的CPLD控制一片AD芯片(状态机实现),7128的晶
[下一篇帖子]:你好,我现在也正在做这方面的研究,非常希望能和你共同探讨,我的email是angelfish_jz@