3 Ekim 2014 Cuma

ETHERNET COMMUNICATION with ENC28J60


  Hi friends.I haven't broadcasted my blog for a long time.I am here with one of the performed projects in this time period.We will provide Ethernet communication in our project via SPI (Serial Peripheral Interface)  with ENC28J60 ethernet chip. SPI is one of serial communication protocols which allowing data exchange with peripheral units or microcontrollers.The ENC28J60 ethernet chip provides  data communication with microcontroller via SPI,up to 10 Mbit / s speed.

   Block diagram of our project;



   Pin configuration of our ENC28J60 Ethernet chip is as below.


   SPI is full duplex and synchronous serial communication protocol.Data transfer is performed by the master-slave relationship in SPI communication.



    SPI protocol is run with four signal line.
  *SI  (SDI)  :Serial Data In,                                                                          
  *SO(SDO):Serial Data Out,                                                                                 *SCK:Serial clock signal,
  *CS:Chip Select.If more than one slave device exists , cs pin of related device is activated to communicate with which device.

  You can set up a circuit as follows for ethernet communication.


    You can use the microcontroller you want at your circuit  but provided  that, SPI and more than memory of 4 KB exists.We need pay attention to matter "crystal of  microcontroller must be  8-10 MHz". I used 16F877A microcontroller  with 10 MHz crystal but I used ready-made module, ınstead of communication circuit.

   
   Now let's specify , what we will control and how we will write a program with ethernet communication. We will do LED and LCD control With ENC28J60 module. We will do an interface UDP terminal  with Microsoft Visual C #. We will send our packages buffer of enc28j60 via ethernet socket with the UDP terminal.  Microcontrollers will receive data from the buffer.If microcontroller received package , which our specified (If the "LED ON" button  pressed),  we will burn led and we will print "LED ON" on the LCD screen.If the microcontroller received package , which  our specified other (If the "LED OFF" button  pressed), we will extinguish led and we will print "LED OFF" on the LCD screen.
   Ethernet communication is taken place via sockets.Sockets  creates our network. Socket specifies two basic address information of the our network. These  IP address and port number.We will specify IP address and port number in our program .
   There are two types of  sockets which used in Ethernet communication.These UDP(User Datagram Protocol)  and TCP(Transmission Control Protocol) . We a little talk about essential differences between TCP and UDP.

* TCP is slower than UDP. Because, the data  sends in a sequential manner and the data is checked whether it reached other side.Due to these reasons, it is safer than UDP.
*UDP , veriler sıralı bir şekilde olmayıp bağımsız bir şekilde karşıya gönderilir. Therefore, it is  faster according to TCP. Because to be fast, UDP is used  to send the video and audio .                                                                                                    

   Now,we can give  our project's general circuit .



   We wrote  our program in mikroC PRO for PIC compiler. Because, many libraries are  ready in mikroC and can be used easily .Our program is immediately below.
/////////
#define SPI_Ethernet_HALFDUPLEX     0
#define SPI_Ethernet_FULLDUPLEX     1

//************  SPI protocol connections *****************
sfr sbit SPI_Ethernet_Rst at RC0_bit;     
sfr sbit SPI_Ethernet_CS  at RC1_bit;
sfr sbit SPI_Ethernet_Rst_Direction at TRISC0_bit;
sfr sbit SPI_Ethernet_CS_Direction  at TRISC1_bit;

//************  LCD module connections  ******************
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;

//****************************************************
typedef struct {
  unsigned canCloseTCP: 1;  
  unsigned isBroadcast: 1; 
} TEthPktFlags;

char txt[17], template_msg[] = "UDP msg rcved:", error_msg[] = "msg too long!";
   
//*******************************************
unsigned int SPI_Ethernet_UserTCP(unsigned char *remoteHost, unsigned int remotePort,unsigned int localPort, unsigned int reqLength, TEthPktFlags *flags) {
  return 0;             
}
//********************************************

