Did you find this site useful ? Please
to help www.micro-examples.com

If you need a coder or a freelance programmer, submit your project to me


The Secret Functions of MikroC Ethernet Library for ENC28J60

Printer-friendly version | Forums | FAQs |

This page will show you how to use advanced mikroC ENC28J60 ethernet library calls :

  • prototypes of low level functions
  • how to read and write raw packets
  • a source code to demonstrate the use of the hidden function calls


DISCLAIMER
Before all, please read this carefully :

  • This is NOT an official manual of the MikroC SPI Ethernet library.
  • MikroElektronika is NOT responsible for this content.
  • The information below are given without any kind of guarantee : USE IT AT YOUR OWN RISKS, and don't bother me if they cause damage or malfunction.

The reader is supposed :

If you have any question, comment, or bug report, you are welcome : please post it to my forum.


Page index :


LOW LEVEL FUNCTIONS

Here are SPI Ethernet mikroC functions, as they are supposed to be.

They should be the same for mikroPascal (see here) and mikroBasic.

READ ENC28J60 REGISTER

PROTOTYPE unsigned char   Spi_Ethernet_readReg(unsigned char addr) ;
PARAMETERS

address of ENC28J60 register to read

RETURNS value of register @ addr in current bank selection
DESCRIPTION

read an ENC28J60 register

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE b = Spi_Ethernet_readReg(0x10) ;

 

WRITE ENC28J60 REGISTER

PROTOTYPE void    Spi_Ethernet_writeReg(unsigned char addr, unsigned short v) ;
PARAMETERS

        addr    : address of ENC28J60 register to write in current bank selection
        v       : value to write

RETURNS nothing
DESCRIPTION

writes a byte to an ENC28J60 register

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_writeReg(0x10, 0xff) ;

 

WRITE ENC28J20 ADDRESS REGISTER

PROTOTYPE void    Spi_Ethernet_writeAddr(unsigned char addr, unsigned int v) ;
PARAMETERS

       addr    : address of ENC28J60 register to write in current bank selection
        v       : value to write

RETURNS nothing
DESCRIPTION

writes an ENC28J60 register with high and low part, usefull to write address registers

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_writeReg(0x10, 0x1234) ;

 

SET BITS OF ENC28J60 REGISTER

PROTOTYPE void    Spi_Ethernet_setBitReg(unsigned char addr, unsigned char mask) ;
PARAMETERS

        addr    : address of ENC28J60 register
        mask    : bit mask of bits to set

RETURNS nothing
DESCRIPTION

ENC28J60 register is ORed with mask

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_setBitReg(0x12, 0b00010010) ;

 

CLEAR BITS OF ENC28J60 REGISTER

PROTOTYPE void    Spi_Ethernet_clearBitReg(unsigned char addr, unsigned char mask) ;
PARAMETERS

        addr    : address of ENC28J60 register
        mask    : bit mask of bits to clear

RETURNS nothing
DESCRIPTION

ENC28J60 register is ANDed with complement of mask

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_clearBitReg(0x12, 0b00010010) ;

 

READ ENC28J60 PHY REGISTER

PROTOTYPE void    Spi_Ethernet_writePHY(unsigned char reg, unsigned short *h, unsigned short *l) ;
PARAMETERS

        reg     : address of ENC28J60 PHY
        h       : pointer to high byte storage location
        l       : pointer to low byte storage location

RETURNS nothing
DESCRIPTION

reads high and low bytes from PHY register

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_writePHY(3, &h, &l) ;

 

WRITE ENC28J60 PHY REGISTER

PROTOTYPE void    Spi_Ethernet_writePHY(unsigned char reg, unsigned short h, unsigned short l) ;
PARAMETERS

        reg     : address of ENC28J60 PHY
        h       : high byte to write to register
        l       : low byte to write to register

RETURNS nothing
DESCRIPTION

writes high and low bytes to PHY register

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_writePHY(3, 0, 0) ;

 

READ ONE BYTE FROM ENC28J60 INTERNAL MEMORY

PROTOTYPE unsigned char   Spi_Ethernet_readMem(unsigned int addr) ;
PARAMETERS

addr    : address of byte to read

RETURNS value of byte @ addr
DESCRIPTION

read one byte from ENC28J60 RAM

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE b = Spi_Ethernet_readMem(0x0250) ;

 

STORE BYTES TO ENC28J60 INTERNAL MEMORY

PROTOTYPE void Spi_Ethernet_writeMemory(unsigned int addr, unsigned char v1, unsigned char v2, unsigned char bis) ;
PARAMETERS

       addr    : destination address of first byte in ENC28J60 RAM
        v1      : value to store @ addr
        v2      : value to store @ addr + 1 if bis is set
        bis     : if 0: store only v1 (v2 is ignored), otherwise store also v2

RETURNS nothing
DESCRIPTION

store one or two bytes to ENC28J60 RAM

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_writeMemory(0x100, 12, 0, 0) ;

 

COPY PIC MEMORY TO ENC28J60 INTERNAL MEMORY

PROTOTYPE void Spi_Ethernet_memcpy(unsigned int addr, unsigned char *s, unsigned char l) ;
PARAMETERS

        addr    : destination address of first byte in ENC28J60 RAM
        s       : pointer to first byte of PIC RAM to copy to ENC28J60 
        l       : length in bytes of memory to copy

