Creating Wi-Fi® and Ethernet Applications Using MPLAB® Harmony Framework

Last modified by Microchip on 2023/11/09 09:12

I. Introduction

This article describes the process of creating a simple Wi-Fi® and Ethernet application on a PIC32MX microcontroller using the MPLAB® Harmony software framework. The concept is equally applicable when you want to add Wi-Fi and/or Ethernet functionality to an existing PIC32 Harmony project.

Reference Materials

Board View of WINC1500 inserteted into Explorer 16/32 Development Board slot

Reference Documents

Alternate Development Tools

If you do not have the specific tools listed above, you can study the process of configuring drivers in MHC as shown in this article, and port it to other combinations of development tools. For example:

Back to Top

II. Getting Started

You will implement a TCP server running on the PIC32 microcontroller which is connected to a local Wi-Fi network through the WINC1500 module in Bypass mode (i.e. using Harmony TCP/IP Stack instead of the on-board WINC TCP/IP Stack). At present, the Harmony driver for WINC1500 is only supported with FreeRTOS to maintain the non-blocking behavior of the Harmony framework. You will use the latest FreeRTOS version that is bundled with the Harmony installation. The “Application Templates” feature in Harmony provides a good base to build custom applications. You will use the TCP server template to write your code. Once Wi-Fi is working, you will extend this project by adding the Ethernet function to it.

III. Using MPLAB MHC plugin to import, configure modules and generate application templates

Create New Project
Start MPLAB X IDE and create a new project.
Select '32-bit MPLAB Harmony Project'.

Complete the Harmony project details as shown in the image below.

You can keep the default Project Location in the applications folder or set a desired one as shown below.

Enter an appropriate 'Configuration Name'.

If there is no target board available for your microcontroller, leave it blank. It helps import respective board support packages.

Click on the Finish button to create a project which launches the MHC by default.

MPLAB X IDE new project dialog

Configuring FreeRTOS

Under the MPLAB Harmony Configurator 'Options' tab, expand 'Third Party Libraries' and 'RTOS' trees:

  • Check the 'Use RTOS?' box to enable it
  • Set 'Select RTOS' to FreeRTOS

Select the first FreeRTOS option which is the latest version.

MPLAB Harmony Configurator 'Options' tab

Expand the 'RTOS Configuration' tree:

  • Set 'Tick rate (Hz)' to 1000
  • Set 'Minimal stack size' to 512 bytes
  • Set 'ISR stack size' to 512 bytes
  • Set 'Memory management type' to Heap 2
  • Set 'Total heap size' to 40960 bytes

The increased stack and heap sizes are to accommodate TCP/IP and Wi-Fi driver tasks.

Note that timer and clock speed options are locked to specified values. This indicates Timer 1 is used by FreeRTOS to manage ticks. Each module (drivers and system services) in MHC will contain its own RTOS configuration settings which will be addressed in the following sections. 

MHC RTOS configuration settings view

Setting FreeRTOS Application Task(s)

Under the MHC 'Options' tab, expand the 'Application Configuration' tree:

  • Set the 'Number of Applications' to 1

For now, you are creating only one application.

Expand the 'Application 0 Configuration' tree:

  • Set the 'Application Name' to something meaningful (for example wnetcom)

This is your Wi-Fi network application.

  • Enable 'Generate Application Code For Selected Harmony Components'

Expand TCPIP:

  • Enable 'TCP Server: Transmit and Receive (same socket)'

If you want, change the TCP template parameters (port, text, etc.). Otherwise, keep them as default.

If you are adding a new application to an existing project, make sure you increment the 'Number of Applications' number and select the appropriate 'Application-‘n’-Configuration'. 

Under 'Application 0 Configuration' expand 'RTOS Configuration':

  • Set 'Task Priority' to 2
  • Enable 'Use Task Delay?' by checking the box
  • Set 'Task Delay' to 1

MHC will highlight a conflict at this point. You may notice grayed-out modules in MHC. Ignore them for now. You will resolve them later.
 

Grayed out modules in MHC window. Ignore them for now.

Using Board Support Package (BSP)
Expand the 'BSP Configuration' tree.

Under 'Select BSP To Use For PIC32MX795F512L Device' check the 'PIC32MX795F512L PIM w\Explorer 16' box to enable it.

Check the 'PIC32MX795F512L PIM w\Explorer 16' box to enable it