unsigned int SPI_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort,unsigned int destPort, unsigned int reqLength, TEthPktFlags *flags) {
  unsigned char len = 0;

  if (destPort != 10001) { //if the destination port is not 10001
    return 0;              //there will be no reply                 
  }
  
  if (reqLength > 16) { 
    Lcd_Out(2,1,error_msg);            
    return sizeof(error_msg)-1;
  }
  
  Lcd_Cmd(_LCD_CLEAR);                      // clear Lcd.
  Lcd_Out(1, 2, template_msg);              // display template message.

 while(reqLength--) {
    txt[len++] = SPI_Ethernet_getByte(); 
  }

  txt[len] = 0;
    if(!strcmp(txt,"g"))                    //compare txt and "g".
    {
     Lcd_Out(2, 1,"LED ON");
     PORTD=0x01;
    }
    if(!strcmp(txt,"s"))                   //compare txt and "s".
    {
     Lcd_Out(2, 1,"LED OFF");
     PORTD.f0=0x00;
    }
     
  return 0;
}

//***********************************

unsigned char myMacAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f};   
unsigned char myIpAddr[4] = {192, 168, 2, 1};                      


void main() {

  TRISD = 0x00;
  PORTB=0;

  Lcd_Init();                               // initialize Lcd.
  Lcd_Cmd(_LCD_CLEAR);                      // clear Lcd.
  Lcd_Cmd(_LCD_CURSOR_OFF);                 // turn off cursor.
  LCD_Out(1, 2, template_msg);              // display template message

  SPI1_Init();
  SPI_Ethernet_Init(myMacAddr, myIpAddr, SPI_Ethernet_FULLDUPLEX);

  while(1) {                  // endless loop              

    SPI_Ethernet_doPacket();  //process incoming Ethernet packets              

  }
}
////////

   Specify the task of few functions in our program.
   SPIx_Init();                                                                                                            This function  installs SPI protocol with standard settings  and its operation starts.If you want to use custom settings instead of the standard settings,you can use the Spıx_ınit_advenced ( )  function. 
  SPI_Ethernet_Init();                                                                                         
 This function installs ethernet library over SPI protocol and its operation starts.
Sample usage:  SPI_Ethernet_Init(myMacAddr, myIpAddr, SPI_Ethernet_ FULLDUPLEX); .We provide full-duplex operation of the ENC28J60 module which specified MAC and IP addresses in this example.
  SPI_Ethernet_doPacket();                                                                                  This function initializes operation of UDP and TCP.I mean, it calls and runs SPI_Ethernet_UserTCP();  and  SPI_Ethernet _ UserUDP();  .
  SPI_Ethernet_getByte();                                                                                      It reads 1 byte data from enc28c60 buffer.
  SPI_Ethernet_putString();
This function puts string or character array in buffer of Enc28c60 .

   After you specify them, we can analyse terminal which  made  the Microsoft Visual C# . Our terminal will have four buttons. Two of buttons to open-close the socket and other two to blink our led.Picture below is better understood.



   
  You can find C # program below .

////////
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;


namespace ethertnet2
{
    public partial class Form1 : Form
    {

        // string Ip = "192.168.2.1";
         //int port = 10001;



        IPEndPoint ipepC;
        Socket udpclnt;     //newsock
         byte[] byteSend;
         int intRcv;
         bool epSFlag = false;
         bool displayRcvFlag = false;
         string stringRcv = "";


         public Form1()
         {
             InitializeComponent();
         }

         private void button1_Click(object sender, EventArgs e)
         {
           IPAddress serverAddr = IPAddress.Parse("192.168.2.1");
           ipepC = new IPEndPoint(serverAddr, 10001);
           udpclnt = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,ProtocolType.Udp);
         }

         private void button2_Click(object sender, EventArgs e)
         {
           udpclnt.Close();
         }

