单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 374|回复: 0
打印 上一主题 下一主题
收起左侧

一个简单的51 SPI Ethernet 测试程序

[复制链接]
跳转到指定楼层
楼主
本帖最后由 oldspring 于 2018-11-17 09:27 编辑

51芯片内部没有Ethernet模块,无法直接与网络连接,但是我们可以利用外部网络专用芯片ENC28J60,使得我们的51芯片可以进行网络通信。这里介绍一个简单的51 SPI Ethernet 测试程序,希望大家能够喜欢。
注意:这个51编译器的Ethernet库函数支持:
  • IPv4 protocol.
  • ARP requests.
  • ICMP echo requests.
  • UDP requests.
  • TCP requests (no stack, no packet reconstruction).
  • packet fragmentation is NOT supported.

  1. // duplex config flags
  2. #define Spi_Ethernet_HALFDUPLEX     0x00  // half duplex
  3. #define Spi_Ethernet_FULLDUPLEX     0x01  // full duplex

  4. // mE ehternet NIC pinout
  5. sfr sbit Spi_Ethernet_RST at P1_0_bit;
  6. sfr sbit Spi_Ethernet_CS  at P1_1_bit;
  7. // end ethernet NIC definitions

  8. /************************************************************
  9. * ROM constant strings
  10. */
  11. const code unsigned char httpHeader[] = "HTTP/1.1 200 OKnContent-type: " ;  // HTTP header
  12. const code unsigned char httpMimeTypeHTML[] = "text/htmlnn" ;              // HTML MIME type
  13. const code unsigned char httpMimeTypeScript[] = "text/plainnn" ;           // TEXT MIME type
  14. idata unsigned char httpMethod[] = "GET /";
  15. /*
  16. * web page, splited into 2 parts :
  17. * when coming short of ROM, fragmented data is handled more efficiently by linker
  18. *
  19. * this HTML page calls the boards to get its status, and builds itself with javascript
  20. */
  21. const code char    *indexPage =                   // Change the IP address of the page to be refreshed
  22. "<meta http-equiv="refresh" content="3;url=http://192.168.20.60">
  23. <HTML><HEAD></HEAD><BODY>
  24. <h1>8051 + ENC28J60 Mini Web Server</h1>
  25. <a href=/>Reload</a>
  26. <script src=/s></script>
  27. <table><tr><td><table border=1 style="font-size:20px ;font-family: terminal ;">
  28. <tr><th colspan=2>P0</th></tr>
  29. <script>
  30. var str,i;
  31. str="";
  32. for(i=0;i<8;i++)
  33. {str+="<tr><td bgcolor=pink>BUTTON #"+i+"</td>";
  34. if(P0&(1<<i)){str+="<td bgcolor=red>ON";}
  35. else {str+="<td bgcolor=#cccccc>OFF";}
  36. str+="</td></tr>";}
  37. document.write(str) ;
  38. </script>
  39. " ;

  40. const char    *indexPage2 =  "</table></td><td>
  41. <table border=1 style="font-size:20px ;font-family: terminal ;">
  42. <tr><th colspan=3>P3</th></tr>
  43. <script>
  44. var str,i;
  45. str="";
  46. for(i=0;i<8;i++)
  47. {str+="<tr><td bgcolor=yellow>LED #"+i+"</td>";
  48. if(P3&(1<<i)){str+="<td bgcolor=red>ON";}
  49. else {str+="<td bgcolor=#cccccc>OFF";}
  50. str+="</td><td><a href=/t"+i+">Toggle</a></td></tr>";}
  51. document.write(str) ;
  52. </script>
  53. </table></td></tr></table>
  54. This is HTTP request #<script>document.write(REQ)</script></BODY></HTML>
  55. " ;

  56. /***********************************
  57. * RAM variables
  58. */
  59. idata unsigned char   myMacAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f} ;   // my MAC address
  60. idata unsigned char   myIpAddr[4]  = {192, 168, 20, 60} ;                      // my IP address
  61. idata unsigned char   getRequest[15] ;                                        // HTTP request buffer
  62. idata unsigned char   dyna[29] ;                                              // buffer for dynamic response
  63. idata unsigned long   httpCounter = 0 ;                                       // counter of HTTP requests

  64. /*******************************************
  65. * functions
  66. */

  67. /*
  68. * put the constant string pointed to by s to the ENC transmit buffer.
  69. */
  70. /*unsigned int    putConstString(const code char *s)
  71.         {
  72.         unsigned int ctr = 0 ;

  73.         while(*s)
  74.                 {
  75.                 Spi_Ethernet_putByte(*s++) ;
  76.                 ctr++ ;
  77.                 }
  78.         return(ctr) ;
  79.         }*/
  80. /*
  81. * it will be much faster to use library Spi_Ethernet_putConstString routine
  82. * instead of putConstString routine above. However, the code will be a little
  83. * bit bigger. User should choose between size and speed and pick the implementation that
  84. * suites him best. If you choose to go with the putConstString definition above
  85. * the #define line below should be commented out.
  86. *
  87. */
  88. #define putConstString  Spi_Ethernet_putConstString

  89. /*
  90. * put the string pointed to by s to the ENC transmit buffer
  91. */
  92. /*unsigned int    putString(char *s)
  93.         {
  94.         unsigned int ctr = 0 ;

  95.         while(*s)
  96.                 {
  97.                 Spi_Ethernet_putByte(*s++) ;

  98.                 ctr++ ;
  99.                 }
  100.         return(ctr) ;
  101.         }*/
  102. /*
  103. * it will be much faster to use library Spi_Ethernet_putString routine
  104. * instead of putString routine above. However, the code will be a little
  105. * bit bigger. User should choose between size and speed and pick the implementation that
  106. * suites him best. If you choose to go with the putString definition above
  107. * the #define line below should be commented out.
  108. *
  109. */
  110. #define putString  Spi_Ethernet_putString

  111. /*
  112. * this function is called by the library
  113. * the user accesses to the HTTP request by successive calls to Spi_Ethernet_getByte()
  114. * the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
  115. * the function must return the length in bytes of the HTTP reply, or 0 if nothing to transmit
  116. *
  117. * if you don't need to reply to HTTP requests,
  118. * just define this function with a return(0) as single statement
  119. *
  120. */
  121. unsigned int    Spi_Ethernet_UserTCP(unsigned char *remoteHost, unsigned int remotePort, unsigned int localPort, unsigned int reqLength)
  122.         {
  123.         idata unsigned int    len;             // my reply length

  124.         if(localPort != 80)                         // I listen only to web request on port 80
  125.                 {
  126.                 return(0) ;
  127.                 }

  128.         // get 10 first bytes only of the request, the rest does not matter here
  129.         for(len = 0 ; len < 10 ; len++)
  130.                 {
  131.                 getRequest[len] = Spi_Ethernet_getByte() ;
  132.                 }
  133.         getRequest[len] = 0 ;

  134.         len = 0;

  135.         if(memcmp(getRequest, httpMethod, 5))       // only GET method is supported here
  136.                 {
  137.                 return(0) ;
  138.                 }

  139.         httpCounter++ ;                             // one more request done

  140.         if(getRequest[5] == 's')                    // if request path name starts with s, store dynamic data in transmit buffer
  141.                 {
  142.                 // the text string replied by this request can be interpreted as javascript statements
  143.                 // by browsers

  144.                 len = putConstString(httpHeader) ;              // HTTP header
  145.                 len += putConstString(httpMimeTypeScript) ;     // with text MIME type

  146.                 // add P3 value (buttons) to reply
  147.                 len += putConstString("var P3=") ;
  148.                 WordToStr(P3, dyna) ;
  149.                 len += putString(dyna) ;
  150.                 len += putConstString(";") ;

  151.                 // add P0 value (LEDs) to reply
  152.                 len += putConstString("var P0=") ;
  153.                 WordToStr(P0, dyna) ;
  154.                 len += putString(dyna) ;
  155.                 len += putConstString(";") ;

  156.                 // add HTTP requests counter to reply
  157.                 WordToStr(httpCounter, dyna) ;
  158.                 len += putConstString("var REQ=") ;
  159.                 len += putString(dyna) ;
  160.                 len += putConstString(";") ;
  161.                 }
  162.         else if(getRequest[5] == 't')                           // if request path name starts with t, toggle P3 (LED) bit number that comes after
  163.                 {
  164.                 unsigned char   bitMask = 0 ;                   // for bit mask

  165.                 if(isdigit(getRequest[6]))                      // if 0 <= bit number <= 9, bits 8 & 9 does not exist but does not matter
  166.                         {
  167.                         bitMask = getRequest[6] - '0' ;         // convert ASCII to integer
  168.                         bitMask = 1 << bitMask ;                // create bit mask
  169.                         P3 ^= bitMask ;                         // toggle P3 with xor operator
  170.                         }
  171.                 }

  172.         if(len == 0)                                            // what do to by default
  173.                 {
  174.                 len =  putConstString(httpHeader) ;             // HTTP header
  175.                 len += putConstString(httpMimeTypeHTML) ;       // with HTML MIME type
  176.                 len += putConstString(indexPage) ;              // HTML page first part
  177.                 len += putConstString(indexPage2) ;             // HTML page second part
  178.                 }

  179.         return(len) ;                                           // return to the library with the number of bytes to transmit
  180.         }
  181.         
  182. /*
  183. * this function is called by the library
  184. * the user accesses to the UDP request by successive calls to Spi_Ethernet_getByte()
  185. * the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
  186. * the function must return the length in bytes of the UDP reply, or 0 if nothing to transmit
  187. *
  188. * if you don't need to reply to UDP requests,
  189. * just define this function with a return(0) as single statement
  190. *                                               
  191. */
  192. unsigned int    Spi_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort, unsigned int destPort, unsigned int reqLength)
  193.         {
  194.         idata unsigned int    len ;                     // my reply length
  195.         idata unsigned char   * ptr ;                   // pointer to the dynamic buffer

  196.         // reply is made of the remote host IP address in human readable format
  197.         ByteToStr(remoteHost[0], dyna) ;                // first IP address byte
  198.         dyna[3] = '.' ;
  199.         ByteToStr(remoteHost[1], dyna + 4) ;            // second
  200.         dyna[7] = '.' ;
  201.         ByteToStr(remoteHost[2], dyna + 8) ;            // third
  202.         dyna[11] = '.' ;
  203.         ByteToStr(remoteHost[3], dyna + 12) ;           // fourth

  204.         dyna[15] = ':' ;                                // add separator

  205.         // then remote host port number
  206.         WordToStr(remotePort, dyna + 16) ;
  207.         dyna[21] = '[' ;
  208.         WordToStr(destPort, dyna + 22) ;
  209.         dyna[27] = ']' ;
  210.         dyna[28] = 0 ;

  211.         // the total length of the request is the length of the dynamic string plus the text of the request
  212.         len = 28 + reqLength;

  213.         // puts the dynamic string into the transmit buffer
  214.         Spi_Ethernet_putBytes(dyna, 28) ;

  215.         // then puts the request string converted into upper char into the transmit buffer
  216.         while(reqLength--)
  217.                 {
  218.                 Spi_Ethernet_putByte(toupper(Spi_Ethernet_getByte())) ;
  219.                 }

  220.         return(len) ;           // back to the library with the length of the UDP reply
  221.         }

  222. /*
  223. * main entry
  224. */
  225. void    main()
  226.         {
  227.         /*
  228.          * starts ENC28J60 with :
  229.          * reset bit on P1_0
  230.          * CS bit on P1_1
  231.          * my MAC & IP address
  232.          * full duplex
  233.          */
  234.         SPI1_Init();
  235.         Spi_Ethernet_Init(myMacAddr, myIpAddr, Spi_Ethernet_FULLDUPLEX) ; // full duplex, CRC + MAC Unicast + MAC Broadcast filtering

  236.         while(1)                            // do forever
  237.                 {
  238.                 /*
  239.                  * if necessary, test the return value to get error code
  240.                  */
  241.                 Spi_Ethernet_doPacket() ;   // process incoming Ethernet packets
  242.                
  243.                 /*
  244.                  * add your stuff here if needed
  245.                  * Spi_Ethernet_doPacket() must be called as often as possible
  246.                  * otherwise packets could be lost
  247.                  */
  248.                 }
  249.         }
复制代码
相关信息:http://www.51hei.com/bbs/dpj-136722-1.html



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 转播转播 分享分享 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51hei电子论坛2群 联系QQ:125739409;技术交流QQ群219535678

Powered by 单片机教程网

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