Setting FreeRTOS System Task
Under the MPLAB Harmony Configurator 'Options' tab, expand the 'Harmony Framework Configuration' tree.

Expand the 'RTOS Configuration' tree:

  • Set 'System Task Size' to 2048
  • Set 'System Task Priority' to 3
  • Enable 'Use System Task Delay?' by checking the box
  • Set 'System Task Delay' to 1

'RTOS Configuration' tree

At this point, you have configured a FreeRTOS system task a and FreeRTOS application task.

To achieve consistency with the Harmony structure without RTOS (i.e. a SYS_Tasks() super loop), MHC will provide you a choice to include further driver tasks as a part of a 'system task' or to be a 'standalone task'. You will set drivers and systems services as part of the 'system task' whereas the Wi-Fi driver has to be run as a 'standalone task'.

Debug and Reset System Services

The WINC1500 Wi-Fi driver uses the Debug system service to send logs to the console output.

Under 'Harmony Framework Configuration', expand 'System Services'.

Expand 'Debug':

  • Enable 'Use Debug System Service?' by checking the box
  • Set 'Debug Print Buffer Size' to 512

'Use Debug System Service?' box

Expand 'Reset' system service:

  • Check the 'Use Reset System Service?' to enable it if not already enabled.

'Use Reset System Service?' box

MHC has interdependencies between modules. Enabling one module sometimes enables the dependent modules. 

Command and Console System Service

For any embedded project, it is important to have a way of printing messages to the console for debugging purposes. For this project, you will use the Harmony Command and Console System Service to send messages to a host computer using the UART module. The Explorer 16 board features a UART communication interface (Refer to the Explorer 16 User’s Guide).

Expand the 'Command' tree:

  • Enable 'Use Command Processor System Service?' by checking the box
  • Under 'RTOS Configuration', set 'Run Library Tasks As' to Combined with System Tasks
  • Set 'Command Print Buffer Size' to 1024 bytes

'Use Command Processor System Service?' box

Expand the 'Console' tree:

  • Enable 'Use Console System Service?' by checking the box
  • Set 'Select Peripheral for Console instance' to UART_CONSOLE
  • Under 'RTOS Configuration (Instance 0)', set 'Run Library Tasks As' to Combined with System Tasks

'Use Console System Service?' box

In the following steps, you will be configuring the corresponding UART driver to work with the console service.

Under 'Harmony Framework Configuration' expand 'Drivers'.

The 'Use USART Driver?' module should already be enabled because of the previous step.

Expand 'USART Driver Instance 0':

  • Under 'RTOS Configuration (Instance 0)', 'Run This Driver Instance As' to Combined with System Tasks
  • Set 'USART Module ID' to USART_ID_2

This is because the Explorer 16 board UART2 is connected to the UART interface.

'Use USART Driver?' module enabled

To complete UART driver configuration you will need to assign Tx/Rx pins for UART2 module. From the schematics (Refer to Explorer 16 Development Board User’s Guide), note that U2RX is pin-49 (RF4) and U2TX is pin-50 (RF5).

Go to MHC 'Pin Table' in MPLAB X IDE and click on the corresponding pin boxes:

MHC 'Pin Table' in MPLAB X IDE

or you can go to 'Pin Settings' tab and modify the function column for respective pins:

'Pin Settings' tab

Sometimes there may be a conflict with pin assignments. You will need to un-assign them from the pin table first.

You can right-click on the module name in Pin Table and isolate them for a better view as shown above. 

To revert, right click on module name>show> all.

Configuring TCP/IP Module:

Expand 'TCP/IP Stack' tree:

  • 'Use TCP/IP Stack?' should already be enabled due to the TCP template configuration in Step 3.

Expand 'Use TCP\IP Stack?' tree:

  • Under 'RTOS Configuration', set 'Run Library Tasks As' to Combined with System Tasks

Expand 'Network Configuration 0' tree:

  • Set 'Interface' to WINC1500
  • Enter a suitable 'Host Name' (for example: PIC32_WINC)

​Sometimes there may be a conflict with pin assignments. You will need to un-assign them from the pin table first.

You can right click on module name in Pin Table and isolate them for a better view as shown above.

The TCP/IP Stack can support multiple network interfaces. For example, you can have a single Wi-Fi or simultaneous Ethernet and Wi-Fi interfaces defined here. For this article, you will only use one Wi-Fi instance.

Leave other network parameters for the TCP/IP Stack to configure since we use DHCP client to get valid IP address (if you want to use static IP, enter it here and disable DHCP client). 

