<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 單片機驅動(dòng)DM9000網(wǎng)卡芯片詳細調試過(guò)程

單片機驅動(dòng)DM9000網(wǎng)卡芯片詳細調試過(guò)程

作者: 時(shí)間:2016-10-07 來(lái)源:網(wǎng)絡(luò ) 收藏

  4、驗證初始化中的各個(gè)函數。

本文引用地址:http://dyxdggzs.com/article/201610/310907.htm

  下面我們來(lái)看一下,上面所寫(xiě)的初始化函數是否可用。以上我們寫(xiě)好了三個(gè)函數,分別為

  _init(),sendpacket()和receivepacket(),保存并命名為dm9000.c。既然我們要進(jìn)行調試,當

  然要有結果輸出,根據自己的處理器的情況寫(xiě)一個(gè)串口程序,這些函數是學(xué)某個(gè)單片機的基礎,這里不

  做詳細介紹,用到是時(shí)候會(huì )在函數里注釋一下。

  接下來(lái)我們來(lái)寫(xiě)個(gè)主函數,新建C文件,命名為mian.c,填寫(xiě)如下函數:

  void main(void)

  {

  unsigned int i;

  unsigned char c;

  uart0_init();//初始化串口,調試時(shí)用到

  _init();//初始化網(wǎng)卡

  print_regs();/*通過(guò)串口,將中的寄存器打印出來(lái),顯示在超級終端上。此函數根據自己

  的處理器進(jìn)行修改,功能僅僅是讀DM9000寄存器dm9000_reg_read(),再通過(guò)串口打印出來(lái)而已*/

  }

  函數寫(xiě)好,保存文件,連接硬件,連接網(wǎng)線(xiàn)到電腦上或局域網(wǎng)上,運行結果如下圖所示:

 

  圖4 顯示寄存器值

  這里首先檢查,各個(gè)控制寄存器是否是自己寫(xiě)進(jìn)去的值,在檢查狀態(tài)寄存器是否正確,其中主要要

  看NSR寄存器的bit[5]是否為“1”,該位表示是否連接成功。本例中NSR的值為40H,括號里的數為對應

  的十進(jìn)制數。

  下面我們將主函數改進(jìn)一下,增加個(gè)中斷接收函數,查看是否能接收到數據。

  void main(void)

  {

  unsigned int i;

  unsigned char c;

  uart0_init();//初始化串口,調試時(shí)用到

  DM9000_init();//初始化網(wǎng)卡

  /********************************************************************************/

  /*這一部分要根據自己的處理器情況,將DM9000的INT引腳連接到處理器的外部中斷上,打開(kāi)中斷*/

  /********************************************************************************/

  sendpacket(60);/*我事先已經(jīng)在Buffer[]中存儲了ARP請求數據包,這里就直接發(fā)送了,以便接收

  ARP應答包。大家可以先參考后面講的ARP協(xié)議,根據自己機器的情況,將數據事先存到Buffer[]中*/

  while(1);//等待中斷

  }

  void int_issue(void) //中斷處理函數,需要根據自己的處理器進(jìn)行設置

  {

  unsigned int i;

  i = receivepacket(Buffer);//將數據讀取到Buffer中。

  int_again :

  if(i == 0)

  {

  return;

  }

  else

  {

  print_buffer();//將接收到的所有數據打印出來(lái)

  while(1);//停止在這里等待觀(guān)察,注意:實(shí)際應用中是不允許停止在中斷中的。

  }

  /************************************************************************************/

  /*這里加上這一段,目的是判斷中斷期間是否接收到其它數據包。有則加以處理。不加也完全可以*/

  /* 根據自己的處理器,判斷處理器是否還處在中斷狀態(tài),若是則進(jìn)行如下操作,不是則跳過(guò)該段。*/

  i = receivepacket(Buffer);

  if(i != 0)

  {

  goto int_again;

  }

  /************************************************************************************/

  }

  編譯調試,運行結果如下:

 

  圖5 接收數據包中的數據

  這是一個(gè)ARP應答包,包含了我電腦上的MAC地址和局域網(wǎng)內的IP地址。反正我也不是啥重要人物,

  這里就不保密了,呵呵。

  如果一些順利,到這里對DM9000網(wǎng)卡的初始化工作就完成了。如果出現問(wèn)題,出現問(wèn)題首先要

  檢查寄存器的值是否正確??梢詫M9000中的寄存器打印出來(lái),查看到底是哪里的問(wèn)題。如果打印出的

  值很混亂,在確保串口程序無(wú)誤的前提下,查看硬件連接,以及寄存器讀寫(xiě)時(shí)序是否正確,重復調試幾

  次查找原因。

  三、ARP協(xié)議的實(shí)現

  1、ARP協(xié)議原理簡(jiǎn)述

  ARP協(xié)議(Address Resolution Protocol 地址解析協(xié)議),在局域網(wǎng)中,網(wǎng)絡(luò )中實(shí)際傳輸的是“

  幀”,幀里面有目標主機的MAC地址。在以太網(wǎng)中,一個(gè)注意要和另一個(gè)主機進(jìn)行直接通信,必須要知

  道目標主機的MAC地址。這個(gè)MAC地址就是標識我們的網(wǎng)卡唯一性的地址。但這個(gè)目標MAC地址是如

  何獲得的呢?這就用到了我們這里講到的地址解析協(xié)議。所有“地址解析”,就是主機在發(fā)送幀前將目

  標IP地址轉換成MAC地址的過(guò)程。ARP協(xié)議的基本功能就是通過(guò)目標設備的IP地址,查詢(xún)目標設備的MAC

  地址,以保證通信的順利進(jìn)行。所以在第一次通信前,我們知道目標機的IP地址,想要獲知目標機的

  MAC地址,就要發(fā)送ARP報文(即ARP數據包)。它的傳輸過(guò)程簡(jiǎn)單的說(shuō)就是:我知道目標機的IP地址,

  那么我就向網(wǎng)絡(luò )中所有的機器發(fā)送一個(gè)ARP請求,請求中有目標機的IP地址,請求的意思是目標機要是

  收到了此請求,就把你的MAC地址告訴我。如果目標機不存在,那么此請求自然不會(huì )有人回應。若目標

  機接收到了此請求,它就會(huì )發(fā)送一個(gè)ARP應答,這個(gè)應答是明確發(fā)給請求者的,應答中有MAC地址。我接

  到了這個(gè)應答,我就知道了目標機的MAC地址,就可以進(jìn)行以后的通信了。因為每次通信都要用到MAC地

  址。

  ARP報文被封裝在以太網(wǎng)幀頭部中傳輸,如圖為ARP請求報文的頭部格式。

 

  圖6 用于以太網(wǎng)的ARP請求或應答分組格式

  注意,以太網(wǎng)的傳輸存儲是“大端格式”,即先發(fā)送高字節后發(fā)送低字節。例如,兩個(gè)字節的數據

  ,先發(fā)送高8位后發(fā)送低8位。所以接收數據的時(shí)候要注意存儲順序。

  整個(gè)報文分成兩部分,以太網(wǎng)首部和ARP請求/應答。下面挑重點(diǎn)講述。

  “以太網(wǎng)目的地址”字段:若是發(fā)送ARP請求,應填寫(xiě)廣播類(lèi)型的MAC地址FF-FF-FF-FF-FF-FF,意思是

  讓網(wǎng)絡(luò )上的所有機器接收到;

  “幀類(lèi)型”字段:填寫(xiě)08-06表示次報文是ARP協(xié)議;

  “硬件類(lèi)型”字段:填寫(xiě)00-01表示以太網(wǎng)地址,即MAC地址;

  “協(xié)議類(lèi)型”字段:填寫(xiě)08-00表示IP,即通過(guò)IP地址查詢(xún)MAC地址;

  “硬件地址長(cháng)度”字段:MAC地址長(cháng)度為6(以字節為單位);

  “協(xié)議地址長(cháng)度”字段:IP地址長(cháng)度為4(以字節為單位);

  “操作類(lèi)型”字段:ARP數據包類(lèi)型,0表示ARP請求,1表示ARP應答;

  “目的以太網(wǎng)地址”字段:若是發(fā)送ARP請求,這里是需要目標機填充的。

  2、ARP的處理程序

  ARP協(xié)議原理很簡(jiǎn)單,下面我們來(lái)編寫(xiě)ARP協(xié)議的處理函數。新建文件命名為arp.c,填寫(xiě)如下函數

 ?。?/p>

  unsigned char mac_addr[6] = {*,*,*,*,*,*};

  unsigned char ip_addr[4] = { 192, 168, *, * };

  unsigned char host_ip_addr[4] = { 192, 168, *, * };

  unsigned char host_mac_addr[6]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

  unsigned char Buffer[1000];

  uint16 packet_len;

  /*這些全局變量,在前面將的文件中有些已經(jīng)有過(guò)定義,這里要注意在前面加上“extern”關(guān)鍵字。“

  *”應該根據自己的機器修改*/

  #define HON(n) ((((uint16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))

  /*此宏定義是將小端格式存儲的字(兩個(gè)字節)轉換成大端格式存儲*/

  void arp_request(void) //發(fā)送ARP請求數據包

  {

  //以太網(wǎng)首部

  memcpy(ARPBUF->ethhdr.d_mac, host_mac_addr, 6);

  /*字符串拷貝函數,文件要包含頭文件。參數依次是,拷貝目標指針,拷貝數據源指針,拷

  貝字符數*/

  memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);

  ARPBUF->ethhdr.type = HON( 0x0806 );

  /*小端格式的編譯器,可以用HON()宏來(lái)轉換成大端格式,如果你的編譯器是大端格式,直接填寫(xiě)

  0x0806即可*/

  /*就是簡(jiǎn)單的按照協(xié)議格式填充,以下同*/

  //ARP首部

  ARPBUF->hwtype = HON( 1 );

  ARPBUF->protocol = HON( 0x0800 );

  ARPBUF->hwlen = 6;

  ARPBUF->protolen = 4;

  ARPBUF->opcode = HON( 0 );

  memcpy(ARPBUF->smac, mac_addr, 6);

  memcpy(ARPBUF->sipaddr, ip_addr, 4);

  memcpy(ARPBUF->dipaddr, host_ip_addr, 4);

  packet_len = 42;//14+28=42

  sendpacket( Buffer, packet_len );

  }

  注釋?zhuān)篈RPBUF的宏定義和ARP首部結構,在前面已經(jīng)講過(guò)。同時(shí)注意執行該函數時(shí)中斷的處理。這里沒(méi)

  作處理。

  看上去很easy吧,下面函數實(shí)現接收ARP請求或接收ARP應答的處理。

  unsigned char arp_process(void)//ARP接收函數,成功返回1,否則返回0

  {

  //簡(jiǎn)單判斷ARP數據包有無(wú)損壞,有損壞則丟棄,不予處理

  if( packet_len < 28 )//ARP數據長(cháng)度為28字節為無(wú)效數據

  {

  return 0;

  }

  switch ( HON( ARPBUF->opcode ) )

  {

  case 0 : //處理ARP請求

  if( ARPBUF->dipaddr[0] == ip_addr[0] &&

  ARPBUF->dipaddr[1] == ip_addr[1] &&

  ARPBUF->dipaddr[2] == ip_addr[2] &&

  ARPBUF->dipaddr[3] == ip_addr[3] )//判斷是否是自己的IP,是否向自己詢(xún)問(wèn)MAC地址

  。

  {

  ARPBUF->opcode = HON( 2 );//設置為ARP應答

  memcpy(ARPBUF->dmac, ARPBUF->smac, 6);

  memcpy(ARPBUF->ethhdr.d_mac, ARPBUF->smac, 6);

  memcpy(ARPBUF->smac, mac_addr, 6);

  memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);

  memcpy(ARPBUF->dipaddr, ARPBUF->sipaddr, 4);

  memcpy(ARPBUF->sipaddr, ip_addr, 4);

  ARPBUF->ethhdr.type = HON( 0x0806 );

  packet_len = 42;

  sendpacket( Buffer, packet_len );//發(fā)送ARP數據包

  return 1;

  }

  else

  {

  return 0;

  }

  break;

  case 1 : //處理ARP應答

  if( ARPBUF->dipaddr[0] == ip_addr[0] &&

  ARPBUF->dipaddr[1] == ip_addr[1] &&

  ARPBUF->dipaddr[2] == ip_addr[2] &&

  ARPBUF->dipaddr[3] == ip_addr[3] )//再次判斷IP,是否是給自己的應答

  {

  memcpy(host_mac_addr, ARPBUF->smac, 6);//保存服務(wù)器MAC地址

  return 1;

  }

  else

  {

  return 0;

  }

  break;

  default ://不是ARP協(xié)議

  return 0;

  }

  }

  根據ARP協(xié)議格式看這兩個(gè)函數并不困難。于是我們又得到兩個(gè)函數:arp_request()和

  arp_process()。

  3、ARP程序調試

  下面我們修改主函數和中斷處理函數。

  將mian()函數中的“sendpacket(60);”語(yǔ)句換成“arp_request();”語(yǔ)句。

  void int_issue(void) //中斷處理函數,需要根據自己的處理器進(jìn)行設置

  {

  unsigned int i;

  i = receivepacket(Buffer);//將數據讀取到Buffer中。

  if(i == 0)

  {

  return;

  }

  else

  {

  i = arp_process();

  if(i == 1)//判斷是否是ARP協(xié)議

  print_hostmacaddr();//打印目標機的MAC地址,就是用串口打印host_mac_addr[]中的6

  個(gè)字節

  }

  }

  保存運行調試。

 

  圖7 主機MAC地址

  至此,關(guān)于DM9000的調試過(guò)程就完成了。之后我還調試了UDP通訊、TCP通訊等,主要是關(guān)于協(xié)議的

  處理了,這里就不介紹了。有興趣的朋友可以參看《TCP/IP協(xié)議》第一卷,將會(huì )有很大幫助。希望這些

  調試過(guò)程能為讀者或多火燒的提供些有用的信息,也歡迎大家和我一起討論。


上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: DM9000 芯片

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>