Giao tiếp giữa Ethernet và Pic

Collapse
X
 
  • Giờ
  • Show
Clear All
new posts
  • tatthang_le
    Nhập môn đệ tử
    • Dec 2007
    • 5

    #1

    Giao tiếp giữa Ethernet và Pic

    Mình đang làm giao tiếp về Ethernet và Pic, mình dùng MikroC để program cho Pic 16F877A, thông qua con ENC28J60. Nhưng mình chưa hiểu rõ việc kết nối giữa Pic và WebServer diễn ra như thế nào. Giả sử trong chương trình gửi một Byte lên từ PortD, vậy làm sao để Web biết được để hiển thị ra ngoài. Đây là Code của nó.
    Em dùng Code này download xuống Pic nhưng khi truy cập vào địa chỉ đã assign cho Pic thì không thấy kết quả gì xảy ra.Mong các bạn giúp đỡ!!!! Cảm ơn các bạn nhiều.
    Code:
    /*
     * Project Name:
         Spi_EthernetDemo (Ethernet Library demo for ENC28J60 mcu)
     * Target Platform:
         PIC
     * Copyright:
         (c) mikroElektronika, 2006.
     * Revision History:
         20060810:
           - Initial release. Author: Bruno Gavand.
     *
     * V1.0 : first release
     * V1.1 : bad MIME type for / path request, changed to HTML instead of SCRIPT (thanks Srdjan !)
     *
     * description  :
     *      this code shows how to use the Spi_Ethernet mini library :
     *              the board will reply to ARP & ICMP echo requests
     *              the board will reply to UDP requests on any port :
     *                      returns the request in upper char with a header made of remote host IP & port number
     *              the board will reply to HTTP requests on port 80, GET method with pathnames :
     *                      /               will return the HTML main page
     *                      /s              will return board status as text string
     *                      /t0 ... /t7     will toggle RC0 to RC7 bit and return HTML main page
     *                      all other requests return also HTML main page
     *
     * target devices :
     *      any PIC with integrated SPI and more than 4 Kb ROM memory
     *      32 to 40 MHz clock is recommended to get from 8 to 10 Mhz SPI clock,
     *      otherwise PIC should be clocked by ENC clock output due to ENC silicon bug in SPI hardware
     *      if you try lower PIC clock speed, don't be surprised if the board hang or miss some requests !
     *      tested with PIC16F877A@10Mhz, PIC18F452@40Mhz on EasyPIC3 board
     *
     *
     * EP settings :
     *      RA2 & RA3 pots jumper : closed
     *      PORTB : pull-down
     *      PORTC : pull-down
     *      BUTTONS : pull-up
     *
     *      RC0 : !RESET    to ENC reset input pin
     *      RC1 : !CS       to ENC chip select input pin
     *      the ENC28J60 SPI bus CLK, SO, SI must be connected to the corresponding SPI pins of the PIC
     *      the INT and WOL signals from the ENC are not used
     *
     * Test configuration:
         MCU:             PIC18F452/PIC16F877A
         Dev.Board:       EasyPIC4
         Oscillator:      HS/PLL4, 10.000MHz
         Ext. Modules:    mE Serial Ethernet board
         SW:              mikroC v7.0
     * NOTES:
     	   Make sure that you use right compiler version with this project
         Renamed functions of Spi ethernet library from (v6.0)ENC28j60... to (v6.2)Spi_Ethernet...
         
     */
     
    #define Spi_Ethernet_HALFDUPLEX     0
    #define Spi_Ethernet_FULLDUPLEX     1
    
    /************************************************************
     * ROM constant strings
     */
    const unsigned char httpHeader[] = "HTTP/1.1 200 OK\nContent-type: " ;  // HTTP header
    const unsigned char httpMimeTypeHTML[] = "text/html\n\n" ;              // HTML MIME type
    const unsigned char httpMimeTypeScript[] = "text/plain\n\n" ;           // TEXT MIME type
    unsigned char httpMethod[] = "GET /";
    /*
     * web page, splited into 2 parts :
     * when coming short of ROM, fragmented data is handled more efficiently by linker
     *
     * this HTML page calls the boards to get its status, and builds itself with javascript
     */
    const   char    *indexPage =                   // Change the IP address of the page to be refreshed
    "<meta http-equiv=\"refresh\" content=\"3;url=http://192.168.20.60\">\
    <HTML><HEAD></HEAD><BODY>\
    <h1>PIC + ENC28J60 Mini Web Server</h1>\
    <a href=/>Reload</a>\
    <script src=/s></script>\
    <table><tr><td valign=top><table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
    <tr><th colspan=2>ADC</th></tr>\
    <tr><td>AN2</td><td><script>document.write(AN2)</script></td></tr>\
    <tr><td>AN3</td><td><script>document.write(AN3)</script></td></tr>\
    </table></td><td><table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
    <tr><th colspan=2>PORTB</th></tr>\
    <script>\
    var str,i;\
    str=\"\";\
    for(i=0;i<8;i++)\
    {str+=\"<tr><td bgcolor=pink>BUTTON #\"+i+\"</td>\";\
    if(PORTB&(1<<i)){str+=\"<td bgcolor=red>ON\";}\
    else {str+=\"<td bgcolor=#cccccc>OFF\";}\
    str+=\"</td></tr>\";}\
    document.write(str) ;\
    </script>\
    " ;
    
    const   char    *indexPage2 =  "</table></td><td>\
    <table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
    <tr><th colspan=3>PORTD</th></tr>\
    <script>\
    var str,i;\
    str=\"\";\
    for(i=0;i<8;i++)\
    {str+=\"<tr><td bgcolor=yellow>LED #\"+i+\"</td>\";\
    if(PORTD&(1<<i)){str+=\"<td bgcolor=red>ON\";}\
    else {str+=\"<td bgcolor=#cccccc>OFF\";}\
    str+=\"</td><td><a href=/t\"+i+\">Toggle</a></td></tr>\";}\
    document.write(str) ;\
    </script>\
    </table></td></tr></table>\
    This is HTTP request #<script>document.write(REQ)</script></BODY></HTML>\
    " ;
    
    /***********************************
     * RAM variables
     */
    unsigned char   myMacAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f} ;   // my MAC address
    unsigned char   myIpAddr[4] = {192, 168, 20, 60} ;                      // my IP address
    unsigned char   getRequest[15] ;                                        // HTTP request buffer
    unsigned char   dyna[31] ;                                              // buffer for dynamic response
    unsigned long   httpCounter = 0 ;                                       // counter of HTTP requests
    
    /*******************************************
     * functions
     */
     
    /*
     * put the constant string pointed to by s to the ENC transmit buffer
     */
    unsigned int    putConstString(const char *s)
            {
            unsigned int ctr = 0 ;
            
            while(*s)
                    {
                    Spi_Ethernet_putByte(*s++) ;
                    ctr++ ;
                    }
            return(ctr) ;
            }
            
    /*
     * put the string pointed to by s to the ENC transmit buffer
     */
    unsigned int    putString(char *s)
            {
            unsigned int ctr = 0 ;
    
            while(*s)
                    {
                    Spi_Ethernet_putByte(*s++) ;
                    ctr++ ;
                    }
            return(ctr) ;
            }
    
    /*
     * this function is called by the library
     * the user accesses to the HTTP request by successive calls to Spi_Ethernet_getByte()
     * the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
     * the function must return the length in bytes of the HTTP reply, or 0 if nothing to transmit
     *
     * if you don't need to reply to HTTP requests,
     * just define this function with a return(0) as single statement
     *
     */
    unsigned int    Spi_Ethernet_UserTCP(unsigned char *remoteHost, unsigned int remotePort, unsigned int localPort, unsigned int reqLength)
            {
            unsigned int    len = 0 ;                   // my reply length
            unsigned int    i ;                         // general purpose integer
    
            if(localPort != 80)                         // I listen only to web request on port 80
                    {
                    return(0) ;
                    }
                    
            // get 10 first bytes only of the request, the rest does not matter here
            for(i = 0 ; i < 10 ; i++)
                    {
                    getRequest[i] = Spi_Ethernet_getByte() ;
                    }
            getRequest[i] = 0 ;
    
            if(memcmp(getRequest, httpMethod, 5))       // only GET method is supported here
                    {
                    return(0) ;
                    }
    
            httpCounter++ ;                             // one more request done
    
            if(getRequest[5] == 's')                    // if request path name starts with s, store dynamic data in transmit buffer
                    {
                    // the text string replied by this request can be interpreted as javascript statements
                    // by browsers
                    
                    len = putConstString(httpHeader) ;              // HTTP header
                    len += putConstString(httpMimeTypeScript) ;     // with text MIME type
    
                    // add AN2 value to reply
                    intToStr(ADC_Read(2), dyna) ;
                    len += putConstString("var AN2=") ;
                    len += putString(dyna) ;
                    len += putConstString(";") ;
    
                    // add AN3 value to reply
                    intToStr(ADC_Read(3), dyna) ;
                    len += putConstString("var AN3=") ;
                    len += putString(dyna) ;
                    len += putConstString(";") ;
    
                    // add PORTB value (buttons) to reply
                    len += putConstString("var PORTB=") ;
                    intToStr(PORTB, dyna) ;
                    len += putString(dyna) ;
                    len += putConstString(";") ;
                            
                    // add PORTD value (LEDs) to reply
                    len += putConstString("var PORTD=") ;
                    intToStr(PORTD, dyna) ;
                    len += putString(dyna) ;
                    len += putConstString(";") ;
    
                    // add HTTP requests counter to reply
                    intToStr(httpCounter, dyna) ;
                    len += putConstString("var REQ=") ;
                    len += putString(dyna) ;
                    len += putConstString(";") ;
                    }
            else if(getRequest[5] == 't')                           // if request path name starts with t, toggle PORTD (LED) bit number that comes after
                    {
                    unsigned char   bitMask = 0 ;                   // for bit mask
    
                    if(isdigit(getRequest[6]))                      // if 0 <= bit number <= 9, bits 8 & 9 does not exist but does not matter
                            {
                            bitMask = getRequest[6] - '0' ;         // convert ASCII to integer
                            bitMask = 1 << bitMask ;                // create bit mask
                            PORTD ^= bitMask ;                      // toggle PORTD with xor operator
                            }
                    }
    
            if(len == 0)                                            // what do to by default
                    {
                    len =  putConstString(httpHeader) ;             // HTTP header
                    len += putConstString(httpMimeTypeHTML) ;       // with HTML MIME type
                    len += putConstString(indexPage) ;              // HTML page first part
                    len += putConstString(indexPage2) ;             // HTML page second part
                    }
    
            return(len) ;                                           // return to the library with the number of bytes to transmit
            }
            
    /*
     * this function is called by the library
     * the user accesses to the UDP request by successive calls to Spi_Ethernet_getByte()
     * the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
     * the function must return the length in bytes of the UDP reply, or 0 if nothing to transmit
     *
     * if you don't need to reply to UDP requests,
     * just define this function with a return(0) as single statement
     *
     */
    unsigned int    Spi_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort, unsigned int destPort, unsigned int reqLength)
            {
            unsigned int    len ;                           // my reply length
            unsigned char   *ptr ;                          // pointer to the dynamic buffer
    
            // reply is made of the remote host IP address in human readable format
            byteToStr(remoteHost[0], dyna) ;                // first IP address byte
            dyna[3] = '.' ;
            byteToStr(remoteHost[1], dyna + 4) ;            // second
            dyna[7] = '.' ;
            byteToStr(remoteHost[2], dyna + 8) ;            // third
            dyna[11] = '.' ;
            byteToStr(remoteHost[3], dyna + 12) ;           // fourth
    
            dyna[15] = ':' ;                                // add separator
    
            // then remote host port number
            intToStr(remotePort, dyna + 16) ;
            dyna[22] = '[' ;
            intToStr(destPort, dyna + 23) ;
            dyna[29] = ']' ;
            dyna[30] = 0 ;
    
            // the total length of the request is the length of the dynamic string plus the text of the request
            len = 30 + reqLength ;
    
            // puts the dynamic string into the transmit buffer
            ptr = dyna ;
            while(*ptr)
                    {
                    Spi_Ethernet_putByte(*ptr++) ;
                    }
    
            // then puts the request string converted into upper char into the transmit buffer
            while(reqLength--)
                    {
                    Spi_Ethernet_putByte(toupper(Spi_Ethernet_getByte())) ;
                    }
    
            return(len) ;           // back to the library with the length of the UDP reply
            }
    
    /*
     * main entry
     */
    void    main()
            {
            ADCON1 = 0x00 ;         // ADC convertors will be used
    
            PORTA = 0 ;
            TRISA = 0xff ;          // set PORTA as input for ADC
    
            PORTB = 0 ;
            TRISB = 0xff ;          // set PORTB as input for buttons
    
            PORTD = 0 ;
            TRISD = 0 ;             // set PORTD as output
            
            /*
             * starts ENC28J60 with :
             * reset bit on RC0
             * CS bit on RC1
             * my MAC & IP address
             * full duplex
             */
            Spi_Init();
            Spi_Ethernet_Init(&PORTD, 1, &PORTD, 0, myMacAddr, myIpAddr, Spi_Ethernet_FULLDUPLEX) ;
    
            while(1)                        // do forever
                    {
                    Spi_Ethernet_doPacket() ;   // process incoming Ethernet packets
                    portd.f5=1;
    
                    
                    /*
                     * add your stuff here if needed
                     * Spi_Ethernet_doPacket() must be called as often as possible
                     * otherwise packets could be lost
                     */
                    }
            }
  • lhthuong81
    Nhập môn đệ tử
    • May 2010
    • 1

    #2
    Ban phai cho ca nguon luon
    minh moi biet ma chia sua chu
    Lần sau đồng chí nhớ gõ tiếng việt nhé
    edit phamminhtuan

    Comment

    • diep9754
      Nhập môn đệ tử
      • Nov 2010
      • 7

      #3
      mikroC

      mình nạp mã vào chương trình mikroC v6.2 biên dịch chương trình báo lỗi demo limit
      nhưng khi xóa lệnh spi_ethernet_dopacket(); thì không báo lỗi .
      mình không biết làm thế nào để hàm spi_ethernet_dopacket(); không báo lỗi mong các bạn giải thích.
      thank!!

      Comment

      • dspic4011
        Đệ tử 4 túi
        • Jul 2008
        • 66

        #4
        Nguyên văn bởi diep9754 View Post
        mình nạp mã vào chương trình mikroC v6.2 biên dịch chương trình báo lỗi demo limit
        nhưng khi xóa lệnh spi_ethernet_dopacket(); thì không báo lỗi .
        mình không biết làm thế nào để hàm spi_ethernet_dopacket(); không báo lỗi mong các bạn giải thích.
        thank!!
        MikroC bán bản quyền mà, bạn chỉ sử dụng 1 số hàm đơn giản thôi. Chịu khó tìm cái crack là xong thôi, cái crack cũng dễ tìm lắm chịu khó bỏ chút thời gian là tìm được thôi.
        kit phát triển các loại: http://picdevelopmenttool.webs.com/index.htm
        Đã có LPC2103 kit, AT91SAM7S KIT và J_link v.7.

        Comment

        • diep9754
          Nhập môn đệ tử
          • Nov 2010
          • 7

          #5
          /*code

          /*
          * file : ethdemo.c
          * project : ENC28J60 SPI ETHERNET LIBRARY DEMO
          * author : Bruno Gavand
          * compiler : mikroC V6.2
          * date : october 27, 2006
          *
          * description :
          * This program shows how to use undocumented mikroC Spi Ethernet functions
          * This example is an UDP push server :
          *
          * Start Ethernet services with ARP and PING reply
          * Listen to the UDP port 33000 for an incoming request :
          * 'b' will start the push
          * 'e' will stop the stop
          * any other incoming char has no effect
          * If push is enabled :
          * send to the remote UDP host a string with PORTB value one time per second
          *
          * target device :
          * Tested with PIC18F452 and PIC18F4620 @ 32 Mhz (8 Mhz crystal + HS PLL)
          *
          * Licence :
          * Feel free to use this source code at your own risks.
          *
          * history :
          october 30, 2006 : ARP cache management, little bug fixed. Thanks Philippe !
          *
          * see more details on http://www.micro-examples.com/
          */

          #define NULL 0

          #define Spi_Ethernet_FULLDUPLEX 1

          #define TRANSMIT_START 0x19AE
          #define REPLY_START (TRANSMIT_START + 1) // reply buffer starts after per packet control byte

          // some ENC28J60 registers, see datasheet
          #define ERDPTL 0x00
          #define ERDPTH 0x01
          #define ECON1 0x1f
          #define EDMACSL 0x16
          #define EDMACSH 0x17

          /***********************************
          * RAM variables
          */
          unsigned char macAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f} ; // my MAC address

          unsigned char ipAddr[4] = {192, 168, 1, 101} ; // my IP address

          unsigned char destIpAddr[4] ; // IP address

          unsigned char transmit = 0 ;
          unsigned char tmr = 0 ;
          unsigned long longTmr = 0 ;
          unsigned int destPortNum = 0 ;
          char udpStr[16] = "PORTB=" ;

          #define ARPCACHELEN 3
          struct
          {
          unsigned char valid ;
          unsigned long tmr ;
          unsigned char ip[4] ;
          unsigned char mac[6] ;
          } arpCache[ARPCACHELEN] ;

          /*******************************************
          * functions
          */

          /*
          * ARP resolution
          * this function returns the MAC address of an IP address
          * an ARP cache is used
          */
          unsigned char *arpResolv(unsigned char *ip)
          {
          unsigned char i ; // general purpose register
          unsigned int rdptr ; // backup of ENC read pointer register
          unsigned char freeSlot ; // index of free slot in ARP cache
          unsigned long tmrSlot ; // oldest slot timer in ARP cache

          tmrSlot = 0xffffffff ; // will try to find less than this !

          // step in ARP cache
          for(i = 0 ; i < ARPCACHELEN; i++)
          {
          // oldest slots must expire
          if(arpCache[i].tmr < longTmr - 1000) // too old ?
          {
          arpCache[i].tmr = 0 ; // clear timer
          arpCache[i].valid = 0 ; // disable slot
          }

          // is it the address I want in a valid slot ?
          if(arpCache[i].valid && (memcmp(arpCache[i].ip, ip, 4) == 0))
          {
          return(arpCache[i].mac) ; // yes, return ready to use MAC addr
          }

          // find older slot, will be needed further
          if(arpCache[i].tmr < tmrSlot)
          {
          tmrSlot = arpCache[i].tmr ; // save best timer
          freeSlot = i ; // save best index
          }
          }

          // select ENC register bank 0
          Spi_Ethernet_clearBitReg(ECON1, 0b00000001) ;
          Spi_Ethernet_clearBitReg(ECON1, 0b00000010) ;

          /***************************
          * first, build eth header
          */
          Spi_Ethernet_memcpy(REPLY_START, "\xff\xff\xff\xff\xff\xff", 6) ; // destination is broadcast
          Spi_Ethernet_memcpy(REPLY_START + 6, macAddr, 6) ; // source : my mac addr
          Spi_Ethernet_writeMemory(REPLY_START + 12, 8, 6, 1) ; // protocol is ARP

          /****************************
          * second, build ARP packet
          */

          /*
          * 0, 1 : hardware type = ethernet
          * 8, 0 : protocole type = ip
          * 6, 4 : HW size = 6, protocol size = 4
          * 0, 1 : ARP opcode = request
          */
          Spi_Ethernet_memcpy(REPLY_START + 14, "\x0\x01\x08\x00\x06\x04\x00\x01", 8) ;

          Spi_Ethernet_memcpy(REPLY_START + 22, macAddr, 6) ; // mac addr source
          Spi_Ethernet_memcpy(REPLY_START + 28, ipAddr, 4) ; // ip addr source
          Spi_Ethernet_memcpy(REPLY_START + 32, "\0\0\0\0\0\0", 6) ; // mac addr destination : broadcast addr
          Spi_Ethernet_memcpy(REPLY_START + 38, ip, 4) ; // who has this ip addr ?

          /************************************************** *****************
          * third, send packet over wires, ARP request packet is 42 bytes len
          */
          Spi_Ethernet_txPacket(42) ;

          tmr = 0 ;
          while(tmr < 45) // allows around 3 seconds for reply
          {
          Spi_Ethernet_doPacket() ; // do not stop eth services !

          // select ENC register bank 0, may have been changed by library
          Spi_Ethernet_clearBitReg(ECON1, 0b00000001) ;
          Spi_Ethernet_clearBitReg(ECON1, 0b00000010) ;

          /*
          * ERDPT[H|L] registers are used by library :
          * always save them before doing anything else !
          */
          rdptr = (Spi_Ethernet_readReg(ERDPTH) << 8) + Spi_Ethernet_readReg(ERDPTL) ;

          /*
          * check if packet is ARP reply to my request (last byte = 2 means ARP reply)
          */
          if((Spi_Ethernet_memcmp(REPLY_START + 12, "\x08\x06\x00\x01\x08\x00\x06\x04\x00\x02", 10) == 0)
          && (Spi_Ethernet_memcmp(REPLY_START, macAddr, 6) == 0) // is it my MAC addr ?
          && (Spi_Ethernet_memcmp(REPLY_START + 28, ip, 4) == 0) // is it my IP addr ?
          )
          {
          /*
          * save remote MAC addr in a free slot of the cache
          */

          // copy MAC addr
          arpCache[freeSlot].mac[0] = Spi_Ethernet_readMem(REPLY_START + 22) ;
          arpCache[freeSlot].mac[1] = Spi_Ethernet_readMem(REPLY_START + 23) ;
          arpCache[freeSlot].mac[2] = Spi_Ethernet_readMem(REPLY_START + 24) ;
          arpCache[freeSlot].mac[3] = Spi_Ethernet_readMem(REPLY_START + 25) ;
          arpCache[freeSlot].mac[4] = Spi_Ethernet_readMem(REPLY_START + 26) ;
          arpCache[freeSlot].mac[5] = Spi_Ethernet_readMem(REPLY_START + 27) ;

          // copy IP addr
          memcpy(arpCache[freeSlot].ip, ip, 4) ;

          // enable slot
          arpCache[freeSlot].valid = 1 ;

          // timestamp
          arpCache[freeSlot].tmr = longTmr ;

          // restore ERDPT before exiting
          Spi_Ethernet_writeAddr(ERDPTL, rdptr) ;

          // return the MAC addr pointer
          return(arpCache[freeSlot].mac) ;
          }

          // restore ERDPT before doing a new call to the library
          Spi_Ethernet_writeAddr(ERDPTL, rdptr) ;
          }

          // failed, no response : MAC addr is null
          return((unsigned char *)NULL) ;
          }

          /*
          * send an UDP packet :
          * destIp : remote host IP address
          * sourcePort : local UDP source port number
          * destPort : destination UDP port number
          * pkt : pointer to packet to transmit
          * pktLen : length in bytes of packet to transmit
          */
          void sendUDP(unsigned char *destIP, unsigned int sourcePort, unsigned int destPort, unsigned char *pkt, unsigned int pktLen)
          {
          unsigned char *destMac ; // destination MAC addr
          static int idUniq ; // uniq packet id (serial number)
          unsigned char align ; // alignement flag
          unsigned int totlen ; // total packet length
          unsigned int rdptr ; // ENC read pointer backup

          // is destination port valid ?
          if(destPort == 0)
          {
          return ; // no, do nothing
          }

          // does destination IP address exist ?
          if((destMac = arpResolv(destIP)) == NULL)
          {
          return ; // no MAC addr matches, do nothing
          }

          // select ENC register bank 0
          Spi_Ethernet_clearBitReg(ECON1, 0b00000001) ;
          Spi_Ethernet_clearBitReg(ECON1, 0b00000010) ;

          /*
          * ERDPT[H|L] registers are used by library :
          * always save them before doing anything else !
          */
          rdptr = (Spi_Ethernet_readReg(ERDPTH) << 8) + Spi_Ethernet_readReg(ERDPTL) ;

          /**************************
          * first, build eth header
          */
          Spi_Ethernet_memcpy(REPLY_START, destMAC, 6) ; // destination
          Spi_Ethernet_memcpy(REPLY_START + 6, macAddr, 6) ; // source
          Spi_Ethernet_writeMemory(REPLY_START + 12, 8, 0, 1) ; // IP type

          /**************************
          * second, build IP header
          */
          totlen = 20 + 8 + pktLen ;
          Spi_Ethernet_writeMemory(REPLY_START + 14, 0x45, 0, 1) ; // IPV4, IHL = 20 bytes, TOS = 0
          Spi_Ethernet_writeMemory(REPLY_START + 16, totlen >> 8, totlen, 1) ; // total packet length
          Spi_Ethernet_memcpy(REPLY_START + 18, (char *)&(idUniq++), 2) ; // identification
          Spi_Ethernet_writeMemory(REPLY_START + 20, 0, 0, 1) ; // flags + 0, fragment offset = 0, TTL = 128, protocol = UDP
          Spi_Ethernet_writeMemory(REPLY_START + 22, 0x80, 0x11, 1) ; // flags + 0, fragment offset = 0, TTL = 128, protocol = UDP
          Spi_Ethernet_writeMemory(REPLY_START + 24, 0, 0, 1) ; // clear IP checksum
          Spi_Ethernet_memcpy(REPLY_START + 26, ipAddr, 4) ; // source
          Spi_Ethernet_memcpy(REPLY_START + 30, destIP, 4) ; // destination

          /***************************
          * third, build UDP header
          */
          totlen = pktLen + 8 ;
          Spi_Ethernet_writeMemory(REPLY_START + 34, sourcePort >> 8, sourcePort, 1) ; // source port
          Spi_Ethernet_writeMemory(REPLY_START + 36, destPort >> 8, destPort, 1) ; // destination port
          Spi_Ethernet_writeMemory(REPLY_START + 38, totlen >> 8, totlen, 1) ; // packet length
          Spi_Ethernet_writeMemory(REPLY_START + 40, 0, 0, 1) ; // clear UDP checksum

          Spi_Ethernet_memcpy(REPLY_START + 42, pkt, pktLen) ; // payload

          /*****************
          * fourth, IP checksum
          */
          Spi_Ethernet_checksum(REPLY_START + 14, 20) ;
          Spi_Ethernet_writeMemory(REPLY_START + 24, Spi_Ethernet_readReg(EDMACSH), Spi_Ethernet_readReg(EDMACSL), 1) ;

          /*****************
          * fifth, UDP checksum
          */
          // pseudo header
          // word alignement
          align = totlen & 1 ;
          Spi_Ethernet_writeMemory(REPLY_START + 42 + pktLen, 0, 0, 0) ; // clear

          // build pseudo header
          Spi_Ethernet_RAMcopy(REPLY_START + 26, REPLY_START + 26 + 8, REPLY_START + 42 + pktLen + align, 0) ;
          Spi_Ethernet_writeMemory(REPLY_START + 42 + pktLen + align + 8, 0, 17, 1) ;
          Spi_Ethernet_putByte(totlen >> 8) ;
          Spi_Ethernet_putByte(totlen) ;

          // ready for checksum
          Spi_Ethernet_checksum(REPLY_START + 34, totlen + 12 + align) ;
          Spi_Ethernet_writeMemory(REPLY_START + 40, Spi_Ethernet_readReg(EDMACSH), Spi_Ethernet_readReg(EDMACSL), 1) ;

          /**************************
          * sixth, send packet over wires
          */
          Spi_Ethernet_txPacket(42 + pktLen) ;

          // restore ERDPT registers before exiting
          Spi_Ethernet_writeAddr(ERDPTL, rdptr) ;
          }


          /*
          * no TCP
          */
          unsigned int Spi_Ethernet_userTCP(unsigned char *remoteHost, unsigned int remotePort, unsigned int localPort, unsigned int reqLength)
          {
          return(0) ;
          }

          /*
          * save remote UDP host and port number, then reply with 'Start'
          */
          unsigned int Spi_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort, unsigned int destPort, unsigned int reqLength)
          {
          if(destPort != 33000) return(0) ; // service is on port 33000

          switch(Spi_Ethernet_getByte())
          {
          // begin command
          case 'b':
          case 'B':
          transmit = 1 ; // set transmission flag
          memcpy(destIPAddr, remoteHost, 4) ; // save remote host IP addr
          destPortNum = remotePort ; // save remote host port number
          Spi_Ethernet_putByte('B') ; // reply with 'Begin' string
          Spi_Ethernet_putByte('e') ;
          Spi_Ethernet_putByte('g') ;
          Spi_Ethernet_putByte('i') ;
          Spi_Ethernet_putByte('n') ;
          return(5) ; // 5 bytes to transmit

          // end command
          case 'e':
          case 'E':
          transmit = 0 ; // clear transmission flag
          Spi_Ethernet_putByte('E') ; // reply with 'End'
          Spi_Ethernet_putByte('n') ;
          Spi_Ethernet_putByte('d') ;
          return(3) ; // 3 bytes to transmit

          // error
          default:
          Spi_Ethernet_putByte('?') ;
          return(1) ;
          }
          }

          /*
          * timers tmr and longTmr are incremented Fosc / 4 / 65536 / TMR1prescaler
          * TMR1prescaler is 8 (see main)
          * about 15.25 times per second with 32 Mhz clock
          */
          void interrupt()
          {
          if(PIR1.TMR1IF) // timer1 overflow ?
          {
          tmr++ ; // increment timers
          longTmr++ ;
          PIR1.TMR1IF = 0 ; // clear timer1 overflow flag
          }
          }
          /*
          * main entry
          */
          void main()
          {
          PORTB = 0 ;
          TRISB = 0xff ; // set PORTB as input

          PORTC = 0 ;
          TRISC = 0b11011100 ; // set PORTC as input except for bits 0 (RESET) and 1 (CS)

          T1CON = 0b10110101 ; // 16 bits, from other source, prescaler 1:8, oscillator disabled, not synchronized, internal clock, enabled
          PIR1.TMR1IF = 0 ; // clear TMR1 overflow interrupt flag
          PIE1.TMR1IE = 1 ; // enable interrupt on TMR1 overflow
          INTCON |= 0b11000000 ; // enable global & peripheral interrupts

          // init ARP cache
          memset(&arpCache, 0, sizeof(arpCache)) ;

          /*
          * starts Spi_Ethernet with :
          * reset bit on RC0,
          * CS bit on RC1,
          * my MAC & IP address,
          * full duplex
          */
          Spi_Init() ;
          Spi_Ethernet_Init(&PORTC, 0, &PORTC, 1, macAddr, ipAddr, Spi_Ethernet_FULLDUPLEX) ;

          while(1) // do forever
          {
          Spi_Ethernet_doPacket() ; // process incoming Ethernet packets

          if(transmit && (tmr > 15)) // transmit one UDP packet per second
          {
          ByteToStr(PORTB, udpStr + 6) ; // read PORTB value and convert to string
          sendUDP(destIpAddr, 3456, destPortNum, udpStr, sizeof(udpStr)) ; // send to remote host
          tmr = 0 ; // reset timer
          }
          }
          }

          Comment

          • diep9754
            Nhập môn đệ tử
            • Nov 2010
            • 7

            #6
            /*code

            /*
            * file : ethdemo.c
            * project : ENC28J60 SPI ETHERNET LIBRARY DEMO
            * author : Bruno Gavand
            * compiler : mikroC V6.2
            * date : october 27, 2006
            *
            * description :
            * This program shows how to use undocumented mikroC Spi Ethernet functions
            * This example is an UDP push server :
            *
            * Start Ethernet services with ARP and PING reply
            * Listen to the UDP port 33000 for an incoming request :
            * 'b' will start the push
            * 'e' will stop the stop
            * any other incoming char has no effect
            * If push is enabled :
            * send to the remote UDP host a string with PORTB value one time per second
            *
            * target device :
            * Tested with PIC18F452 and PIC18F4620 @ 32 Mhz (8 Mhz crystal + HS PLL)
            *
            * Licence :
            * Feel free to use this source code at your own risks.
            *
            * history :
            october 30, 2006 : ARP cache management, little bug fixed. Thanks Philippe !
            *
            * see more details on http://www.micro-examples.com/
            */

            #define NULL 0

            #define Spi_Ethernet_FULLDUPLEX 1

            #define TRANSMIT_START 0x19AE
            #define REPLY_START (TRANSMIT_START + 1) // reply buffer starts after per packet control byte

            // some ENC28J60 registers, see datasheet
            #define ERDPTL 0x00
            #define ERDPTH 0x01
            #define ECON1 0x1f
            #define EDMACSL 0x16
            #define EDMACSH 0x17

            /***********************************
            * RAM variables
            */
            unsigned char macAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f} ; // my MAC address

            unsigned char ipAddr[4] = {192, 168, 1, 101} ; // my IP address

            unsigned char destIpAddr[4] ; // IP address

            unsigned char transmit = 0 ;
            unsigned char tmr = 0 ;
            unsigned long longTmr = 0 ;
            unsigned int destPortNum = 0 ;
            char udpStr[16] = "PORTB=" ;

            #define ARPCACHELEN 3
            struct
            {
            unsigned char valid ;
            unsigned long tmr ;
            unsigned char ip[4] ;
            unsigned char mac[6] ;
            } arpCache[ARPCACHELEN] ;

            /*******************************************
            * functions
            */

            /*
            * ARP resolution
            * this function returns the MAC address of an IP address
            * an ARP cache is used
            */
            unsigned char *arpResolv(unsigned char *ip)
            {
            unsigned char i ; // general purpose register
            unsigned int rdptr ; // backup of ENC read pointer register
            unsigned char freeSlot ; // index of free slot in ARP cache
            unsigned long tmrSlot ; // oldest slot timer in ARP cache

            tmrSlot = 0xffffffff ; // will try to find less than this !

            // step in ARP cache
            for(i = 0 ; i < ARPCACHELEN; i++)
            {
            // oldest slots must expire
            if(arpCache[i].tmr < longTmr - 1000) // too old ?
            {
            arpCache[i].tmr = 0 ; // clear timer
            arpCache[i].valid = 0 ; // disable slot
            }

            // is it the address I want in a valid slot ?
            if(arpCache[i].valid && (memcmp(arpCache[i].ip, ip, 4) == 0))
            {
            return(arpCache[i].mac) ; // yes, return ready to use MAC addr
            }

            // find older slot, will be needed further
            if(arpCache[i].tmr < tmrSlot)
            {
            tmrSlot = arpCache[i].tmr ; // save best timer
            freeSlot = i ; // save best index
            }
            }

            // select ENC register bank 0
            Spi_Ethernet_clearBitReg(ECON1, 0b00000001) ;
            Spi_Ethernet_clearBitReg(ECON1, 0b00000010) ;

            /***************************
            * first, build eth header
            */
            Spi_Ethernet_memcpy(REPLY_START, "\xff\xff\xff\xff\xff\xff", 6) ; // destination is broadcast
            Spi_Ethernet_memcpy(REPLY_START + 6, macAddr, 6) ; // source : my mac addr
            Spi_Ethernet_writeMemory(REPLY_START + 12, 8, 6, 1) ; // protocol is ARP

            /****************************
            * second, build ARP packet
            */

            /*
            * 0, 1 : hardware type = ethernet
            * 8, 0 : protocole type = ip
            * 6, 4 : HW size = 6, protocol size = 4
            * 0, 1 : ARP opcode = request
            */
            Spi_Ethernet_memcpy(REPLY_START + 14, "\x0\x01\x08\x00\x06\x04\x00\x01", 8) ;

            Spi_Ethernet_memcpy(REPLY_START + 22, macAddr, 6) ; // mac addr source
            Spi_Ethernet_memcpy(REPLY_START + 28, ipAddr, 4) ; // ip addr source
            Spi_Ethernet_memcpy(REPLY_START + 32, "\0\0\0\0\0\0", 6) ; // mac addr destination : broadcast addr
            Spi_Ethernet_memcpy(REPLY_START + 38, ip, 4) ; // who has this ip addr ?

            /************************************************** *****************
            * third, send packet over wires, ARP request packet is 42 bytes len
            */
            Spi_Ethernet_txPacket(42) ;

            tmr = 0 ;
            while(tmr < 45) // allows around 3 seconds for reply
            {
            Spi_Ethernet_doPacket() ; // do not stop eth services !

            // select ENC register bank 0, may have been changed by library
            Spi_Ethernet_clearBitReg(ECON1, 0b00000001) ;
            Spi_Ethernet_clearBitReg(ECON1, 0b00000010) ;

            /*
            * ERDPT[H|L] registers are used by library :
            * always save them before doing anything else !
            */
            rdptr = (Spi_Ethernet_readReg(ERDPTH) << 8) + Spi_Ethernet_readReg(ERDPTL) ;

            /*
            * check if packet is ARP reply to my request (last byte = 2 means ARP reply)
            */
            if((Spi_Ethernet_memcmp(REPLY_START + 12, "\x08\x06\x00\x01\x08\x00\x06\x04\x00\x02", 10) == 0)
            && (Spi_Ethernet_memcmp(REPLY_START, macAddr, 6) == 0) // is it my MAC addr ?
            && (Spi_Ethernet_memcmp(REPLY_START + 28, ip, 4) == 0) // is it my IP addr ?
            )
            {
            /*
            * save remote MAC addr in a free slot of the cache
            */

            // copy MAC addr
            arpCache[freeSlot].mac[0] = Spi_Ethernet_readMem(REPLY_START + 22) ;
            arpCache[freeSlot].mac[1] = Spi_Ethernet_readMem(REPLY_START + 23) ;
            arpCache[freeSlot].mac[2] = Spi_Ethernet_readMem(REPLY_START + 24) ;
            arpCache[freeSlot].mac[3] = Spi_Ethernet_readMem(REPLY_START + 25) ;
            arpCache[freeSlot].mac[4] = Spi_Ethernet_readMem(REPLY_START + 26) ;
            arpCache[freeSlot].mac[5] = Spi_Ethernet_readMem(REPLY_START + 27) ;

            // copy IP addr
            memcpy(arpCache[freeSlot].ip, ip, 4) ;

            // enable slot
            arpCache[freeSlot].valid = 1 ;

            // timestamp
            arpCache[freeSlot].tmr = longTmr ;

            // restore ERDPT before exiting
            Spi_Ethernet_writeAddr(ERDPTL, rdptr) ;

            // return the MAC addr pointer
            return(arpCache[freeSlot].mac) ;
            }

            // restore ERDPT before doing a new call to the library
            Spi_Ethernet_writeAddr(ERDPTL, rdptr) ;
            }

            // failed, no response : MAC addr is null
            return((unsigned char *)NULL) ;
            }

            /*
            * send an UDP packet :
            * destIp : remote host IP address
            * sourcePort : local UDP source port number
            * destPort : destination UDP port number
            * pkt : pointer to packet to transmit
            * pktLen : length in bytes of packet to transmit
            */
            void sendUDP(unsigned char *destIP, unsigned int sourcePort, unsigned int destPort, unsigned char *pkt, unsigned int pktLen)
            {
            unsigned char *destMac ; // destination MAC addr
            static int idUniq ; // uniq packet id (serial number)
            unsigned char align ; // alignement flag
            unsigned int totlen ; // total packet length
            unsigned int rdptr ; // ENC read pointer backup

            // is destination port valid ?
            if(destPort == 0)
            {
            return ; // no, do nothing
            }

            // does destination IP address exist ?
            if((destMac = arpResolv(destIP)) == NULL)
            {
            return ; // no MAC addr matches, do nothing
            }

            // select ENC register bank 0
            Spi_Ethernet_clearBitReg(ECON1, 0b00000001) ;
            Spi_Ethernet_clearBitReg(ECON1, 0b00000010) ;

            /*
            * ERDPT[H|L] registers are used by library :
            * always save them before doing anything else !
            */
            rdptr = (Spi_Ethernet_readReg(ERDPTH) << 8) + Spi_Ethernet_readReg(ERDPTL) ;

            /**************************
            * first, build eth header
            */
            Spi_Ethernet_memcpy(REPLY_START, destMAC, 6) ; // destination
            Spi_Ethernet_memcpy(REPLY_START + 6, macAddr, 6) ; // source
            Spi_Ethernet_writeMemory(REPLY_START + 12, 8, 0, 1) ; // IP type

            /**************************
            * second, build IP header
            */
            totlen = 20 + 8 + pktLen ;
            Spi_Ethernet_writeMemory(REPLY_START + 14, 0x45, 0, 1) ; // IPV4, IHL = 20 bytes, TOS = 0
            Spi_Ethernet_writeMemory(REPLY_START + 16, totlen >> 8, totlen, 1) ; // total packet length
            Spi_Ethernet_memcpy(REPLY_START + 18, (char *)&(idUniq++), 2) ; // identification
            Spi_Ethernet_writeMemory(REPLY_START + 20, 0, 0, 1) ; // flags + 0, fragment offset = 0, TTL = 128, protocol = UDP
            Spi_Ethernet_writeMemory(REPLY_START + 22, 0x80, 0x11, 1) ; // flags + 0, fragment offset = 0, TTL = 128, protocol = UDP
            Spi_Ethernet_writeMemory(REPLY_START + 24, 0, 0, 1) ; // clear IP checksum
            Spi_Ethernet_memcpy(REPLY_START + 26, ipAddr, 4) ; // source
            Spi_Ethernet_memcpy(REPLY_START + 30, destIP, 4) ; // destination

            /***************************
            * third, build UDP header
            */
            totlen = pktLen + 8 ;
            Spi_Ethernet_writeMemory(REPLY_START + 34, sourcePort >> 8, sourcePort, 1) ; // source port
            Spi_Ethernet_writeMemory(REPLY_START + 36, destPort >> 8, destPort, 1) ; // destination port
            Spi_Ethernet_writeMemory(REPLY_START + 38, totlen >> 8, totlen, 1) ; // packet length
            Spi_Ethernet_writeMemory(REPLY_START + 40, 0, 0, 1) ; // clear UDP checksum

            Spi_Ethernet_memcpy(REPLY_START + 42, pkt, pktLen) ; // payload

            /*****************
            * fourth, IP checksum
            */
            Spi_Ethernet_checksum(REPLY_START + 14, 20) ;
            Spi_Ethernet_writeMemory(REPLY_START + 24, Spi_Ethernet_readReg(EDMACSH), Spi_Ethernet_readReg(EDMACSL), 1) ;

            /*****************
            * fifth, UDP checksum
            */
            // pseudo header
            // word alignement
            align = totlen & 1 ;
            Spi_Ethernet_writeMemory(REPLY_START + 42 + pktLen, 0, 0, 0) ; // clear

            // build pseudo header
            Spi_Ethernet_RAMcopy(REPLY_START + 26, REPLY_START + 26 + 8, REPLY_START + 42 + pktLen + align, 0) ;
            Spi_Ethernet_writeMemory(REPLY_START + 42 + pktLen + align + 8, 0, 17, 1) ;
            Spi_Ethernet_putByte(totlen >> 8) ;
            Spi_Ethernet_putByte(totlen) ;

            // ready for checksum
            Spi_Ethernet_checksum(REPLY_START + 34, totlen + 12 + align) ;
            Spi_Ethernet_writeMemory(REPLY_START + 40, Spi_Ethernet_readReg(EDMACSH), Spi_Ethernet_readReg(EDMACSL), 1) ;

            /**************************
            * sixth, send packet over wires
            */
            Spi_Ethernet_txPacket(42 + pktLen) ;

            // restore ERDPT registers before exiting
            Spi_Ethernet_writeAddr(ERDPTL, rdptr) ;
            }


            /*
            * no TCP
            */
            unsigned int Spi_Ethernet_userTCP(unsigned char *remoteHost, unsigned int remotePort, unsigned int localPort, unsigned int reqLength)
            {
            return(0) ;
            }

            /*
            * save remote UDP host and port number, then reply with 'Start'
            */
            unsigned int Spi_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort, unsigned int destPort, unsigned int reqLength)
            {
            if(destPort != 33000) return(0) ; // service is on port 33000

            switch(Spi_Ethernet_getByte())
            {
            // begin command
            case 'b':
            case 'B':
            transmit = 1 ; // set transmission flag
            memcpy(destIPAddr, remoteHost, 4) ; // save remote host IP addr
            destPortNum = remotePort ; // save remote host port number
            Spi_Ethernet_putByte('B') ; // reply with 'Begin' string
            Spi_Ethernet_putByte('e') ;
            Spi_Ethernet_putByte('g') ;
            Spi_Ethernet_putByte('i') ;
            Spi_Ethernet_putByte('n') ;
            return(5) ; // 5 bytes to transmit

            // end command
            case 'e':
            case 'E':
            transmit = 0 ; // clear transmission flag
            Spi_Ethernet_putByte('E') ; // reply with 'End'
            Spi_Ethernet_putByte('n') ;
            Spi_Ethernet_putByte('d') ;
            return(3) ; // 3 bytes to transmit

            // error
            default:
            Spi_Ethernet_putByte('?') ;
            return(1) ;
            }
            }

            /*
            * timers tmr and longTmr are incremented Fosc / 4 / 65536 / TMR1prescaler
            * TMR1prescaler is 8 (see main)
            * about 15.25 times per second with 32 Mhz clock
            */
            void interrupt()
            {
            if(PIR1.TMR1IF) // timer1 overflow ?
            {
            tmr++ ; // increment timers
            longTmr++ ;
            PIR1.TMR1IF = 0 ; // clear timer1 overflow flag
            }
            }
            /*
            * main entry
            */
            void main()
            {
            PORTB = 0 ;
            TRISB = 0xff ; // set PORTB as input

            PORTC = 0 ;
            TRISC = 0b11011100 ; // set PORTC as input except for bits 0 (RESET) and 1 (CS)

            T1CON = 0b10110101 ; // 16 bits, from other source, prescaler 1:8, oscillator disabled, not synchronized, internal clock, enabled
            PIR1.TMR1IF = 0 ; // clear TMR1 overflow interrupt flag
            PIE1.TMR1IE = 1 ; // enable interrupt on TMR1 overflow
            INTCON |= 0b11000000 ; // enable global & peripheral interrupts

            // init ARP cache
            memset(&arpCache, 0, sizeof(arpCache)) ;

            /*
            * starts Spi_Ethernet with :
            * reset bit on RC0,
            * CS bit on RC1,
            * my MAC & IP address,
            * full duplex
            */
            Spi_Init() ;
            Spi_Ethernet_Init(&PORTC, 0, &PORTC, 1, macAddr, ipAddr, Spi_Ethernet_FULLDUPLEX) ;

            while(1) // do forever
            {
            Spi_Ethernet_doPacket() ; // process incoming Ethernet packets

            if(transmit && (tmr > 15)) // transmit one UDP packet per second
            {
            ByteToStr(PORTB, udpStr + 6) ; // read PORTB value and convert to string
            sendUDP(destIpAddr, 3456, destPortNum, udpStr, sizeof(udpStr)) ; // send to remote host
            tmr = 0 ; // reset timer
            }
            }
            }

            Comment

            • diep9754
              Nhập môn đệ tử
              • Nov 2010
              • 7

              #7
              mình đã crack rồi nhung hàm spi_ethernet_dopacket() ; vẫn không dùng được
              xóa nó thì biên dịch vẫn được
              bạn có thể chỉ giúp mình , được ko ,thank

              Comment

              • dspic4011
                Đệ tử 4 túi
                • Jul 2008
                • 66

                #8
                Nguyên văn bởi diep9754 View Post
                mình đã crack rồi nhung hàm spi_ethernet_dopacket() ; vẫn không dùng được
                xóa nó thì biên dịch vẫn được
                bạn có thể chỉ giúp mình , được ko ,thank
                Bạn remove cái cũ đi rồi cài lại cái này nhé.
                kit phát triển các loại: http://picdevelopmenttool.webs.com/index.htm
                Đã có LPC2103 kit, AT91SAM7S KIT và J_link v.7.

                Comment

                Working...