Network parameters for the TCP/IP Stack

Under 'Network Configuration Start-up Flags', make sure that 'DNS Client Enabled on this Interface' is checked.
Enable 'Use ICMPv4 Server'
This will allow you to use the ping service.

The WINC1500 Wi-Fi driver uses Wi-Fi commands:

  • Enable 'Use TCP/IP Commands':
    • Check 'Enable Storage for Stack Commands'
    • Check 'Enable Wi-Fi Related Commands'

Check 'Enable Storage for Stack Commands' and Check 'Enable Wi-Fi Related Commands'

Configuring Timer System Service and Timer Driver

At this point, you will need to configure corresponding drivers and services for the TCP/IP Stack. The TCP/IP Stack uses Timer System Service to keep track of all the timeout events. After looking at the Timer System Service, you will notice that it uses 'Timer Driver instance 0'. This means you will need to configure both Timer System Service and Timer Driver (which will be done in this Step). Also, since the PIC32 communicates to the WINC1500 module via an SPI interface on the Explorer 16 board, you need to configure two drivers: Wi-Fi (Step 10) and SPI (Step 12).

Under System Services >Timer:

  • Under 'RTOS Configuration', set 'Run Library Tasks As' to Combined with System Tasks
  • Check the 'Interrupt Notification Enabled' box

'RTOS Configuration': Set 'Run Library Tasks As' to Combined with System Tasks and Check the 'Interrupt Notification Enabled' box

Under 'Harmony Framework Configuration':

  • Expand 'Drivers'.

In Timer driver, MHC has detected a conflict. Expand it to see why.

Under 'TMR Driver Instance 0':

  • Set 'Timer Module ID' to TMR_ID_2
  • Under 'RTOS Configuration (Instance 0)', set 'Interrupt Priority' to INT_PRIORITY_LEVEL4

Remember that Timer 1 is already dedicated to FreeRTOS. This should resolve the conflict. 

'TMR Driver Instance 0':   Set 'Timer Module ID' to TMR_ID_2,  Under 'RTOS Configuration (Instance 0)', set 'Interrupt Priority' to INT_PRIORITY_LEVEL4  ​

Configuring Wi-Fi Driver

Under 'Drivers':

  • Disable 'Use Internal Ethernet MAC Driver?' by unchecking the box

Unchecking the box

This is important because enabling the TCP module in Step 3 - Setting up FreeRTOS Application Task(s) enables the Ethernet driver by default. In order to use Wi-Fi, you must disable it for this project. 

Under the 'Wi-Fi' driver:

  • Enable 'Use Wi-Fi Driver?'
  • Set 'Wi-Fi Device' to WINC1500
  • Under 'RTOS Configuration', ensure that 'Run Wi-Fi Driver RTOS Task' is set to Standalone
  • Ensure 'Wi-Fi Network Type' is set to Infrastructure which means you will connect the WINC1500 to an existing Wi-Fi network
  • Enter the 'Wi-Fi SSID' in the space provided or indicated by <Your Wi-Fi Name> in the image below
  • Set 'Wi-Fi Security Mode' to your security mode
  • Enter the 'Wi-Fi WPA-PSK' or 'WPA2-PSK Pass Phrase' in the space provided or indicated by <Your Wi-Fi Password> in the image below

Set WINC1500 Pin Port Channels and Pin Bit Positions

You can determine the Pin Port Channels and Pin Bit Positions by examining Appendix A-1. The WINC1500 to PIC32 connections are shown in the table below:

WINC1500 pinPIC32 Pin PortPIC32 Pin Bit
Chip EnableF1
ResetF0
InterruptE8 (INT10)
SPI ClockD10 (SCK1)
SPI Data IND0 (SDO1)
SPI Data OUTC4 (SDI1)
SPI Slave SelectD9 (SS1)

Set WINC1500 Pin Port Channels and Pin Bit Positions

Go to the Harmony 'Pin Settings' tab and change 'Function' for pin number 87 (RF0) and 88 (RF1) to GPIO_OUT. These two pins are Reset and Chip Enable. You will set the SPI pins later in Step 12.

Harmony 'Pin Settings' tab

Note that you will be using the External Interrupt for Change Notification. This means you need to configure External Interrupt Service under 'System Services' (Step 11). 

Setting External Interrupt System Services

Go to System Services > Interrupts:

  • Enable 'Use External Interrupts?' by checking the box

