Menu

Use_NetV_as_a_serial_interface

This implementation of NETV, known as NETV8 (8 bits), is made to be used on any PIC18F micro controller with a serial connection to a PC. This guide describes how to use the library with your own project. This is the kind of implementation that is useful if you want to plot variables on a PC, tune a controller, run your hardware with scripts, etc. For an example project, refer to the [UControl] page.

Images

[-img src=Netv ucontrol 1.png: missing =-]

[-img src=IMG 7163.JPG: missing =-]

Assumptions

  • PIC18
  • Hardware UART
  • USB to serial interface, Virtual COM Port (FT232, MCP2200, etc.)

Files

First of all, you need to get the library from our SVN repository. Here are the files that you need:

  • NETVx_Common.c / NETVx_Common.h : The protocol itself (identification, memory access, etc.)
  • NETVx_Shared.c / NETVx_Shared.h : Shared variables
  • NETVx_SerialDriver.c / NETVx_SerialDriver.h : Serial (UART) driver.
  • NETVx_Utils.h: Macros and definitions

Note: x is used for the architecture. For PIC18, x=8, for PIC24, dsPIC30 and dsPIC33F x=16, for PIC32 x=32.

Some files are application-specific for your project:

  • NETVx_Shared_project-name.c / NETVx_Shared_project-name.h : Module definition and shared variables
  • NETVx_bsp.h : Definitions and includes
  • usart.c/usart.h: For a serial implementation you need those files. More details in the next section.

How to use the library in a PIC project

Note: this example is based on the [UControl] project.

Main file