RETURNS nothing
DESCRIPTION

copy PIC memory to ENC28J60 RAM

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_memcpy(0x0600, "TEST", 4) ;

 

COMPARE PIC MEMORY TO ENC28J60 INTERNAL MEMORY

PROTOTYPE unsigned char Spi_Ethernet_memcmp(unsigned int addr, unsigned char *s, unsigned char l) ;
PARAMETERS

        addr    : address of first byte in ENC28J60 RAM to compare
        s       : pointer to first byte of PIC RAM to compare
        l       : length in bytes of memory to compare

RETURNS 0 if memories match, > 0 otherwise
DESCRIPTION

compares ENC28J60 RAM from address addr to PIC RAM pointed to by s, on l bytes length

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_memcmp(0x0600, "TEST", 4) ;

 

CHECKSUM CALCULATION (DMA OPERATION)

PROTOTYPE void Spi_Ethernet_checksum(unsigned int start, unsigned int l) ;
PARAMETERS

start : address of first byte in ENC28J60 memory
l : number of bytes to include in checksum calculation

RETURNS nothing, checksum is in ENC28J60 EDMACS[H:L] registers
DESCRIPTION ENC28J60 performs DMA checksum of l bytes starting from start addr, using ENC28J60 built-in DMA operation
REQUIRES Spi_Ethernet_init must have been called
EXAMPLE Spi_Ethernet_checksum(0x1000, 60) ;

 


ENC28J60 INTERNAL RAM COPY (DMA OPERATION)

PROTOTYPE void Spi_Ethernet_RAMcopy(unsigned int start, unsigned int stop, unsigned int dest, unsigned char w) ;
PARAMETERS

        start           address of first source byte (included) in ENC memory to copy
        stop           address of last source byte (not included) in ENC memory to copy
        dest           address of first destination byte in ENC memory
        w               mode : 0 = no wrap (copy from transmit buffer), 1 = wrap (copy from receive buffer)

RETURNS nothing
DESCRIPTION ENC28J60 performs DMA memory copy from start to dest, using ENC28J60 built-in DMA operation.
if wrap is allowed, performs correct operation to avoid ENC28J60 hang on circular buffer
REQUIRES Spi_Ethernet_init must have been called
EXAMPLE Spi_Ethernet_RAMcopy(0x500, 0x600, 0x1400, 1) ;

 

TRANSMIT PACKET

PROTOTYPE void Spi_Ethernet_TXpacket(unsigned int l) ;
PARAMETERS

l : length in bytes of packet to transmit

RETURNS nothing
DESCRIPTION

send packet over wires
l bytes are sent, starting form ENC internal address REPLY_START

REQUIRES

Spi_Ethernet_init must have been called 

EXAMPLE Spi_Ethernet_TXpacket(60) ;

 


LIBRARY OVERVIEW

Here is what you have to know, and to keep in mind, when using the functions above.

Please respect this few rules if you want to mix successfully mikroC user's functions with your own library calls :

  • Always call Spi_Ethernet_doPacket() as often as possible : this function manages ENC28J60 hardware and replies to ARP, PING, UDP and TCP requests. If you don't, the internal circular receive buffer of ENC28J60 may overlap, incoming packets will be lost or delayed.
  • You don't need to call a receive function : Spi_Ethernet_doPacket() does it. This function returns with the last incoming packet ready to use at address REPLY_START in the ENC28J60 RAM. Just parse from this location to get the last incoming packet.
  • You must protect ERDPTL and ERDPTH registers (register bank 0) : they are essential to the library. So read them after a call Spi_Ethernet_doPacket() and write them back before a new call.
  • Don't try to modify ENC28J60 registers : library will be corrupted
  • Don't write memory below REPLY_START : incoming packets will be corrupted
  • The transmit buffer REPLY_START is at address 0x19AE in ENC28J60 internal memory


PROGRAM EXAMPLE

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

 You can test it with the built-in UDP terminal of your MikroElektronika compiler (Tools -> UDP Terminal).

Here is a screen capture :

ENC28J60 SPI ETHERNET test program screen capture

 

Type here the IP address of your board, the port number 33000, then click "Connect"

 

Type here your requests, end with carriage return (or click "Send") :
b : begin push
e : end push

 

 

 History of your commands are here

 

 

 

 

 

 

UDP packets received from ENC28J60 bord are here (I played with PORTB buttons during test)

 

 

 

 

 

The hardware is the one described in the mikroC manual, the software has been tested with the mikroElektronika Serial Ethernet Board, and with my own board too.

 

MIKROC SOURCE CODE EXAMPLE

Create a new mikroC project for your PIC18 target, copy/paste this source code into editor, change your MAC and IP addresses in macAddr and IpAddr variables and just build the project.

/*
 * 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
                        }
                }
        }

 

mikroPascal Source Code EXAMPLE

Philippe Celma did the translation from the original mikroC source code into mikroPascal, it is fully documented and works exactly the same.

You can download its mikroPascal project from here :

ENC28J60-LIBRARY-Spi_Ethernet_TxPacket_mikroPascal.ZIP (Zip file, 5.56 Ko).

Like the mikroC example, just set your own MAC and IP addresses in the source code before building the project.

Thank you Philippe  !

 

 

All trademarks and registered trademarks are the property of their respective owners