External interrupts will be used by the Wi-Fi driver.

Ensure 'External Interrupt Instance 0' is enabled:

  • Set 'External Interrupt Module ID' to INT_EXTERNAL_INT_SOURCE_1

This will connect the WINC1500 interrupt pin to the PIC32 INT1 pin.

  • Enable 'Generate ISR Code?' :
    • Set 'Interrupt Priority' to INT_PRIORITY_LEVEL3
    • Set 'Interrupt Sub-priority' to INT_SUBPRIORITY_LEVEL1
    • Set 'Polarity' to INT_EDGE_TRIGGER_FALLING

Interrupt Settings View

In the Pin Table:

  • Assign pin 18 (RE8) to the External Interrupt 1 module.

Assign pin 18 (RE8) to the External Interrupt 1 module

Configuring SPI Driver:

You will be using the SPI driver in interrupt mode.

You may see MHC showing the SPI driver grayed out. 

Enable 'Use Interrupt Mode?' by checking the box

Enable 'Use Interrupt Mode?' by checking box

Under 'SPI Driver Instance 0':

  • Set 'RTOS Configuration (Instance 0)' to Combined with System Tasks
  • Set 'SPI Module ID' to SPI_ID_1
  • Enable 'Driver Mode' by checking the 'Interrupt Mode' box (This should resolve the SPI issue.)
  • Set 'Clock Mode' to DRV_SPI_CLOCK_MODE_IDLE_LOW_EDGE_FALL
  • Set 'Dummy Byte Value' to 0x00

'SPI Driver Instance 0' Settings

In the Pin Table, assign SPI1 (SPI_ID_1) pins as:

  • SCK1 = pin 70 (RD10)
  • SDI1 = pin 9 (RC4)
  • SDO1 = pin 72 (RD0)
  • SS1 = pin 69 (RD9).

Pin Table View

Complete the MHC Configuration
Click on the Generate Code button in the MHC toolbar.
Save the configuration in next popup window.

In the Generate Project window ,select desired merging strategy and click Generate.

In the merge window, ignore all the differences for wnetcom.c file and click Close. This happens because MHC is comparing a fresh TCP template with your modified one. 

Generate Project window view

You will notice several source files and header files created in the project window.

  • main.c file has the generic state machine while loop.
  • wnetcom.c file is your application file where you will be writing and updating code.

All the variable and state names will be coherent with your application name defined in Step 3.

Source files and header files created are shown in project window

You can close MHC now. To re-open, set the project as Main Project and go to Tools> Embedded > MHC 

Back to Top

IV. Adding code to the application template

In this section you will write a simple LED toggle application that receives commands from the Tera Term terminal emulation program which acts as a TCP Client.

In the wnetcom.c file (under Source Files > app >), you will notice that MHC has generated a basic TCP server template for you. The three functions are:

  • void WNETCOM_Initialize (void)
  • void WNETCOM_Tasks (void)
  • static void TCP_Server_TXRX_Task (void)

The basic flow of the project is as follows:

  1. Check if TCP/IP Stack is successfully initialized. Proceed after successful initialization.
  2. Check the number of available network interfaces. (in our case, it’s only 1: Wi-Fi)
  3. Wait till the interface receives a valid IP address from the DHCP server.
  4. After receiving a valid IP, open a TCP server socket on the specified port.
  5. Wait for incoming connection from a TCP Client.
  6. After receiving a TCP Client connection, send the greeting “Hello Client!”
  7. Wait for any messages from the client and parse them. Toggle LED on Explorer 16 board if a valid message is received.
  8. Keep checking the connection continuously.
  9. Notify when the client disconnects.
  10. Go back to step (5).

API functions used are:
(You can read their description in C:\microchip\harmony\v2_04\doc\help_harmony.htm file)

  • TCPIP_STACK_Status()
  • TCPIP_STACK_NumberOfNetworksGet()
  • TCPIP_STACK_IndexToNet()
  • TCPIP_STACK_NetAddress()
  • TCPIP_STACK_NetIsReady()
  • TCPIP_TCP_ServerOpen()
  • TCPIP_TCP_ArrayPut()
  • TCPIP_TCP_GetIsReady()
  • TCPIP_TCP_ArrayGet()

By referring to the code flow above and the API functions, analyze the application structure. Let’s start adding code to your application file. (Line numbers in the images are for reference only and may vary in your project).

