Difference between revisions of "NU32v2: Serial Communication with the PC"

From Mech
Jump to navigationJump to search
 
(27 intermediate revisions by 2 users not shown)
Line 1: Line 1:
'''THIS PAGE REFERS TO A PRE-RELEASE VERSION OF THE NU32 PIC32 DEVELOPMENT BOARD. FOR INFORMATION, SAMPLE CODE, AND VIDEOS RELATED TO THE PRODUCTION VERSION (2016 AND LATER), AND TO THE CORRESPONDING BOOK "EMBEDDED COMPUTING AND MECHATRONICS WITH THE PIC32 MICROCONTROLLER," VISIT [[NU32|THE NU32 PAGE]].'''
'''Under construction NDM 1/25/2010'''



Digital inputs and outputs (DIO) are the simplest of interfaces between the PIC and other electronics, sensors, and actuators. The PIC32 has many DIO pins, each of which can take one of two states: high or low.
The NU32v2 has the ability to talk directly with a computer over a virtual serial port connection. This ability can be used to debug code, transfer data, and interact with the microcontroller using a computer.


== Overview ==
== Overview ==


The NU32v2 uses an on board [http://www.ftdichip.com/Products/ICs/FT232R.htm FT233RL] chip from FTDI to convert [http://en.wikipedia.org/wiki/RS-232 RS-232 TTL serial communication] to USB. Using drivers from FTDI, the communication can be opened by any program that can access a serial port. On the NU32v2 side, sample code has been created to enable the UART module on the PIC32. Using this code you can write strings to the computer, and generate an interrupt when characters are received. On the computer side, several programs that can access the serial connection are discussed, including PuTTY, Processing and MATLAB.
The PIC32


== Details ==
== Details ==
The FT232RL chip is hardwired to the UART3 module on the PIC32M795F512L. The Receive (RX) pin, G7, and Transmit (TX) pin, G8, are also brought out to the sides of the NU32v2 board. '''They should not be used as general IO.'''


The NU32v2 Serial Bootloader uses the UART3 module at 115200 baud, as does the code below, but this can be changed as desired.
The functions of the DIO pins are controlled by special function registers (SFRs). Each of these SFRs has 32 bits on the PIC32, but for many, not all 32 are relevant. Depending on whether these bits are set to 0 or 1, different actions or settings are performed:


== Library Functions ==
* '''AD1PCFG''': This SFR determines which of the 16 pins with an analog input function (port B) is treated as an analog input or a DIO pin. The 16 most significant bits (high bits) AD1PCFG<31:16> are ignored, but AD1PCFG<15:0> determine which of the 16 pins is treated as an analog input. 0 indicates analog input, and 1 indicates DIO. So if the bit AD1PCFG<7> is 0, then the pin with the function AN7 is an analog input; if AD1PCFG<7> is 1, then it is a DIO. AD1PCFG resets to 0x0000, so all 16 pins of port B are treated as analog inputs by default. To make AN15 and AN1 analog inputs and the rest DIO, we can use the C command <tt>AD1PCFG = 0x7FFD</tt>. To make AN15 and AN1 analog inputs but leave the other settings unchanged, we can use the C command <tt>AD1PCFG &= 0x7FFD</tt>. Note we only have to specify 16 bits, or 4 hex digits, as the 16 most significant bits have no role. Instead of acting on the entire SFR, we could instead address an individual bit, using <tt>AD1PCFGbits.PCFG15 = 1</tt>, for example, to set the value of a single bit.
[[Media:NU32v2_serial_example.zip | This code]] contains functions to read characters and write strings over the serial port.


NU32v2.h contains function prototypes, in addition to the serial functions, to initialize the LEDs on the NU32v2 board as well as the bootloader button.
<!--
A block diagram of a typical input/output port is shown below, taken from the Reference Manual.


NU32v2.c contains the functions. You do not need to change this file or the .h file need to use serial communication.


The functions that control the serial communication are:
[[Image:pic-gpio-module.png|center]]
*void initSerialNU32v2(void) - enables UART3 at 115200 baud with an interrupt at priority level 2
*void WriteString(UART_MODULE, const char *) - call with UART3 and the character array you wish to send
*void PutCharacter(UART_MODULE, const char) - writes an individual character to the computer when the module is able to, called by WriteString()


NU32v2_serial_example.c contains example code that shows how to use the functions. It also contains the ISR for UART3, with an example of how to receive characters.


== Sample Code ==
OK, this looks pretty complicated, so let's go through it systematically. First, there may be some symbols you are unfamiliar with in this figure. These are all digital logic. Consult the figure below:


To initialize the serial communication, call initSerialNU32v2():
<table border=1 cellpadding=5 align=center>
<tr>
<td>'''Symbol'''</td>
<td>'''Name'''</td>
<td>'''Description'''</td>
</tr>
<tr>
<td>[[Image:pic-hysteresis-buffer.png]]</td>
<td>Schmitt trigger</td>
<td>The output (on the left) is digital, high or low, and matches the input if it is high or low. Because the input may be noisy and take values in between clearly low and clearly high, the gate implements "hysteresis." This means that if the output is currently low, the input must go quite high before the output will switch to high, and if the output is high, the signal must go quite low before the output will switch.</td>
</tr>
<tr>
<td>[[Image:pic-tristate-buffer.png]]</td>
<td>tri-state buffer</td>
<td>If the input coming in from the top is high, the output matches the input. If it is low, the output is high impedance (disconnected).</td>
</tr>
<tr>
<td>[[Image:pic-multiplexer.png]]</td>
<td>multiplexer</td>
<td>Depending on the input coming in from the top, one or the other inputs is passed through to the output.</td>
</tr>
<tr>
<td>[[Image:pic-dflipflop.png]]</td>
<td>D flip-flop</td>
<td>If the D flip-flop is enabled (bottom input), then the input at D is latched through to the output Q when the clock CK goes high. The output only changes on a rising clock edge, and does not change if the flip-flop is not enabled. </td>
</tr>
<tr>
<td>[[Image:pic-logic-or.png]]</td>
<td>logic OR</td>
<td>Outputs the logical OR of the two inputs.</td>
</tr>
<tr>
<td>[[Image:pic-invert-and.png]]</td>
<td>logic AND (with inverted input)</td>
<td>Outputs the logical AND of the two inputs (where one input is inverted, as indicated by the circle).</td>
</tr>
</table>
-->


<pre>
== Library Functions ==
initSerialNU32v2();
</pre>


To write a string to the computer, use WriteString(UART3, charArray)
The peripheral library offers a number of function calls to help you use the DIO pins. These functions have names such as <tt>PORTRead</tt>, <tt>PORTSetPinsDigitalIn</tt>, <tt>PORTSetPinsDigitalOut</tt>, etc. C source code can be found in pic32-libs/peripheral/ports/source/*.c, and .h header files can be found in pic32-libs/include/peripheral/ports.h. Documentation can be found in your MPLAB C32's doc directory, in Microchip-PIC32MX-Peripheral-Library.chm. The DIO functions are simple enough, however, that we will usually just set the appropriate SFRs manually, as described above and demonstrated in the samples below.


<pre>
== Sample Code ==
WriteString(UART3, "\r\nHello World!\r\n");
</pre>


To write a string with the value of a variable in it, use sprintf(RS232_Out_Buffer,charArray) and WriteString(UART3, charArray). RS232_Out_Buffer is declared in NU32v2.h as a char with 32 elements.
This example uses two of the PIC32 pins as digital outputs and one pin as digital input. In particular, it uses pins RG12 and RG13 as outputs, since these are connected to LEDs on the NU32v2 board (by the NU32v2 circuit schematic, the associated LED is on when the pin is low). It configures RG6 as an input for a button press. If RG6 is high, the LEDs will be off. If RG6 is low, the LEDs will be on. Let's assume RG6 is low when the button is pressed (as it is with the NU32v2 and your button in the breadboard).


<pre>
<pre>
sprintf(RS232_Out_Buffer, "the value of i is: %d\r\n", i);
/*
WriteString(UART3, RS232_Out_Buffer);
* Simple digital input/output.
</pre>
*/


To receive characters in an interrupt, use this ISR
#include <plib.h>


<pre>
// No need to configure the configuration bits controlling clock speed, etc.;
void __ISR(_UART_3_VECTOR, ipl2) IntUart3Handler(void) {
// these definitions are in the bootloader.
// Is this an RX interrupt?
if(INTGetFlag(INT_SOURCE_UART_RX(UART3))){
char data = UARTGetDataByte(UART3);


// now do something with data
// Lines below could go into a separate .h file, since they're the same
// for all projects using the NU32v2 and the NU32v2 bootloader.
#define LED0 LATGbits.LATG12
#define LED1 LATGbits.LATG13
#define SW PORTGbits.RG6
#define SYS_FREQ 80000000 // 80 MHz


// Clear the RX interrupt Flag
int main(void) {
INTClearFlag(INT_SOURCE_UART_RX(UART3));
// Turn on the pre-fetch cache, choose the maximum possible peripheral
}
// bus frequency, and choose minimum flash wait states. Could be done in
// bootloader. See pic32-libs/include/peripheral/system.h.
SYSTEMConfig(SYS_FREQ, SYS_CFG_ALL);


// We don't care about TX interrupt
AD1PCFG = 0xFFFF; // sets all port B to DIO. Only needed if using port B.
if(INTGetFlag(INT_SOURCE_UART_TX(UART3))) {
INTClearFlag(INT_SOURCE_UART_TX(UART3));
}
}
</pre>


== PuTTY ==
// Initialize LEDs as output, switch as input. Could be done in bootloader.
PuTTY is a terminal program that will let you open the virtual serial port created by the FTDI driver.
// Note we don't technically have to set switch as an input, since it's the
// default, but let's do it in case someone inserts code before this line.
TRISGCLR = 0x3000; TRISGSET = 0x0040;


Directions to install PuTTY can be found in [[NU32v2: Software to Install#PuTTY Terminal Emulator]]
while(1) {

while(!SW) { // if button is pressed, turn LEDs on
Before launching PuTTY, note the name of your COM port, same name as you use in the Serial Bootloader Application.
LED0 = 0; LED1 = 0;


Launch Putty.exe. Set up your communication by:
*Selecting the 'Serial' radio button

Select the 'Serial' branch in the tree on the bottom left.
*Enter the name of your COM port in 'Serial line to connect to'
*Enter 115200 in 'Speed (baud)'
*Change 'Flow control' from 'XON/XOFF' to 'None'

Go back to the 'Session' screen by selecting the 'Session' in the top left of the tree.
*Name your settings in 'Saved Sessions' and click 'Save'
*Click the 'Open' button

== Processing ==
'''**To Do - Processing basics, see [[Processing]]**'''

The [[Media:NU32v2_stripchart.zip | NU32v2 Stripchart plotting tool]] can be used to plot 1000 data points in each of six traces, with values between 0 and 511, where each new data point is added to the right side of the plot, stripchart style. For example,

<pre>
for (i=0; i<1000; i++) {
// plot on trace a the refValue and on trace b the ADC value
sprintf(RS232_Out_Buffer, "%d %d\r\n", refValue[i]/2, adcValue[i]/2); // max adc is 1023, max plotted value is 511,
// so divide by 2 before sending
WriteString(UART3, RS232_Out_Buffer);
}
}
</pre>
LED0 = 1; LED1 = 1; // when button is released turn LEDs off

The [[Media:NU32v2_plot.zip | NU32v2 Plotting tool]] can be used to plot 1000 data points in each of four traces, with values between 0 and 511.

To plot the values of an array of 1000 integers to trace a, use something like:

<pre>
for (i=0; i<1000; i++) {
sprintf(RS232_Out_Buffer, "a %d %d\r\n", i, adcValue[i]/2); // max adc is 1023, max plotted value is 511,
// so divide by 2 before sending
WriteString(UART3, RS232_Out_Buffer);
}
</pre>

Typing a key while the tool is running will send that character to the microcontroller.
To write a message to the tool from the microcontroller, '''send a string that does not start with a, b, c or d'''.

For example, to change the value of a control gain when the microcontroller receives an 'a' and return the new value of the control gain, try:

<pre>
void __ISR(_UART_3_VECTOR, ipl2) IntUart3Handler(void) {
// Is this an RX interrupt?
if(INTGetFlag(INT_SOURCE_UART_RX(UART3))){
char data = UARTGetDataByte(UART3);

// now do something with data
if (data == 'a') { // increase kp
kp=kp+0.01;
sprintf(RS232_Out_Buffer, " kp=%4.2f\r\n", kp);
WriteString(UART3, RS232_Out_Buffer);
}

// Clear the RX interrupt Flag
INTClearFlag(INT_SOURCE_UART_RX(UART3));
}

// We don't care about TX interrupt
if(INTGetFlag(INT_SOURCE_UART_TX(UART3))) {
INTClearFlag(INT_SOURCE_UART_TX(UART3));
}
}
return 0;
}
}
</pre>
</pre>


== MATLAB ==
Now, for fun, let's make a couple of small changes to the code.
'''**To Do**'''


== More Information ==
== More Information ==


More detailed information on how the the serial module on the PIC32 can be configured is on this page.'''**To Do**'''
More information on the I/O ports can be found in Chapter 12 of the Data Sheet and Chapter 12 of the Reference Manual. Some special function registers (SFRs) are listed in Chapter 4 of the Data Sheet. The SET, CLR, and INV registers are described in Section 2 of the Reference Manual.

Latest revision as of 06:27, 16 January 2016

THIS PAGE REFERS TO A PRE-RELEASE VERSION OF THE NU32 PIC32 DEVELOPMENT BOARD. FOR INFORMATION, SAMPLE CODE, AND VIDEOS RELATED TO THE PRODUCTION VERSION (2016 AND LATER), AND TO THE CORRESPONDING BOOK "EMBEDDED COMPUTING AND MECHATRONICS WITH THE PIC32 MICROCONTROLLER," VISIT THE NU32 PAGE.


The NU32v2 has the ability to talk directly with a computer over a virtual serial port connection. This ability can be used to debug code, transfer data, and interact with the microcontroller using a computer.

Overview

The NU32v2 uses an on board FT233RL chip from FTDI to convert RS-232 TTL serial communication to USB. Using drivers from FTDI, the communication can be opened by any program that can access a serial port. On the NU32v2 side, sample code has been created to enable the UART module on the PIC32. Using this code you can write strings to the computer, and generate an interrupt when characters are received. On the computer side, several programs that can access the serial connection are discussed, including PuTTY, Processing and MATLAB.

Details

The FT232RL chip is hardwired to the UART3 module on the PIC32M795F512L. The Receive (RX) pin, G7, and Transmit (TX) pin, G8, are also brought out to the sides of the NU32v2 board. They should not be used as general IO.

The NU32v2 Serial Bootloader uses the UART3 module at 115200 baud, as does the code below, but this can be changed as desired.

Library Functions

This code contains functions to read characters and write strings over the serial port.

NU32v2.h contains function prototypes, in addition to the serial functions, to initialize the LEDs on the NU32v2 board as well as the bootloader button.

NU32v2.c contains the functions. You do not need to change this file or the .h file need to use serial communication.

The functions that control the serial communication are:

  • void initSerialNU32v2(void) - enables UART3 at 115200 baud with an interrupt at priority level 2
  • void WriteString(UART_MODULE, const char *) - call with UART3 and the character array you wish to send
  • void PutCharacter(UART_MODULE, const char) - writes an individual character to the computer when the module is able to, called by WriteString()

NU32v2_serial_example.c contains example code that shows how to use the functions. It also contains the ISR for UART3, with an example of how to receive characters.

Sample Code

To initialize the serial communication, call initSerialNU32v2():

  initSerialNU32v2();

To write a string to the computer, use WriteString(UART3, charArray)

  WriteString(UART3, "\r\nHello World!\r\n");

To write a string with the value of a variable in it, use sprintf(RS232_Out_Buffer,charArray) and WriteString(UART3, charArray). RS232_Out_Buffer is declared in NU32v2.h as a char with 32 elements.

  sprintf(RS232_Out_Buffer, "the value of i is: %d\r\n", i);
  WriteString(UART3, RS232_Out_Buffer);

To receive characters in an interrupt, use this ISR

void __ISR(_UART_3_VECTOR, ipl2) IntUart3Handler(void) {
  // Is this an RX interrupt?
  if(INTGetFlag(INT_SOURCE_UART_RX(UART3))){
    char data = UARTGetDataByte(UART3);

    // now do something with data

    // Clear the RX interrupt Flag
    INTClearFlag(INT_SOURCE_UART_RX(UART3)); 
  }

  // We don't care about TX interrupt
  if(INTGetFlag(INT_SOURCE_UART_TX(UART3))) {
    INTClearFlag(INT_SOURCE_UART_TX(UART3));
  }
}

PuTTY

PuTTY is a terminal program that will let you open the virtual serial port created by the FTDI driver.

Directions to install PuTTY can be found in NU32v2: Software to Install#PuTTY Terminal Emulator

Before launching PuTTY, note the name of your COM port, same name as you use in the Serial Bootloader Application.


Launch Putty.exe. Set up your communication by:

  • Selecting the 'Serial' radio button

Select the 'Serial' branch in the tree on the bottom left.

  • Enter the name of your COM port in 'Serial line to connect to'
  • Enter 115200 in 'Speed (baud)'
  • Change 'Flow control' from 'XON/XOFF' to 'None'

Go back to the 'Session' screen by selecting the 'Session' in the top left of the tree.

  • Name your settings in 'Saved Sessions' and click 'Save'
  • Click the 'Open' button

Processing

**To Do - Processing basics, see Processing**

The NU32v2 Stripchart plotting tool can be used to plot 1000 data points in each of six traces, with values between 0 and 511, where each new data point is added to the right side of the plot, stripchart style. For example,

    for (i=0; i<1000; i++) {
      // plot on trace a the refValue and on trace b the ADC value
      sprintf(RS232_Out_Buffer, "%d %d\r\n", refValue[i]/2, adcValue[i]/2); // max adc is 1023, max plotted value is 511, 
                                                                  // so divide by 2 before sending
      WriteString(UART3, RS232_Out_Buffer);
    }

The NU32v2 Plotting tool can be used to plot 1000 data points in each of four traces, with values between 0 and 511.

To plot the values of an array of 1000 integers to trace a, use something like:

    for (i=0; i<1000; i++) {
      sprintf(RS232_Out_Buffer, "a %d %d\r\n", i, adcValue[i]/2); // max adc is 1023, max plotted value is 511, 
                                                                  // so divide by 2 before sending
      WriteString(UART3, RS232_Out_Buffer);
    }

Typing a key while the tool is running will send that character to the microcontroller. To write a message to the tool from the microcontroller, send a string that does not start with a, b, c or d.

For example, to change the value of a control gain when the microcontroller receives an 'a' and return the new value of the control gain, try:

void __ISR(_UART_3_VECTOR, ipl2) IntUart3Handler(void) {
  // Is this an RX interrupt?
  if(INTGetFlag(INT_SOURCE_UART_RX(UART3))){
    char data = UARTGetDataByte(UART3);

    // now do something with data
    if (data == 'a') { // increase kp
      kp=kp+0.01;
      sprintf(RS232_Out_Buffer, " kp=%4.2f\r\n", kp);
      WriteString(UART3, RS232_Out_Buffer);
    }

    // Clear the RX interrupt Flag
    INTClearFlag(INT_SOURCE_UART_RX(UART3)); 
  }

  // We don't care about TX interrupt
  if(INTGetFlag(INT_SOURCE_UART_TX(UART3))) {
    INTClearFlag(INT_SOURCE_UART_TX(UART3));
  }
}

MATLAB

**To Do**

More Information

More detailed information on how the the serial module on the PIC32 can be configured is on this page.**To Do**