Ethernet PIC18FxxJ60 Library
PIC18FxxJ60 family of microcontrollers feature an embedded Ethernet controller module.
This is a complete connectivity solution, including full implementations of both
Media Access Control (MAC) and Physical Layer transceiver (PHY) modules. Two pulse
transformers and a few passive components are all that are required to connect the
microcontroller directly to an Ethernet network.
The Ethernet module meets all of the IEEE 802.3 specifications for 10-BaseT connectivity to a twisted-pair network. It incorporates a number of packet filtering schemes to limit incoming packets. It also provides an internal DMA module for fast data throughput and hardware assisted IP checksum calculations. Provisions are also made for two LED outputs to indicate link and network activity
This library provides the posibility to easily utilize ethernet feature of the above mentioned MCUs.
Ethernet PIC18FxxJ60 library supports:
- IPv4 protocol.
- ARP requests.
- ICMP echo requests.
- UDP requests.
- TCP requests (no stack, no packet reconstruction).
- ARP client with cache.
- DNS client.
- UDP client.
- DHCP client.
- packet fragmentation is NOT supported.
Important :
- Global library variable
Ethernet_userTimerSecis used to keep track of time for all client implementations (ARP, DNS, UDP and DHCP). It is user responsibility to increment this variable each second in it's code if any of the clients is used. - For advanced users there is
__EthJ60Private.mpasunit in Uses\P18 folder of the compiler with description of all routines and global variables, relevant to the user, implemented in the Ethernet PIC18FxxJ60 Library.
Library Routines
- Ethernet_Init
- Ethernet_Enable
- Ethernet_Disable
- Ethernet_doPacket
- Ethernet_putByte
- Ethernet_putBytes
- Ethernet_putString
- Ethernet_putConstString
- Ethernet_putConstBytes
- Ethernet_getByte
- Ethernet_getBytes
- Ethernet_UserTCP
- Ethernet_UserUDP
- Ethernet_getIpAddress
- Ethernet_getGwIpAddress
- Ethernet_getDnsIpAddress
- Ethernet_getIpMask
- Ethernet_confNetwork
- Ethernet_arpResolve
- Ethernet_sendUDP
- Ethernet_dnsResolve
- Ethernet_initDHCP
- Ethernet_doDHCPLeaseTime
- Ethernet_renewDHCP
Ethernet_Init
| Prototype |
procedure Ethernet_Init(var mac : array[6] of byte; var ip : array[4] of byte; fullDuplex : byte); |
|---|---|
| Returns |
Nothing. |
| Description |
This is MAC module routine. It initializes Ethernet controller. This function is internaly splited into 2 parts to help linker when coming short of memory. Ethernet controller settings (parameters not mentioned here are set to default):
Parameters:
Note :
If a DHCP server is to be used, IP address should be set to 0.0.0.0.
|
| Requires | Nothing. |
| Example |
var
myMacAddr : array[6] of byte; // my MAC address
myIpAddr : array[4] of byte; // my IP addr
...
myMacAddr[0] := 0x00;
myMacAddr[1] := 0x14;
myMacAddr[2] := 0xA5;
myMacAddr[3] := 0x76;
myMacAddr[4] := 0x19;
myMacAddr[5] := 0x3F;
myIpAddr[0] := 192;
myIpAddr[1] := 168;
myIpAddr[2] := 20;
myIpAddr[3] := 60;
Ethernet_Init(myMacAddr, myIpAddr, Ethernet_FULLDUPLEX);
|
Ethernet_Enable
| Prototype |
procedure Ethernet_Enable(enFlt : byte); |
||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Returns |
Nothing. |
||||||||||||||||||||||||||||||||||||
| Description |
This is MAC module routine. This routine enables appropriate network traffic on the MCU's internal Ethernet module by the means of it's receive filters (unicast, multicast, broadcast, crc). Specific type of network traffic will be enabled if a corresponding bit of this routine's input parameter is set. Therefore, more than one type of network traffic can be enabled at the same time. For this purpose, predefined library constants (see the table below) can be ORed to form appropriate input value. Parameters:
Note :
|
||||||||||||||||||||||||||||||||||||
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
||||||||||||||||||||||||||||||||||||
| Example |
Ethernet_Enable(_Ethernet_CRC or _Ethernet_UNICAST); // enable CRC checking and Unicast traffic |
Ethernet_Disable
| Prototype |
procedure Ethernet_Disable(disFlt : byte); |
||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Returns |
Nothing. |
||||||||||||||||||||||||||||||||||||
| Description |
This is MAC module routine. This routine disables appropriate network traffic on the MCU's internal Ethernet module by the means of it's receive filters (unicast, multicast, broadcast, crc). Specific type of network traffic will be disabled if a corresponding bit of this routine's input parameter is set. Therefore, more than one type of network traffic can be disabled at the same time. For this purpose, predefined library constants (see the table below) can be ORed to form appropriate input value. Parameters:
Note :
|
||||||||||||||||||||||||||||||||||||
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
||||||||||||||||||||||||||||||||||||
| Example |
Ethernet_Disable(_Ethernet_CRC or _Ethernet_UNICAST); // disable CRC checking and Unicast traffic |
Ethernet_doPacket
| Prototype |
function Ethernet_doPacket() : byte; |
|---|---|
| Returns |
|
| Description |
This is MAC module routine. It processes next received packet if such exists. Packets are processed in the following manner:
Note :
Ethernet_doPacket must be called as often as possible in user's code.
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
while true do
begin
...
Ethernet_doPacket(); // process received packets
...
end;
|
Ethernet_putByte
| Prototype |
procedure Ethernet_putByte(v : byte); |
|---|---|
| Returns |
Nothing. |
| Description |
This is MAC module routine. It stores one byte to address pointed by the current Ethernet controller's write pointer ( Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var data : byte; ... Ethernet_putByte(data); // put an byte into ethernet buffer |
Ethernet_putBytes
| Prototype |
procedure Ethernet_putBytes(ptr : ^byte; n : word); |
|---|---|
| Returns |
Nothing. |
| Description |
This is MAC module routine. It stores requested number of bytes into Ethernet controller's RAM starting from current Ethernet controller's write pointer ( Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var buffer : array[17] of byte; ... buffer := 'mikroElektronika'; ... Ethernet_putBytes(buffer, 16); // put an RAM array into ethernet buffer |
Ethernet_putConstBytes
| Prototype |
procedure Ethernet_putConstBytes(const ptr : ^byte; n : word); |
|---|---|
| Returns |
Nothing. |
| Description |
This is MAC module routine. It stores requested number of const bytes into Ethernet controller's RAM starting from current Ethernet controller's write pointer ( Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
const buffer : array[17] of byte; ... buffer := 'mikroElektronika'; ... Ethernet_putConstBytes(buffer, 16); // put a const array into ethernet buffer |
Ethernet_putString
| Prototype |
function Ethernet_putString(ptr : ^byte) : word; |
|---|---|
| Returns |
Number of bytes written into Ethernet controller's RAM. |
| Description |
This is MAC module routine. It stores whole string (excluding null termination) into Ethernet controller's RAM starting from current Ethernet controller's write pointer ( Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var buffer : string[16]; ... buffer := 'mikroElektronika'; ... Ethernet_putString(buffer); // put a RAM string into ethernet buffer |
Ethernet_putConstString
| Prototype |
function Ethernet_putConstString(const ptr : ^byte) : word; |
|---|---|
| Returns |
Number of bytes written into Ethernet controller's RAM. |
| Description |
This is MAC module routine. It stores whole const string (excluding null termination) into Ethernet controller's RAM starting from current Ethernet controller's write pointer ( Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
const buffer : string[16]; ... buffer := 'mikroElektronika'; ... Ethernet_putConstString(buffer); // put a const string into ethernet buffer |
Ethernet_getByte
| Prototype |
function Ethernet_getByte() : byte; |
|---|---|
| Returns |
Byte read from Ethernet controller's RAM. |
| Description |
This is MAC module routine. It fetches a byte from address pointed to by current Ethernet controller's read pointer ( |
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var buffer : byte; ... buffer := Ethernet_getByte(); // read a byte from ethernet buffer |
Ethernet_getBytes
| Prototype |
procedure Ethernet_getBytes(ptr : ^byte; addr : word; n : word); |
|---|---|
| Returns |
Nothing. |
| Description |
This is MAC module routine. It fetches equested number of bytes from Ethernet controller's RAM starting from given address. If value of Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var buffer: array[16] of byte; ... Ethernet_getBytes(buffer, 0x100, 16); // read 16 bytes, starting from address 0x100 |
Ethernet_UserTCP
| Prototype |
function Ethernet_UserTCP(var remoteHost : array[4] of byte; remotePort, localPort, reqLength : word; var flags: TEthPktFlags) : word; |
|---|---|
| Returns |
|
| Description |
This is TCP module routine. It is internally called by the library. The user accesses to the TCP request by using some of the Ethernet_get routines. The user puts data in the transmit buffer by using some of the Ethernet_put routines. The function must return the length in bytes of the TCP reply, or 0 if there is nothing to transmit. If there is no need to reply to the TCP requests, just define this function with return(0) as a single statement. Parameters:
Note :
The function source code is provided with appropriate example projects. The code should be adjusted by the user to achieve desired reply.
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
This function is internally called by the library and should not be called by the user's code. |
Ethernet_UserUDP
| Prototype |
function Ethernet_UserUDP(var remoteHost : array[4] of byte; remotePort, destPort, reqLength : word; var flags: TEthPktFlags) : word; |
|---|---|
| Returns |
|
| Description |
This is UDP module routine. It is internally called by the library. The user accesses to the UDP request by using some of the Ethernet_get routines. The user puts data in the transmit buffer by using some of the Ethernet_put routines. 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 the UDP requests, just define this function with a return(0) as single statement. Parameters:
Note :
The function source code is provided with appropriate example projects. The code should be adjusted by the user to achieve desired reply.
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
This function is internally called by the library and should not be called by the user's code. |
Ethernet_getIpAddress
| Prototype |
function Ethernet_getIpAddress() : word;
|
|---|---|
| Returns | Ponter to the global variable holding IP address. |
| Description |
This routine should be used when DHCP server is present on the network to fetch assigned IP address. Note :
User should always copy the IP address from the RAM location returned by this routine into it's own IP address buffer. These locations should not be altered by the user in any case!
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var ipAddr : array[4] of byte; // user IP address buffer ... memcpy(ipAddr, Ethernet_getIpAddress(), 4); // fetch IP address |
Ethernet_getGwIpAddress
| Prototype |
function Ethernet_getGwIpAddress() : word;
|
|---|---|
| Returns | Ponter to the global variable holding gateway IP address. |
| Description |
This routine should be used when DHCP server is present on the network to fetch assigned gateway IP address. Note :
User should always copy the IP address from the RAM location returned by this routine into it's own gateway IP address buffer. These locations should not be altered by the user in any case!
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var gwIpAddr : array[4] of byte; // user gateway IP address buffer ... memcpy(gwIpAddr, Ethernet_getGwIpAddress(), 4); // fetch gateway IP address |
Ethernet_getDnsIpAddress
| Prototype |
function Ethernet_getDnsIpAddress() : word;
|
|---|---|
| Returns | Ponter to the global variable holding DNS IP address. |
| Description |
This routine should be used when DHCP server is present on the network to fetch assigned DNS IP address. Note :
User should always copy the IP address from the RAM location returned by this routine into it's own DNS IP address buffer. These locations should not be altered by the user in any case!
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var dnsIpAddr : array[4] of byte; // user DNS IP address buffer ... memcpy(dnsIpAddr, Ethernet_getDnsIpAddress(), 4); // fetch DNS server address |
Ethernet_getIpMask
| Prototype |
function Ethernet_getIpMask() : word;
|
|---|---|
| Returns | Ponter to the global variable holding IP subnet mask. |
| Description |
This routine should be used when DHCP server is present on the network to fetch assigned IP subnet mask. Note :
User should always copy the IP address from the RAM location returned by this routine into it's own IP subnet mask buffer. These locations should not be altered by the user in any case!
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var IpMask : array[4] of byte; // user IP subnet mask buffer ... memcpy(IpMask, Ethernet_getIpMask(), 4); // fetch IP subnet mask |
Ethernet_confNetwork
| Prototype |
procedure Ethernet_confNetwork(var ipMask, gwIpAddr, dnsIpAddr : array[4] of byte);
|
|---|---|
| Returns | Nothing. |
| Description |
Configures network parameters (IP subnet mask, gateway IP address, DNS IP address) when DHCP is not used. Parameters:
Note :
The above mentioned network parameters should be set by this routine only if DHCP module is not used. Otherwise DHCP will override these settings.
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var ipMask : array[4] of byte; // network mask (for example : 255.255.255.0) gwIpAddr : array[4] of byte; // gateway (router) IP address dnsIpAddr : array[4] of byte; // DNS server IP address ... gwIpAddr[0] := 192; gwIpAddr[1] := 168; gwIpAddr[2] := 20; gwIpAddr[3] := 6; dnsIpAddr[0] := 192; dnsIpAddr[1] := 168; dnsIpAddr[2] := 20; dnsIpAddr[3] := 100; ipMask[0] := 255; ipMask[1] := 255; ipMask[2] := 255; ipMask[3] := 0; ... Ethernet_confNetwork(ipMask, gwIpAddr, dnsIpAddr); // set network configuration parameters |
Ethernet_arpResolve
| Prototype |
function Ethernet_arpResolve(var ip : array[4] of byte; tmax : byte) : word; |
|---|---|
| Returns |
|
| Description |
This is ARP module routine. It sends an ARP request for given IP address and waits for ARP reply.
If the requested IP address was resolved, an ARP cash entry is used for storing the configuration.
ARP cash can store up to 3 entries. For ARP cash structure refer to Parameters:
Note :
The Ethernet services are not stopped while this routine waits for ARP reply. The incoming packets will be processed normaly during this time.
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var IpAddr : array[4] of byte; // IP address ... IpAddr[0] := 192; IpAddr[0] := 168; IpAddr[0] := 1; IpAddr[0] := 1; ... Ethernet_arpResolve(IpAddr, 5); // get MAC address behind the above IP address, wait 5 secs for the response |
Ethernet_sendUDP
| Prototype |
function Ethernet_sendUDP(var destIP : array[4] of byte; sourcePort, destPort : word; pkt : ^byte; pktLen : word) : byte; |
|---|---|
| Returns |
|
| Description |
This is UDP module routine. It sends an UDP packet on the network. Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var IpAddr : array[4] of byte; // remote IP address ... IpAddr[0] := 192; IpAddr[0] := 168; IpAddr[0] := 1; IpAddr[0] := 1; ... Ethernet_sendUDP(IpAddr, 10001, 10001, 'Hello', 5); // send Hello message to the above IP address, from UDP port 10001 to UDP port 10001 |
Ethernet_dnsResolve
| Prototype |
function Ethernet_dnsResolve(var host : array[4] of byte; tmax : byte) : word; |
|---|---|
| Returns |
|
| Description |
This is DNS module routine. It sends an DNS request for given host name and waits for DNS reply.
If the requested host name was resolved, it's IP address is stored in library global variable
and a pointer containing this address is returned by the routine. UDP port Parameters:
Note :
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
var
remoteHostIpAddr : array[4] of byte; // user host IP address buffer
...
// SNTP server:
// Zurich, Switzerland: Integrated Systems Lab, Swiss Fed. Inst. of Technology
// 129.132.2.21: swisstime.ethz.ch
// Service Area: Switzerland and Europe
memcpy(remoteHostIpAddr, Ethernet_dnsResolve('swisstime.ethz.ch', 5), 4);
|
Ethernet_initDHCP
| Prototype |
function Ethernet_initDHCP(tmax : byte) : byte; |
|---|---|
| Returns |
|
| Description |
This is DHCP module routine. It sends an DHCP request for network parameters (IP, gateway, DNS addresses and IP subnet mask) and waits for DHCP reply. If the requested parameters were obtained successfully, their values are stored into the library global variables. These parameters can be fetched by using appropriate library IP get routines:
UDP port Parameters:
Note :
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
... Ethernet_initDHCP(5); // get network configuration from DHCP server, wait 5 sec for the response ... |
Ethernet_doDHCPLeaseTime
| Prototype |
function Ethernet_doDHCPLeaseTime() : byte; |
|---|---|
| Returns |
|
| Description |
This is DHCP module routine. It takes care of IP address lease time by decrementing the global lease time library counter. When this time expires, it's time to contact DHCP server and renew the lease. |
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
while true do
begin
...
if(Ethernet_doDHCPLeaseTime() <> 0) then
begin
... // it's time to renew the IP address lease
end;
end;
|
Ethernet_renewDHCP
| Prototype |
function Ethernet_renewDHCP(tmax : byte) : byte; |
|---|---|
| Returns |
|
| Description |
This is DHCP module routine. It sends IP address lease time renewal request to DHCP server. Parameters:
|
| Requires |
Ethernet module has to be initialized. See Ethernet_Init. |
| Example |
while true do
begin
...
if(Ethernet_doDHCPLeaseTime() <> 0) then
begin
Ethernet_renewDHCP(5); // it's time to renew the IP address lease, with 5 secs for a reply
end;
...
end;
|
Library Example
This code shows how to use the PIC18FxxJ60 Ethernet 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 RD0 to RD7 bit and return HTML main page
- all other requests return also HTML main page.
program http_Demo;
{***********************************
* RAM variables
*}
var myMacAddr : array[6] of byte ; // my MAC address
myIpAddr : array[4] of byte ; // my IP address
gwIpAddr : array[4] of byte ; // gateway (router) IP address
ipMask : array[4] of byte ; // network mask (for example : 255.255.255.0)
dnsIpAddr : array[4] of byte ; // DNS server IP address
{************************************************************
* ROM constant strings
*}
const httpHeader : string[30] = 'HTTP/1.1 200 OK'+#10+'Content-type: ' ; // HTTP header
const httpMimeTypeHTML : string[11] = 'text/html'+#10+#10 ; // HTML MIME type
const httpMimeTypeScript : string[12] = 'text/plain'+#10+#10 ; // TEXT MIME type
const httpMethod : string[5] = '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 indexPage : string[759] =
'<meta http-equiv="refresh" content="3;url=http://192.168.20.60">' +
'<HTML><HEAD></HEAD><BODY>'+
'<h1>PIC18FxxJ60 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 indexPage2 : string[466] =
'</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<3;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>';
var getRequest : array[15] of byte; // HTTP request buffer
dyna : array[30] of char; // buffer for dynamic response
httpCounter : word ; // counter of HTTP requests
{*******************************************
* user defined functions
*}
{*
* this function is called by the library
* the user accesses to the HTTP request by successive calls to Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to 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
*
*}
function Ethernet_UserTCP(var remoteHost : array[4] of byte;
remotePort, localPort, reqLength : word; var flags: TEthJ60PktFlags) : word; var i : word ; // my reply length
bitMask : byte ; // for bit mask
tmp: string[11]; // to copy const array to ram for memcmp
begin
result := 0;
// should we close tcp socket after response is sent?
// library closes tcp socket by default if canClose flag is not reset here
// flags.canCloseTCP := 0; // 0 - do not close socket
// otherwise - close socket
if(localPort <> 80) then // I listen only to web request on port 80
begin
result := 0;
exit;
end;
// get 10 first bytes only of the request, the rest does not matter here
for i := 0 to 9 do
getRequest[i] := Ethernet_getByte() ;
getRequest[i] := 0 ;
// copy httpMethod to ram for use in memcmp routine
for i := 0 to 4 do
tmp[i] := httpMethod[i];
if(memcmp(@getRequest, @tmp, 5) <> 0) then // only GET method is supported here
begin
result := 0 ;
exit;
end;
Inc(httpCounter) ; // one more request done
if(getRequest[5] = 's') then // if request path name starts with s, store dynamic data in transmit buffer
begin
// the text string replied by this request can be interpreted as javascript statements
// by browsers
result := Ethernet_putConstString(@httpHeader) ; // HTTP header
result := result + Ethernet_putConstString(@httpMimeTypeScript) ; // with text MIME type
// add AN2 value to reply
WordToStr(ADC_Read(2), dyna) ;
tmp := 'var AN2=';
result := result + Ethernet_putString(@tmp) ;
result := result + Ethernet_putString(@dyna) ;
tmp := ';';
result := result + Ethernet_putString(@tmp) ;
// add AN3 value to reply
WordToStr(ADC_Read(3), dyna) ;
tmp := 'var AN3=';
result := result + Ethernet_putString(@tmp) ;
result := result + Ethernet_putString(@dyna) ;
tmp := ';';
result := result + Ethernet_putString(@tmp) ;
// add PORTB value (buttons) to reply
tmp := 'var PORTB= ';
result := result + Ethernet_putString(@tmp) ;
WordToStr(PORTB, dyna) ;
result := result + Ethernet_putString(@dyna) ;
tmp := ';';
result := result + Ethernet_putString(@tmp) ;
// add PORTD value (LEDs) to reply
tmp := 'var PORTD= ';
result := result + Ethernet_putString(@tmp) ;
WordToStr(PORTD, dyna) ;
result := result + Ethernet_putString(@dyna) ;
tmp := ';';
result := result + Ethernet_putString(@tmp) ;
// add HTTP requests counter to reply
WordToStr(httpCounter, dyna) ;
tmp := 'var REQ= ';
result := result + Ethernet_putString(@tmp) ;
result := result + Ethernet_putString(@dyna) ;
tmp := ';';
result := result + Ethernet_putString(@tmp) ;
end
else
if(getRequest[5] = 't') then // if request path name starts with t, toggle PORTD (LED) bit number that comes after
begin
bitMask := 0;
if(isdigit(getRequest[6]) <> 0) then // if 0 <= bit number <= 9, bits 8 & 9 does not exist but does not matter
begin
bitMask := getRequest[6] - '0' ; // convert ASCII to integer
bitMask := 1 shl bitMask ; // create bit mask
PORTD := PORTD xor bitMask ; // toggle PORTD with xor operator
end;
end;
if(result = 0) then // what do to by default
begin
result := Ethernet_putConstString(@httpHeader) ; // HTTP header
result := result + Ethernet_putConstString(@httpMimeTypeHTML) ; // with HTML MIME type
result := result + Ethernet_putConstString(@indexPage) ; // HTML page first part
result := result + Ethernet_putConstString(@indexPage2) ; // HTML page second part
end;
// return to the library with the number of bytes to transmit
end;
{*
* this function is called by the library
* the user accesses to the UDP request by successive calls to Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to 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
*
*}
function Ethernet_UserUDP(var remoteHost : array[4] of byte;
remotePort, destPort, reqLength : word; var flags: TEthJ60PktFlags) : word;
var tmp : string[5];
begin
result := 0;
// 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], tmp) ; // second
dyna[4] := tmp[0];
dyna[5] := tmp[1];
dyna[6] := tmp[2];
dyna[7] := '.' ;
byteToStr(remoteHost[2], tmp) ; // second
dyna[8] := tmp[0];
dyna[9] := tmp[1];
dyna[10] := tmp[2];
dyna[11] := '.' ;
byteToStr(remoteHost[3], tmp) ; // second
dyna[12] := tmp[0];
dyna[13] := tmp[1];
dyna[14] := tmp[2];
dyna[15] := ':' ; // add separator
// then remote host port number
WordToStr(remotePort, tmp) ;
dyna[16] := tmp[0];
dyna[17] := tmp[1];
dyna[18] := tmp[2];
dyna[19] := tmp[3];
dyna[20] := tmp[4];
dyna[21] := '[' ;
WordToStr(destPort, tmp) ;
dyna[22] := tmp[0];
dyna[23] := tmp[1];
dyna[24] := tmp[2];
dyna[25] := tmp[3];
dyna[26] := tmp[4];
dyna[27] := ']' ;
dyna[28] := 0 ;
// the total length of the request is the length of the dynamic string plus the text of the request
result := 28 + reqLength ;
// puts the dynamic string into the transmit buffer
Ethernet_putBytes(@dyna, 28) ;
// then puts the request string converted into upper char into the transmit buffer
while(reqLength <> 0) do
begin
Ethernet_putByte(Ethernet_getByte()) ;
reqLength := reqLength - 1;
end;
// back to the library with the length of the UDP reply
end;
begin
ADCON1 := 0x0B ; // ADC convertors will be used with AN2 and AN3
CMCON := 0x07 ; // turn off comparators
PORTA := 0 ;
TRISA := 0x0C ; // RA2:RA3 - analog inputs
// RA1:RA0 - ethernet LEDA:LEDB
PORTB := 0 ;
TRISB := 0xff ; // set PORTB as input for buttons
PORTD := 0 ;
TRISD := 0 ; // set PORTD as output
httpCounter := 0;
// set mac address
myMacAddr[0] := 0x00;
myMacAddr[1] := 0x14;
myMacAddr[2] := 0xA5;
myMacAddr[3] := 0x76;
myMacAddr[4] := 0x19;
myMacAddr[5] := 0x3F;
// set IP address
myIpAddr[0] := 192;
myIpAddr[1] := 168;
myIpAddr[2] := 20;
myIpAddr[3] := 60;
// set gateway address
gwIpAddr[0] := 192;
gwIpAddr[1] := 168;
gwIpAddr[2] := 20;
gwIpAddr[3] := 6;
// set dns address
dnsIpAddr[0] := 192;
dnsIpAddr[1] := 168;
dnsIpAddr[2] := 20;
dnsIpAddr[3] := 1;
// set subnet mask
ipMask[0] := 255;
ipMask[1] := 255;
ipMask[2] := 255;
ipMask[3] := 0;
{*
* starts ENC28J60 with :
* reset bit on PORTC.B0
* CS bit on PORTC.B1
* my MAC & IP address
* full duplex
*}
Ethernet_Init(myMacAddr, myIpAddr, _Ethernet_FULLDUPLEX) ; // init ethernet module
Ethernet_setUserHandlers(@Ethernet_UserTCP, @Ethernet_UserUDP); // set user handlers
// dhcp will not be used here, so use preconfigured addresses
Ethernet_confNetwork(ipMask, gwIpAddr, dnsIpAddr) ;
while true do // do forever
begin
Ethernet_doPacket() ; // process incoming Ethernet packets
{*
* add your stuff here if needed
* Ethernet_doPacket() must be called as often as possible
* otherwise packets could be lost
*}
end;
end.
What do you think about this topic ? Send us feedback!