In the WNETCOM_Tasks() function and WNETCOM_STATE_INIT state, Change the appInitialized declaration to false.

bool appInitialized = false;

WNETCOM_Tasks() function

If TCPIP_STACK_Status() returns a negative value, notify the user that TCP Stack Initialization has failed. You will use the console service API to send formatted strings to the serial terminal.

Make sure you put console print statements before state variable changes in the code. Otherwise, the logs may be confusing!

SYS_CONSOLE_PRINT("WNETCOM[%d]: TCP/IP stack initialization failed!\r\n", wnetcomData.state);

Console print statements before state variable changes

Add these lines to set appInitialized equal to true when the TCP/IP Stack becomes ready and display a message.

appInitialized = true;
SYS_CONSOLE_PRINT("WNETCOM[%d]: TCP/IP stack initialized!\r\n", wnetcomData.state);

SYS_CONSOLE_PRINT("WNETCOM[%d]: TCP/IP stack initialized!\r\n", wnetcomData.state);

Add another console message while exiting the WNETCOM_STATE_INIT state.

SYS_CONSOLE_PRINT("WNETCOM[%d]: Application initialized!\r\n", wnetcomData.state);

SYS_CONSOLE_PRINT("WNETCOM[%d]: Application initialized!\r\n", wnetcomData.state);

At this point, the function WNETCOM_Tasks() enters state WNETCOM_STATE_SERVICE_TASKS where it is executing TCP_Server_TXRX_Task() continuously. This function maintains its own state machine to handle the TCP server.

In the WNETCOM_STATE_INIT state, set the TXRX state machine in WNETCOM_TCPIP_WAIT_FOR_IP after TCP/IP Stack state becomes SYS_STATUS_READY. Change the TXRX function code in the WNETCOM_TCPIP_WAIT_FOR_IP state as follows:

case WNETCOM_TCPIP_WAIT_FOR_IP:
       {
           // Check if the IP address of an interface has changed
            wnetcom_nNets = TCPIP_STACK_NumberOfNetworksGet();
            for (i = 0; i < wnetcom_nNets; i++)
            {
                wnetcom_netH = TCPIP_STACK_IndexToNetinformation;
                ipAddr.Val = TCPIP_STACK_NetAddress(wnetcom_netH);
                if (dwLastIP[i].Val != ipAddr.Val)
                {
                    dwLastIP[i].Val = ipAddr.Val;
                    SYS_CONSOLE_PRINT("TCP_TXRX[%d]: IP Address: ", wnetcomData.txrxTaskState);
                    SYS_CONSOLE_PRINT("%d.%d.%d.%d \r\n", ipAddr.v[0], ipAddr.v[1],
                            ipAddr.v[2], ipAddr.v[3]);
                    if (ipAddr.v[0] != 0 && ipAddr.v[0] != 169) // Wait for a Valid IP
                    {
                        wnetcomData. txrxTaskState = WNETCOM_TCPIP_OPENING_SERVER;
                    }
                }
            }           
        }
        break;

TCP_Server_TXRX_Task()  function view

Once a valid IP Address is received, proceed to open a TCP server. Add a couple of console statements to WNETCOM_TCPIP_OPENING_SERVER state for checking (code locations as shown in image below).

  SYS_CONSOLE_PRINT("TCP_TXRX[%d]: Couldn't open server socket\r\n", wnetcomData.txrxTaskState);
  SYS_CONSOLE_PRINT("TCP_TXRX[%d]: Waiting for Client Connection on port: %d\r\n",
                    wnetcomData.txrxTaskState, wnetcomData.port);

Add statements to WNETCOM_TCPIP_OPENING_SERVER state

Wait till you receive a connection. You can implement a timeout here using a Timer if you want. Send a greeting to the client and change state to wait for client response in the state WNETCOM_TCPIP_WAIT_FOR_CONNECTION.

SYS_CONSOLE_MESSAGE("WNETCOM: Received a connection\r\n");

SYS_CONSOLE_MESSAGE("WNETCOM: Received a connection\r\n"); function view

Modify WNETCOM_TCPIP_WAIT_FOR_RESPONSE state so that if connection is closed, state will be changed to WNETCOM_TCPIP_WAIT_FOR_CONNECTION. If data is received from the client, parse it and add logic for toggling LED’s.