In your main project file (let's call it main.c) you need to add includes:

#include "NETV8_SerialDriver.h"
#include "NETV8_Device.h"
#include "NETV8_Shared.h"

In void main (void) you need to add two lines at the top:

unsigned char canAddr = 0;
BootConfig *bootConfig = NULL;

and the boot config just before your while loop:

    //reading boot config and device configuration
    //MUST BE DONE BEFORE INITIALIZING NETV MODULE
    bootConfig = netv_get_boot_config();

    if (bootConfig)
    {
            //read configuration
            netv_read_boot_config(bootConfig);

            //safety
            bootConfig->module_state = BOOT_NORMAL;

            //verify if we have correct configuration
            //write it back if not updated
            if (bootConfig->table_version !=  MODULE_TABLE_VERSION
            || bootConfig->project_id != MODULE_PROJECT_ID
            || bootConfig->code_version != MODULE_CODE_VERSION)
            {
                    bootConfig->table_version = MODULE_TABLE_VERSION;
                    bootConfig->project_id = MODULE_PROJECT_ID;
                    bootConfig->code_version = MODULE_CODE_VERSION;

                    //Set to default address
                    bootConfig->module_id = 1;

                    //Writing back the boot config for the next version
                    netv_write_boot_config(bootConfig);

                    //set variables to zero
                    init_default_variables();
            }
    }

    //UPDATE NETV ADDRESS
   canAddr = bootConfig->module_id;

In your main loop, you need to add the transceiver function. In that case, I also refresh my variables in the main loop.

    //Main loop
    while(1)
    {
        //Right now will never come out of this function (blocking on serial port)
        netv_transceiver(canAddr);
        update_variables();
    }

In the same main.c file, you need to add several functions:

void netv_proc_message(NETV_MESSAGE *message)
{
    //Handle custom messages...
}

void init_default_variables(void)
{
    memset(&g_globalNETVVariables, 0, sizeof(GlobalNETVVariables));
}

For the [UControl] project, here is what it looks like:

void netv_proc_message(NETV_MESSAGE *message)
{
    //Handle custom messages...
}

void init_default_variables(void)
{
    memset(&g_globalNETVVariables, 0, sizeof(GlobalNETVVariables));
    g_globalNETVVariables.FlashRate = REFRESH_RATE;
}

void update_variables(void)
{
    //Misc.
    REFRESH_RATE = g_globalNETVVariables.FlashRate;
    g_globalNETVVariables.Count = TMR1L;

    //Analog:
    g_globalNETVVariables.Analog0 = adc_buffer[0];
    g_globalNETVVariables.Analog1 = adc_buffer[1];
    g_globalNETVVariables.Analog2 = adc_buffer[2];
    g_globalNETVVariables.Analog3 = adc_buffer[3];
    g_globalNETVVariables.Analog4 = adc_buffer[4];
    g_globalNETVVariables.Analog5 = adc_buffer[5];
    g_globalNETVVariables.Analog6 = adc_buffer[6];
    g_globalNETVVariables.Analog7 = adc_buffer[7];
    g_globalNETVVariables.Analog8 = adc_buffer[8];
    g_globalNETVVariables.Analog9 = adc_buffer[9];
    g_globalNETVVariables.Analog10 = adc_buffer[10];
    g_globalNETVVariables.Analog11 = adc_buffer[11];

    //Pre-computed analog values:   
    g_globalNETVVariables.Temp = adc_get_temp();
    g_globalNETVVariables.Amp = adc_buffer[8] - 512;
}

Finally, you need to deal with incoming data in your ISR:

#pragma interrupt Interrupt_High
void Interrupt_High(void)
{
    unsigned char sauv1;
    unsigned char sauv2;

    sauv1 = PRODL; // Save context
    sauv2 = PRODH;

    if(PIR1bits.RC1IF)  //USART1 RX
    {
        //Handle USART Interrupt
        serial_usart_interrupt_handler();
    }

    PRODL = sauv1;  //Restore context
    PRODH = sauv2;               
}
#pragma code

usart.c/usart.h

Since there is no clear convention of registers and bits name for different PIC controllers, we need to customize the usart.c file for a specific project. The function names are fixed and should not be changed (the SerialDriver wouldn't know where to look).

Here is a typical usart.h file with function prototypes:

#ifndef INC_USART_H
#define INC_USART_H

void setup_usart1(void);
void putc_usart1(char data);
char getc_usart1(void);
char busy_usart1(void);
char datardy_usart1(void);
void puts_usart1(char *data);
void gets_usart1(char *buffer, unsigned char len);

#endif

In the usart.c file, you need to "fill" each function according to the datasheet. You can look in the Microchip's library for inspiration. Here is the file for the [UControl] project:

//Important: this code is strongly inspired from the C18 uart lib because for the moment
//the PIC18F44K22 isn't supported.  Limitations: 8-bits only, no error check, usart1 only

//#include "def.h"
#include "usart.h"
#include "NETV8_Device.h"

void setup_usart1(void)
{
    RCSTA1bits.SPEN = 1;    //Disable serial port

    TXSTA1bits.TX9 = 0;     //8bits transmission
    TXSTA1bits.TXEN = 1;    //Enable transmit
    TXSTA1bits.SYNC = 0;    //Asynchronous
    TXSTA1bits.BRGH = 1;        //1 = High speed

    RCSTA1bits.SPEN = 1;    //Enable serial port
    RCSTA1bits.RX9 = 0;     //8bits reception
    RCSTA1bits.CREN = 1;    //Continuous reception

    BAUDCON1bits.BRG16 = 0; //1 = 16bits
    SPBRG1 = 51;            //8 = 115200, 16 = 57600, 103 = 9600, 51 = 19200 @ 64MHz

    PIE1bits.RC1IE = 1;     //Enable interrupt on reception

    RCSTA1bits.SPEN = 1;    //Enable serial port
}

void putc_usart1(char data)
{   
    TXREG1 = data;          //Write the data byte to the USART1
}

char getc_usart1(void)
{   
    return (RCREG1);        // Return the received data 
}

char busy_usart1(void)
{
  if(!TXSTA1bits.TRMT)  // Is the transmit shift register empty
        return 1;       // No, return FALSE
  return 0;             // Return TRUE
}

char datardy_usart1(void)
{
  if(PIR1bits.RC1IF)    // If RCIF is set
        return 1;       // Data is available, return TRUE
  return 0;             // Data not available, return FALSE
}

void gets_usart1(char *buffer, unsigned char len)
{
    char i;                         // Length counter
    unsigned char data;

    for(i=0;i

NETVx_Shared_project-name.c/NETVx_Shared_project-name.c

The NETVx_Shared_project-name.h file contains the data structure GlobalNETVVariables that Network Viewer can read and write. Here is an example:

#ifndef _NETV8_SHARED_UCONTROL_H_
#define _NETV8_SHARED_UCONTROL_H_

#include "NETV8_Utils.h"

#define MODULE_TABLE_VERSION 0x02
#define MODULE_PROJECT_ID 0x01
#define MODULE_CODE_VERSION 0x01

typedef struct 
{
        uint16  FlashRate;
        uint8   Count;
        uint8   Free;
        uint16  Analog0;
        uint16  Analog1;
        uint16  Analog2;
        uint16  Analog3;
        uint16  Analog4;
        uint16  Analog5;
        uint16  Analog6;
        uint16  Analog7;
        uint16  Analog8;
        uint16  Analog9;
        uint16  Analog10;
        uint16  Analog11;
        uint16  Temp;
        sint16  Amp;
        uint16  Volt1;
        uint16  Volt2;

} GlobalNETVVariables;

#endif

The NETVx_Shared_project-name.c only is minimalist and only contains an include:

#include "NETV8_Shared_ucontrol.h"

bsp.h

For the moment the bsp.h file is simple and only contains some definitions:

#ifndef _BSP_UCONTROL_H_
#define _BSP_UCONTROL_H_

#include <p18f44k22.h>

#include "NETV8_Shared_ucontrol.h"

#define DEVID_BASE_ADDRESS 0x3FFFFE

#endif

How to use your PIC project with Network Viewer

Now that the PIC is programmed with the library, there is one last step to use it with Network Viewer: the XML config file. All the necessery information to write an application-specific file is on the [NetworkViewer] page. Here is an example:

<ModuleConfiguration moduleState="-1" deviceID="-1" projectID="1" codeVersion="-1" processorID="-1" tableVersion="-1" >
     <ModuleVariable offset="0"  description="Alive LED flash rate" type="uint16"  value="" name="FlashRate" />
     <ModuleVariable offset="2"  description="Counter" type="uint8" value="" name="Count" />
     <ModuleVariable offset="3"  description="Unused" type="uint8" value="" name="Free" />
     <ModuleVariable offset="4"  description="Analog input 0" type="uint16" value="" name="Analog0" />
     <ModuleVariable offset="6"  description="Analog input 1" type="uint16" value="" name="Analog1" />
     <ModuleVariable offset="8"  description="Analog input 2" type="uint16" value="" name="Analog2" />
     <ModuleVariable offset="10"  description="Analog input 3" type="uint16" value="" name="Analog3" />
     <ModuleVariable offset="12"  description="Analog input 4" type="uint16" value="" name="Analog4" />
     <ModuleVariable offset="14"  description="Analog input 5" type="uint16" value="" name="Analog5" />
     <ModuleVariable offset="16"  description="Analog input 6" type="uint16" value="" name="Analog6" />
     <ModuleVariable offset="18"  description="Analog input 7" type="uint16" value="" name="Analog7" />
     <ModuleVariable offset="20"  description="Analog input 8" type="uint16" value="" name="Analog8" />
     <ModuleVariable offset="22"  description="Analog input 9" type="uint16" value="" name="Analog9" />
     <ModuleVariable offset="24"  description="Analog input 10" type="uint16" value="" name="Analog10" />
     <ModuleVariable offset="26"  description="Analog input 11" type="uint16" value="" name="Analog11" />
     <ModuleVariable offset="28"  description="Temperature" type="uint16" value="" name="Temp" />
     <ModuleVariable offset="30"  description="Current" type="sint16" value="" name="Amp" />
     <ModuleVariable offset="32"  description="Voltage channel 1" type="uint16" value="" name="Volt1" />
     <ModuleVariable offset="34"  description="Voltage channel 2" type="uint16" value="" name="Volt2" />
</ModuleConfiguration>


Related

OpenECoSys-Wiki: NetworkViewer
OpenECoSys-Wiki: UControl

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.