EthernetICMP

SwordfishUser.EthernetICMP History

Show minor edits - Show changes to output

Added lines 1-31:
This sample program uses the ICMP module to ping a remote host. The first example program requires you to enter a numeric IP address. In the second code example, the DNS module is used to resolve a hostname (for example, www.microchip.com) before pinging. Here's what you need to do.

*Plug a network cable into your board and connect to your network. For example, just plug your Ethernet board into your broadband router, which will act as a DHCP server.
*Compile and then program the code into your device.
*Start the Swordfish Serial Communicator plugin, and a connect to your MCUs USART at 115200 baud.
*Reset the MCU.

If all goes well, something like the following should be displayed in the Serial Communicator window

>>default bgcolor=#f5f5f5<<
 Waiting for DHCP...
 Host Name    : SWORDFISH     
 MAC Address  : $00 $04 $A3 $00 $00 $00
 IP address    : 192.123.223.1
 Mask          : 255.255.255.0
 Gateway      : 192.123.223.254
>><<

Now enter a numeric IP address and press enter. For example,

>>default bgcolor=#f5f5f5<<
 88.221.127.45
>><<

which should return something like

>>default bgcolor=#f5f5f5<<
 Ping...40 ms
>><<

!!!Sample Code - No DNS
Changed lines 186-188 from:


to:
The next code example is pretty much the same as the above, except it uses the DNS module to resolve a hostname. This means you do not have to enter a numeric IP address. For example,

>>default bgcolor=#f5f5f5<<
 www.microchip.com
>><<

which should return something like

>>default bgcolor=#f5f5f5<<
 Ping...40 ms
>><<

!!!Sample Code with DNS
Added lines 1-351:
=code [=
// device and clock - code will work on an 18F452 as well...
Device = 18F4680
Clock = 20

// important configurations...
#option ENC28J60_CS = PORTD.6
#option NET_ICMP = true  // enable ping
#option NET_DHCP = true  // enable Dynamic Host Configuration Protocol (DHCP)
#option NET_NBNS = true  // enable NETBIOS
Include "NETApp.bas"      // always first!

// TCPIP stack specifics...
Include "NETTypes.bas"
Include "NETUtils.bas"
Include "Tick.bas"
Include "ICMP.bas"

// program helpers...
Include "NETAppDisplay.bas"
Include "usart.bas"
Include "convert.bas"
Include "ISRRX.bas"

// state machine constants...
Const
  SM_HOME = 0,
  SM_GET_RESPONSE = 1,
  SM_FINISHED = 2

// ping variables... 
Dim
  PingState As Byte,
  PingTimer As TICK
{
****************************************************************************
* Name    : Init                                                          *
* Purpose : Initialise timer and state machine                            *
****************************************************************************
}
Sub Init()
  PingTimer = 0
  PingState = SM_HOME
End Sub
{
****************************************************************************
* Name    : Ping                                                          *
* Purpose : Start a ping                                                  *
****************************************************************************
}
Sub Ping(ByRef pIP As String)
  Dim PingIP As IP_ADDR
  If PingState = SM_HOME Then
  If ICMPBeginUsage() Then
    NETUtils.StringToIPAddress(@pIP, PingIP)    
    ICMPSendPing(PingIP.Val)
        PingState = SM_GET_RESPONSE
    PingTimer = TickGet()       
      EndIf
  EndIf 
End Sub
{
****************************************************************************
* Name    : PingTask                                                      *
* Purpose : Process a ping task                                            *
****************************************************************************
}
Function PingTask() As SHORT
  Result = -2 // do nothing...

  // ping has been started, now wait for ping response...
  If PingState = SM_GET_RESPONSE Then
      Result = ICMPGetReply()

      // the request timed out...
      If Result <> - 2 Then
        PingState = SM_FINISHED
      EndIf
  EndIf
 
  // wait at least one second before another ping - remove the ping timer
  // code if you do not need this functionality...
  If PingState = SM_FINISHED And (TickGet() - PingTimer) > 1000 Then
      PingState = SM_HOME
      ICMPEndUsage()
  EndIf
End Function
{
****************************************************************************
* Name    : OnData                                                        *
* Purpose : The TCPIP stack is a co-operative state machine. Therefore, we *
*        : cannot wait around for USART data and use a buffered interrupt *
*        : instead. When a CR is received, set a ReadyToRead flag to true *
****************************************************************************
}
Dim ReadyToRead As Boolean
Event OnData()
  If ISRRX.DataChar = #13 Then
      ReadyToRead = true
  EndIf
End Event

// main program variables...
Dim Result As SHORT
Dim StrIP As String(80)

// program start...
SetBaudrate(br115200)
Init()
#if NET_DHCP
Write("Waiting for DHCP...",13,10)
#else
DisplayConfig
#endif

// use interrupt buffered USART...
ReadyToRead = false
USART.ReadTerminator = 13
ISRRX.Initialize(OnData)

// loop forever...
While true

  // This task performs normal stack task including checking for incoming
  // packet, type of packet and calling appropriate stack entity to process it.
  NETApp.Task
 
  // If the ready to read flag has been set, read a string from the interrupt
  // buffer and start the ping...
  If ReadyToRead Then
      ReadyToRead = false
      ISRRX.ReadStr(StrIP,13)
      USART.Write("Ping...")
      Ping(StrIP)
  EndIf
 
  // Process the ping task state machine...
  Result = PingTask()
  If Result >= 0 Then
      USART.Write(DecToStr(Result), " ms", 13,10)
  ElseIf Result = -1 Then
      USART.Write("timed out",13,10)
  EndIf     
 
  // If DHCP is enabled, display configuration when a DHCP event
  // has occurred...
  #if NET_DHCP
  If NETApp.DHCPEvent() Then
      DisplayConfig()
  EndIf
  #endif   
Wend
=]