case WNETCOM_TCPIP_WAIT_FOR_RESPONSE:
        {
            if (!TCPIP_TCP_IsConnected(wnetcomData.socket))
            {
                SYS_CONSOLE_PRINT("TCP_TXRX[%d]: Connection closed/lost\r\n", wnetcomData.txrxTaskState);
                SYS_CONSOLE_PRINT("TCP_TXRX[%d]: Waiting for Client Connection on port: %d\r\n",
                        wnetcomData.txrxTaskState, wnetcomData.port);
                wnetcomData.txrxTaskState = WNETCOM_TCPIP_WAIT_FOR_CONNECTION;
                break;
            }
            if (TCPIP_TCP_GetIsReady(wnetcomData.socket))
            {
                TCPIP_TCP_ArrayGet(wnetcomData.socket, wnetcomMsgFromClient, sizeof(wnetcomMsgFromClient) - 1);
                SYS_CONSOLE_PRINT("TCP_TXRX[%d]: Client sent: %s\r\n",
                        wnetcomData.txrxTaskState, wnetcomMsgFromClient);
                if (strncmp((char*) wnetcomMsgFromClient, (const char *) "toggle D", 8) == 0)
                {
                    if (wnetcomMsgFromClient[8] == '3')
                    {
                        BSP_LEDToggle(BSP_LED_3);
                        SYS_CONSOLE_PRINT("TCP_TXRX[%d]: LED D%c is toggled\r\n",
                                wnetcomData.txrxTaskState, wnetcomMsgFromClient[8]);
                    }
                    if (wnetcomMsgFromClient[8] == '4')
                    {
                        BSP_LEDToggle(BSP_LED_4);
                        SYS_CONSOLE_PRINT("TCP_TXRX[%d]: LED D%c is toggled\r\n",
                                wnetcomData.txrxTaskState, wnetcomMsgFromClient[8]);
                    }
                }
            }
        }
        break;

WNETCOM_TCPIP_WAIT_FOR_RESPONSE view

All the necessary changes are complete. Feel free to modify the parsing code, add more states to the TXRX function to handle the closing of sockets, or implement timeout for sockets and so on.

  • Save changes
  • Click on Clean and Build Main Project icon in the MPLAB IDE toolbar
  • Check for errors

Do not program the device yet. 

IMPORTANT: If you modify MHC and regenerate the code it will try to overwrite the application file(s) with a fresh template each time. Pay attention to the merge window generated after MHC generate action and keep the custom code as it is.

Merge window generated after MHC generate action

Back to Top

V. PC interface to interact with the PIC32 based TCP server

Connect the serial port connector on Explorer 16 board to the host computer.
Connect the WINC1500 PICtail in top socket of J5 connector (SPI1).

Connect power supply and programmer tool to the Explorer 16 board.

For the Wi-Fi portion of this project, you can plug in only the WINC1500 PICtail Plus daughter board. The ENC624J600 PICtail Plus will be used later. 

WINC1500 PICtail Plus daughter board

Open Tera Term and select the serial interface instance created by Explorer 16 board. You may see a different COM# number. It will open a blank terminal window.

Tera Term  View: Select the serial interface instance created by Explorer 16 board.

Click Make and Program Device Main Project icon in the MPLAB X IDE toolbar.

Once the PIC32 is successfully programmed, you will see the following messages on the serial terminal. These messages include system debug messages as well as console print statements that you just put in. Numbers in square brackets are the state numbers from respective functions for easier debugging.

Messages on the Tera Term serial terminal

Open a new Tera Term instance and select TCP/IP connections. Enter the WINC1500 IP address displayed in the console serial terminal and port number as set in MHC. Protocol as IPv4. (Configure it to echo typed chars)

Tera Term View: Enter the WINC1500 IP address displayed in the console serial terminal and port number

In the newly opened TCP connection, you will receive the greeting from TCP server on PIC32. Enter LED toggle commands as toggle D3 and notice the output on the Explorer 16 board and the serial terminal.

Greeting from TCP server on PIC32

Close the TCP client terminal and notice the output in the console. You can open a new TCP connection and test more.

Output in the console

Back to Top

VI. Adding Ethernet using MHC

Now that you have a working Wi-Fi project you can extend its functionality by adding Ethernet so that you can have simultaneous Wi-Fi and Ethernet.

You will be connecting the Fast 100 Mbps Ethernet PICtail™ Plus Daughter Board (ENC624J600) to the Explorer 16 Development Board or Explorer 16/32 Development Board with a PICtail Plus Expansion Board and communicating via the SPI2 serial interface. You will need to configure the following modules:

  1. TCP/IP Stack
  2. ENCx24J600 driver
  3. SPI driver
  4. Interrupt driver