         private void button3_Click(object sender, EventArgs e)
         {
           byteSend = new byte[5];
           byteSend[0] = 103;
           udpclnt.SendTo(byteSend, ipepC);
        
         }

         private void button4_Click(object sender, EventArgs e)
         {
           byteSend = new byte[5];
           byteSend[0] = 115;
           udpclnt.SendTo(byteSend, ipepC);
         }

     }
 }
////////

   Explain briefly our program.We should import  System.Net and System.Net.Socket in the program to do ethernet communication.
 using System.Net; 
 using System.Net.Sockets;
   Our IP address is specified as "192.168.2.1"  and port number is specified as 10001 when  "SOCKET ON" button is clicked that first button.Then,with udpclnt = new Socket (Address Family.Inter Network,SocketType.Dgram,    ProtocolType.Udp);  , a new instance of the Socket class is opened by the name of udpclnt and the type of UDP.
   Our UDP socket connection is closed with udpclnt.Close();  when "SOCKET OFF" button is clicked that second button.
   We opened location of five bytes in our array which we defined bytesend name when "LED ON" button is clicked that third button with byteSend = new byte[5]; . We assigned  as 103 to first element of the bytesend array.The 103 is 'g' character's decimal equivalent. Then ,with udpclnt.SendTo(byteSend,ipepC); we sent  'g' character our port . Thus, we have sent  'g' character to the buffer of Enc28j60.
   When "LED OFF" button is clicked that is fourth button does similar operations what third button does.The differance that 115 is assigned to first element of bytesend array. The 115 is 's' character's decimal equivalent.
After we specify them now we can connect to computer our circuit with an ethernet cable. But probably,you will see warning of "Unidentified Network" in your local network. As shown in the picture below from the Local Area Connection Properties , you must write a different IP from the IP address that you specify in the program to  identify network in IP address box the TCP / IPv4 option by double-clicking from TCP / IPv4 properties.As for the default gateway box,you must write IP address that you specify in the program. After making these changes, your network will be defined.


    After network identified, on the ENC28J60 module, yellow led which is nearby RJ45(with transformator) must be lighting and yellow led must blink.Now ,we can open and run the terminal which did with C#. Also Udp Terminal is located in the tools menu of MikroC PRO for PIC compiler , you can use it.
      See you next project.I wish you success.Sincerely.