=code [=
// device and clock - code will work on an 18F452 as well...
Device = 18F4680
Clock = 20

// important configurations...
#option ENC28J60_CS = PORTD.6
#option NET_ICMP = true  // enable ping
#option NET_DHCP = true  // enable Dynamic Host Configuration Protocol (DHCP)
#option NET_NBNS = true  // enable NETBIOS
#option NET_DNS = true    // enable Domain Name Service (DNS)
Include "NETApp.bas"      // always first!

// TCPIP stack specifics...
Include "NETTypes.bas"
Include "NETUtils.bas"
Include "Tick.bas"
Include "ICMP.bas"
Include "DNS.bas"

// program helpers...
Include "NETAppDisplay.bas"
Include "usart.bas"
Include "convert.bas"
Include "ISRRX.bas"

// state machine constants...
Const
  SM_HOME = 0,
  SM_RESOLVING = 1,
  SM_PING = 2,
  SM_GET_RESPONSE = 3,
  SM_FINISHED = 4

// ping variables... 
Dim
  PingState As Byte,
  PingTimer As TICK,
  PingIP As IP_ADDR
{
****************************************************************************
* Name    : Init                                                          *
* Purpose : Initialise timer and state machine                            *
****************************************************************************
}
Sub Init()
  PingTimer = 0
  PingState = SM_HOME
End Sub
{
****************************************************************************
* Name    : Ping                                                          *
* Purpose : Start a ping                                                  *
****************************************************************************
}
Sub Ping(ByRef pHostname As String)
  If PingState = SM_HOME Then
      If DNSBeginUsage() Then
        DNSResolve(@pHostName, DNS_TYPE_A)
        PingState = SM_RESOLVING
      EndIf   
  EndIf   
End Sub
{
****************************************************************************
* Name    : PingTask                                                      *
* Purpose : Process a ping task                                            *
****************************************************************************
}
Function PingTask() As SHORT
  Dim PingResult As SHORT
 
  // default result is 0
  Result = 0
 
  // resolve hostname to an IP address...
  If PingState = SM_RESOLVING Then
      PingIP.Val = 0
      If DNSIsResolved(PingIP) Then
        DNSEndUsage
       
        // resolved, start ping...
        If PingIP.Val <> 0 Then
            PingState = SM_PING
       
        // unable to resolve, abort...
        Else
            Result = -1
            PingState = SM_HOME
        EndIf
      EndIf
  EndIf
 
  // hostname has been resolved, start ping using
  // the IP address obtained from the DNS server...
  If PingState = SM_PING Then
  If ICMPBeginUsage() Then
    ICMPSendPing(PingIP.Val)
        PingState = SM_GET_RESPONSE
    PingTimer = TickGet()       
      EndIf
  EndIf   
 
  // ping has been started, now wait for ping response...
  If PingState = SM_GET_RESPONSE Then
      PingResult = ICMPGetReply()

      // the request timed out...
      If PingResult = -1 Then
        Result = -2
        PingState = SM_FINISHED

      // echo received, time elapsed is stored in result (units of TICK)
      ElseIf PingResult >= 0 Then
Result = PingResult
PingState = SM_FINISHED
      EndIf
  EndIf
 
  // wait at least one second before another ping - remove the ping timer
  // code if you do not need this functionality...
  If PingState = SM_FINISHED And (TickGet() - PingTimer) > 1000 Then
      PingState = SM_HOME
      ICMPEndUsage()
  EndIf
End Function
{
****************************************************************************
* Name    : OnData                                                        *
* Purpose : The TCPIP stack is a co-operative state machine. Therefore, we *
*        : cannot wait around for USART data and use a buffered interrupt *
*        : instead. When a CR is received, set a ReadyToRead flag to true *
****************************************************************************
}
Dim ReadyToRead As Boolean
Event OnData()
  If ISRRX.DataChar = #13 Then
      ReadyToRead = true
  EndIf
End Event

// main program variables...
Dim Result As SHORT
Dim StrHostname As String(80)

// program start...
SetBaudrate(br115200)
Init()
#if NET_DHCP
Write("Waiting for DHCP...",13,10)
#else
DisplayConfig
#endif

// use interrupt buffered USART...
ReadyToRead = false
USART.ReadTerminator = 13
ISRRX.Initialize(OnData)

// loop forever...
While true

  // This task performs normal stack task including checking for incoming
  // packet, type of packet and calling appropriate stack entity to process it.
  NETApp.Task
 
  // If the ready to read flag has been set, read a string from the interrupt
  // buffer and start the ping...
  If ReadyToRead Then
      ReadyToRead = false
      ISRRX.ReadStr(StrHostname,13)
      USART.Write("Ping...")
      Ping(StrHostname)
  EndIf
 
  // Process the ping task state machine...
  Result = PingTask()
  If Result > 0 Then
      USART.Write(DecToStr(Result), " ms", 13,10)
  ElseIf Result = -1 Then
      USART.Write("Unable to resolve ", StrHostname, 13,10)
  ElseIf Result = -2 Then
      USART.Write("timed out",13,10)
  EndIf     
 
  // If DHCP is enabled, display configuration when a DHCP event
  // has occurred...
  #if NET_DHCP
  If NETApp.DHCPEvent() Then
      DisplayConfig()
  EndIf
  #endif   
Wend
=]