Configuring the TCP/IP Stack:

In this step you will be configuring the TCP/IP stack to communicate with the Ethernet driver.

Expand the 'TCPIP stack' tree:

The TCP/IP Stack is already configured for one network interface: WINC1500.

  • Change the 'Number of Network Configurations' to 2
  • Under 'Network Configuration 1' tree:
    • Set 'Interface' as ENCx24J600
    • Enter an appropriate 'Host Name' (Example: PIC32_ENC)

Expanded 'TCPIP stack' tree

Configuring the ENCx24J600 driver

In this step, you will be configuring the ENCx24J600 driver.

Under Drivers > ENCx24J600:

  • Enable 'Use ENCx24J600 Driver?' by checking the box

Expand 'ENCx24J600 Driver Instance 0':

  • Set 'SPI Driver Instance Number' to 1

This is because the SPI driver instance 0 is communicating with the WINC1500 Wi-Fi module.

  • Set 'ENCx24J600 SPI Slave Select Port Pin' to PORTS_BIT_POS_12

To identify pin mappings for ENCx24J600 module refer to Appendix A-2.

ENC624J600 pinPIC32 Pin PortPIC32 Pin Bit
InterruptA15 (INT4)
SPI ClockG6 (SCK2)
SPI Data ING8 (SDO2)
SPI Data OUTG7 (SDI2)
SPI Slave SelectF12
ShutdownF13

Expand 'ENCx24J600 Driver Instance 0' and Set 'SPI Driver Instance Number' to 1

In the Pin Settings window

  • Change the Direction (TRIS) and Latch (LAT) of RF12 (pin 40) and RF13 (pin 39) to Out and High.

Pin Settings window

Configuring the SPI Driver

In this step, you will be configuring the SPI driver to communicate with the ENC624J600 PICtail Plus daughter board via the SPI2 serial communications port.

Expand the 'SPI Driver' tree:

  • Change the 'Number of SPI Driver Instances' to 2

Under 'SPI Driver Instance 1' tree:

  • Under 'RTOS Configuration (Instance 1)', set 'Run This Driver Instance As' to Combined with System Tasks
  • Set 'SPI Module ID' to SPI_ID_2
  • Set 'Clock\Baud Rate - Hz' to 13333333
  • Set 'Clock Mode' to DRV_SPI_CLOCK_MODE_IDLE_LOW_EDGE_FALL
  • Set 'Input Phase' to SPI_INPUT_SAMPLING_AT_END

Expanded 'SPI Driver' tree

In the Pin Table, assign SPI2 (SPI_ID_2) pins as:

  • SCK2 = pin 10 (RG6)
  • SDI2 = pin 11 (RG7)
  • SDO2 = pin 12 (RG8)

You do not need to assign SS2 in the Pin Table as it was assigned in Step 2.b above.

Pin Table View

Setting External Interrupt System Service

In this step, you will be configuring the External Interrupt to communicate with the ENC62J600 PICtail Plus daughter board.

Under System Services > Interrupts:

  • Change the 'Number of External Interrupt Instances' to 2

To be used by the ENC driver.

Under 'External Interrupt Instance 1':

  • Change 'External Interrupt Module ID' to INT_EXTERNAL_INT_SOURCE_4

Because the ENCx24J600 interrupt pin connects to INT4.

  • Enable 'Generate ISR Code?' by checking the box
    • Set 'Interrupt Priority' to INT_PRIORITY_LEVEL3
    • Set 'Interrupt Sub-priority' to INT_SUBPRIORITY_LEVEL1
    • Set 'Polarity' to INT_EDGE_TRIGGER_FALLING

System Services > Interrupts View

In the Pin Table, assign:

  • pin 67 (RA15) to External Interrupt 4 Module

Pin Table View

Completing the MHC Configuration
Click on Generate Code button in MHC toolbar.
Save the configuration in next popup window.

In the Generate Project window, select desired 'merging strategy' and click Generate.

In the merge window, ignore all the differences for wnetcom.c file and click Close. This happens because MHC is comparing a fresh TCP template with your modified one.

Merge window view

Modifying Application code

In order to use the Command System Service to receive commands from the serial terminal, you need to add SYS_CMD_READY_TO_READ() function to the application loop. The function is necessary for the Command System Service and Console System Service to function correctly. You will call it in WNETCOM_Tasks() function in WNETCOM_STATE_SERVICE_TASKS state.