22 yorum:

  1. Eser kardeş örnek için teşekkür ederim güzel bir çalışma olmuş benimde böyle bir devre yapmam gerekiyor devreye bağlı analog ve dijital veri kaynakları olacak ve bu verileri ethernet portu üzerinden belli bi protokolle bilgisayarda hazır yazılmış olan bir yazılıma göndermem gerekiyor yardımcı olabilirmisin veya önerebileceğin micro c kaynağı varmı bildiğin. Tekrardan teşekkür ederim. İyi günler.

    YanıtlaSil
  2. Teşekkür ederim ilginiz için. mikro C pro for pic derleyicisini bilgisayarınıza kurunca örnek programlarla birlikte kuruluyor. O örnek programları inceleyebilirsiniz. Ve ayrıca derleyicide Library Manager de SPI_Ethernet ve ADC kütüphaneleri bulunmaktadır. ADC kütüphanesini inceledikten ve fonksiyonların görevlerini anladıktan sonra analog verilerinizi mikrodenetleyiciye alabilirsiniz. Daha sonra da SPI_Ethernet kütüphanesini incelerseniz bilgisayarınıza verilerinizi gönderebilirsiniz. Yine anlayamadığınız bir kısım olursa yardımcı olurum. İyi çalışmalar.

    YanıtlaSil
    Yanıtlar
    1. Teşekkür ederim. ADC ile veri okuduğum bikaç devre olmuştu o acıdan sıkıntım yok sadece ethernet kısmında biraz kafam karışıyor onuda dün araştırmalarım sonucu birşeyler canlanmaya başladı ama doğruluğundan emin olamadım. göndermek istediğim verileri önce enj28j60 entegresi içinde bulunan bi tampon alan var buffer diye gecen anladığım kadarıyla ve oraya sırayla "SPI_Ethernet_putByte" vs. gibi PUT komutlarıyla yükleyip sonrasında verileri entegreye yükleme işlemi bittikten sonrada "SPI_Ethernet_doPacket" koduyla yollama işlemi yapılıyor benim anladığım kadarıyla.ancak protokol tcp protokol olcak kartın görevi tcp server olacak ve gelen veriyi işleyip istek verisi ise portlardaki değer bilgisini göndecek. tcp port yayını açmak için nasıl bi kodlama yapmam gerekiyor.

      Sil
    2. Genel itibari ile doğru anlamışsınız.Put komutları enc28j60 ın bufferına veri gönderir. Get komutları da ethernet portundan enc28j60 ın bufferına gönderilen verileri mikrodenetleyiciye alır. SPI_Ethernet_doPacket(); komutu SPI_Ethernet_UserTCP() ve SPI_Ethernet _ UserUDP() fonksiyonlarını çağırır ve çalıştırır. Benim programımda UDP soketi kullanılmıştır. Onun içinde SPI_Ethernet_UserTCP() fonksiyonu içinde sadece return 0; kullanılmıştır. Ve veri okuma ve portlara veri yazma işlemi SPI_Ethernet _ UserUDP() fonksiyonu içinde yapılmıştır. TCP kullanacaksanız bu işlemleri SPI_Ethernet_UserTCP() fonksiyonunda yapmanız gerekir diye düşünüyorum. Fakat ben TCP soketi denemedim.

      Sil
  3. Merhaba Eser bey,benim kodlarda SPI_Ethernet_doPacket() fonksiyonu sorun çıkarıyor.Bu fonksiyonu silince diğer kod blokları çalışırken bu fonksiyonu aktif edince diğer tüm kodlar çalışmıyor.PIC resmen kilitleniyor.Sorun ne olabilir acaba?

    YanıtlaSil
    Yanıtlar
    1. Merhaba. Programınızı görmem gerekir sorunun ne olabileceği ile ilgili birşey söyleye bilmem için.

      Sil
    2. Eser bey,kodlarım sizinkiyle birebir aynı.Ben internetteki örnekleri de inceleyerek webserver için http sayfalarının kodlarını da kodun içine koydum.Devreyi board üzerine kurup kullandığım PIC18F4685 ine ENC modülünü 3.3v da besliyorum.Bağlantıları doğrudan yaptım 74hc entegresini kullanmadım.İnternette böyle çalıştıranlar da varmış.Acaba board üzerine kurmak iletişimin başarısız olmasına mı neden oluyor? ENC modülünün SO bacağındaki voltajı 0.2-0.7v arasında görmem normal mi?

      Sil
    3. Eser bey,uygulamaları 74hc245 entegresiyle yapsam da bir sonuç değişmedi,aynı uygulamaları ccs c de de yaptım ancak yine ağda PIC'in ip sini göremedim. ENC ile PIC bağlantılarını board üzerinde kablo ile yaptım.Uzun kablo ve board üzerine kurulmuş bir devreye güvenilebilir mi? Yardımcı olursanız çok sevinirim,iyi çalışmalar dilerim.

      Sil
    4. Bende ENC modül kullandım. 3.3V ile beslemenize gerek yok ben 5V ile besledim sorunsuz şekilde çalıştı. Modülün arka tarafında bi transistör var o zaten 5 voltu 3.3 volta düşürüyor. Kolay gelsin.

      Sil
    5. Bu yorum yazar tarafından silindi.

      Sil
    6. Eser bey,datasheetinde 3.3v ile beslenmesi gerektiği yazıyor.Kullandığım modülün üstünde transistör yok.5v modüle zarar vermesin?
      Kullandığım modül şu: https://www.google.com.tr/search?q=ENC28J60+module&newwindow=1&biw=1366&bih=608&source=lnms&tbm=isch&sa=X&ei=hgyRVf73I8iNsgG8zKCYDw&ved=0CAYQ_AUoAQ#imgrc=TQAhpzM9P1NhyM%3A

      Sil
    7. Benim modülün üzerinde iki tane besleme yeri var hem 5V hemde 3.3V için besleme pini koymuşlar. Ben 5V yazan yerden besledim. Modülün arkasındada ams1117 transistörü var. Oda 3.3V a düşürüyor. Modül ün üzerin toplamda 12 pin var. Galiba sizin modülde 10 pin var. Fakat 3.3voltla besleyince de çalışması gerekir .

      Sil
    8. SPI iletişim kablo uzunluğundan kaynaklandığını varsayarak PIC ve ENC için baskı devresi yapacağım.Sonuçları sizinle de paylaşırım.Vakit ayırıp sorularıma cevap verdiğiniz için teşekkür ederim Eser bey,iyi çalışmalar dilerim.

      Sil
    9. SPI iletişim kablo uzunluğundan kaynaklandığını zannetmiyorum. PIC devresini boarda kurup daha sonra boarda jumper ile bağlantı yapıştım bende. Bence tekrar devrenizi inceleyin. Sizede kolay gelsin, iyi çalışmalar.

      Sil
  4. mikroişlemciden den pice veri göndermede sıkıntı yok fakat mikroişlemciden bilgisaya veri göndermek için SPI_Ethernet_sendUDP(IpAddr, 17200, 17200, "mesaj", 5);fonksiyonunu kullanıyorum ama çalışmıyor böyle birşey deneyen varmı acaba?

    YanıtlaSil
  5. Pic den bilgisayara veri göndermek için SPI_Ethernet_putBytes(); SPI_Ethernet_putString(); fonksiyonlarını kullandım. SPI_Ethernet_sendUDP(); fonksiyonu kullanmadım fakat SPI_Ethernet_sendUDP(); fonksiyonu pic16F de çalışmaz sadece pic18 lerde çalışır.

    YanıtlaSil
  6. Bu yorum yazar tarafından silindi.

    YanıtlaSil
  7. Sayın Eser bey

    Bir konuda yardım rica edebilirmiyim, ENC28j60 ile iki pic arasında kontrol yapmaya çalışıyorum, ilk aşamada proteus da denemek istiyorum, yalnız simülasyonda rj45 için izolasyon trafosunu kullanamıyoruz, bu nedenle bende, 2 adet ENC28j60'nin TPout ve TPin üçlarını direk olarak cros yaparak şemada bağladım tıpkı iki bilgisayarı kablo ile birbirine bağlamak gibi, ayrıca 50r luk pulldown dirençlerinide takdım , böyle bir durumda haberleşme sağlayabilirmiyim, eğer olmaz ise nasıl bir yol izlemem gerek

    saygılarımla

    YanıtlaSil
  8. Merhaba Kamil Bey

    Ben simülasyon yapmadım çünkü proteusda RJ45 söketini bulamamıştım. Devreyi kurmadan enj28j60 modülü ile uygulamayı gerçekleştirdim. Söylediğiniz bağlantı mantıklı gibi fakat devre hakkında pek bilgim yok. Ben modülü RJ45 soketinden doğrudan bilgisayara bağladım. İyi günler dilerim.

    YanıtlaSil
    Yanıtlar
    1. Cevap için teşekkürler, evet bende proteus da rj45 bulamadım o yüzden, simülasyonu o olmadan yapmayı deneyeceğim, birde proteus da enj28j60 farklı farklı yapılmış , oda kafamı karıştırdı biraz araştırma yapınca doğru olanı buldum, bakalım ne sonuç çıkacak deneyip göreceğim

      Sil
  9. Rica ederim. Sonucu bildirirseniz memnun olurum. Kolay gelsin.

    YanıtlaSil
  10. Bunun Türkçesi de var mı?

    YanıtlaSil