/************************************************** ************************************************
* Project name:
ETH_click (Demonstration of mikroBUS ETH click board)
* Copyright:
(c) Mikroelektronika, 2011.
* Revision History:
20071210:
- initial release; Author: Bruno Gavand.
20071210:
- modified for PRO compilers (FJ).
20111215:
- modified for ETH click board (DA);
* Description:
this code shows how to use the ENC28J60 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 RD0 to RD7 bit and return HTML
* EP7 settings :
AN0 potentiometer jumper (J15)
PORTB : pull-down (PortB three-state switch) (board specific)
Jumper (J17) in Vcc position
the INT and WOL signals from the ENC are not used
* Test configuration:
MCU: PIC18F45K22
http://ww1.microchip.com/downloads/en/DeviceDoc/41412D.pdf
dev.board: EasyPIC7
http://www.mikroe.com/eng/products/view/757/easypic-v7-development-system/
Oscillator: HS-PLL 32.0000 MHz, 8.0000 MHz Crystal
SW: mikroC PRO for PIC
http://www.mikroe.com/eng/products/view/7/mikroc-pro-for-pic/
ext. modules: ETH click ac:ETH_click
http://www.mikroe.com/eng/products/view/794/eth-click/
* NOTES:
- ETH click board with ETHERNET controller ENC24J60 is placed to the mikroBUS socket 1.
Program uses SPI1 perpheral to comunicate with ETHERNET controller.
LED RB0 will always be ON since it is connected to INT pin of ENC24J60.
************************************************** ************************************************/
#include ‹built_in.h›
/************************************************** ************************************************
*
************************************************** ************************************************/
// duplex config flags
#define Spi_Ethernet_HALFDUPLEX 0x00 // half duplex
#define Spi_Ethernet_FULLDUPLEX 0x01 // full duplex
// mE ehternet NIC pinout
sfr sbit SPI_Ethernet_Rst at LATE1_bit;
sfr sbit SPI_Ethernet_CS at LATE0_bit;
sfr sbit SPI_Ethernet_Rst_Direction at TRISE1_bit;
sfr sbit SPI_Ethernet_CS_Direction at TRISE0_bit;
// TCP flags
typedef struct {
unsigned canCloseTCP: 1; // flag which closes TCP socket (not relevant to UDP)
unsigned isBroadcast: 1; // flag which denotes that the IP package has been received via subnet broadcast address (not used for PIC16 family)
} TEthPktFlags;
//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.61\"›\
‹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›AN0‹/td›‹td›‹script›document.write(AN0)‹/script›‹/td›‹/tr›\
‹/table›‹/td›‹td valign=top›‹table border=1 style=\"font-size:20px ;font-family: terminal ;\"›\
‹tr›‹th colspan=2›PORTB‹/th›‹/tr›\
‹script›\
var str,i;\
str=\"\";\
for(i=1;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, 61 }; // my IP address
unsigned char gwIpAddr[4] = {192, 168, 20, 6 }; // gateway (router) IP address
unsigned char ipMask[4] = {255, 255, 255, 0 }; // network mask (for example : 255.255.255.0)
unsigned char dnsIpAddr[4] = {192, 168, 20, 1 }; // DNS server IP address
unsigned char getRequest[15]; // HTTP request buffer
unsigned char dyna[30]; // buffer for dynamic response
unsigned long httpCounter = 0; // counter of HTTP requests
unsigned char buffer, buf[] = "Temp=";
unsigned char IpAddr77[4] = {192, 168, 20, 62 }; // remote IP address
/*******************************************
* 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) ;
}*/
/*
* it will be much faster to use library Spi_Ethernet_putConstString routine
* instead of putConstString routine above. However, the code will be a little
* bit bigger. User should choose between size and speed and pick the implementation that
* suites him best. If you choose to go with the putConstString definition above
* the #define line below should be commented out.
*
*/
#define putConstString SPI_Ethernet_putConstString
/*
* 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) ;
}*/
/*
* it will be much faster to use library Spi_Ethernet_putString routine
* instead of putString routine above. However, the code will be a little
* bit bigger. User should choose between size and speed and pick the implementation that
* suites him best. If you choose to go with the putString definition above
* the #define line below should be commented out.
*
*/
#define putString SPI_Ethernet_putString
/*
* 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, TEthPktFlags *flags) {
//return 0;
unsigned int len = 0 ; // my reply length
unsigned int i ; // general purpose integer
// should we close tcp socket after response is sent?
// library closes tcp socket by default if canClose flag is not reset here
// flags-›canClose = 0; // 0 - do not close socket
// otherwise - close socket
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(0), dyna) ;
len += putConstString("var AN0=") ;
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(LATD, 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
LATD ^= 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, TEthPktFlags *flags) {
//return 0; // back to the library with the length of the UDP reply
}
/************************************************** ************************************************
* MAIN PROGRAM
************************************************** ************************************************/
void main()
{
ANSELA = 0x01; // Configure PORTA pins as digital except RA0. This pin is analog (AN0).
ANSELB = 0; // Configure PORTB pins as digital.
ANSELC = 0; // Configure PORTC pins as digital
ANSELE = 0; // Configure PORTE pins as digital
SLRCON = 0; // Configure all PORTS at the standard Slew
PORTB = 0;
TRISB = 0xff; // set PORTB as input for buttons
PORTD = 0;
TRISD = 0; // set PORTD as output
/*
* starts ENC28J60 with :
* reset bit on RE1
* CS bit on RE0
* my MAC & IP address
* full duplex
*/
SPI1_Init();
SPI_Ethernet_Init(myMacAddr, myIpAddr, Spi_Ethernet_FULLDUPLEX) ;
while(1) { // do forever
//SPI_Ethernet_doPacket() ; // process incoming Ethernet packets
SPI_Ethernet_sendUDP(IpAddr77, 10001, 10001, buf, 5); // send Hello message to the above IP address, from UDP port 10001 to UDP port 10001
delay_ms(1000);
}
}
/************************************************** ************************************************
* End of File
************************************************** ************************************************/ |