SYS_CMD_READY_TO_READ();

SYS_CMD_READY_TO_READ() function view

Back to Top

VII. Testing Your New Application

Connect the serial port connector on Explorer 16 Development Board to the host computer.
Connect the WINC1500 PICtail/PICtail PLUS daughter board in top socket of J5 connector (SPI1).

Connect power supply and programmer tool to the Explorer 16. board.

WINC1500 PICtail/PICtail PLUS daughter board plugging into Explorer 16 board

Open Tera Term and select the serial interface instance (see Section V Step 4).

Click Make and Program Device Main Project icon in the MPLAB X IDE toolbar.

Once the PIC32 is successfully programmed, you will see similar messages on the serial terminal as before (see Section V Step 5.

Messages on the Tera Term serial terminal

You can make use of TCP/IP Commands available in the Harmony TCP/IP Stack. In the serial terminal, type command netinfo and observe the output. It will show the details of available interfaces and their status. You may notice that the interface names will match with the ones entered in MHC TCP/IP Stack settings.

Command "netinfo" output. It shows the details of available interfaces and their status.

As a simple test, pull out the Ethernet cable from the ENC module and notice the output from netinfo command again.
At this point, feel free to modify the socket function call to open the server socket on the desired interface. You may implement two different sockets (TCP Client or Server) listening on different interfaces.

VIII. Instructions for migrating this project

Things to take care of when using different hardware:

Which peripheral can be used for console I/O? For example, on some boards, you might have to use the USB CDC console.

Expand the 'Console' tree:

  • Set 'Select Peripheral For Console Instance' to USB_CDC_CONSOLE

Expanded 'Console' tree

Expand 'USB Library' tree:
  • Under 'USB Device Instance 0'

    • Set 'Product ID Selection' to cdc_com_port_single_demo

The Product ID selection will populate the Vendor and Product IDs for the USB Device which are necessary for the USB device enumeration.

Expanded 'USB Library' tree

Figure out the connections for your hardware. For example, on the Curiosity PIC32MZEF Development Board, there is a MRF24WN0MA module populated. Figure out how it interfaces with the onboard PIC32 microcontroller. Change the Wi-Fi and SPI drivers accordingly. Please refer to the Curiosity demo available on its product page for more information.

Taking it further

  • Try adding this Wi-Fi or Ethernet driver to an existing project to add connectivity.
  • Study the demo “wifi_easy_configuration” located at C:\microchip\harmony\v2_04\apps\tcpip
  • Study other interesting Harmony demo’s located in the install directory C:\microchip\harmony\v2_04\apps
  • Visit Microchip Developer Help website (http://microchipdeveloper.com/harmony:start) for more tutorials.

Back to Top

IX. Troubleshooting

If you are having problems, please refer to the Microchip Support pages.

Back to Top

Appendix A

A-1 Pin mapping between PIC32MX plug-in-module (PIM) and WINC1500 PICtail module

This section demonstrates how to map a WINC1500 module pin to PIC32 microcontroller pin. Refer to the three figures below for Explorer 16 board, WINC1500 module and PIC32MX plug-in-module. An example of a pin mapping process is also provided after the third figure.

1. PICtail Plus connector on Explorer 16 board showing top socket:

Pin mapping showing PIC32MX plug-in-module (PIM) and WINC1500 PICtail module

2. WINC1500 PICTAIL/PICTAIL PLUS schematics:

WINC1500 PICTAIL/PICTAIL PLUS schematic

3. Explorer 16 board schematic - PIM socket:

Explorer 16 board schematic - PIM socket

Using the three connection diagrams above, find the required plug-in-module(PIM) pins and then look-up those pins in the PIC32MX PIM sheet to get the actual microcontroller pins (As an example of mapping pins - WINC slave select connects to Pin 1 of J5 header on Explorer 16 board which connects to PIM pin 23 which is PIC32 device pin 69 > RD9.)

Here is a snapshot from the PIC32MX PIM sheet:

Snapshot from the PIC32MX PIM sheet:

A-2 Pin mapping between PIC32MX plug-in-module and ENC624J600 PICTail module

1. ENC624J600 Fast 100 Mbps Ethernet PICtail Plus Daughter Board:

Pin mapping between PIC32MX plug-in-module and ENC624J600 PICTail module

Back to Top