Difference between revisions of "Introduction to the PIC32"
(127 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
[[Image:nu32_complete.jpg|thumb|500px|The NU32 board that breaks out the PIC32MX460F512L.|right]] |
[[Image:nu32_complete.jpg|thumb|500px|The NU32 board that breaks out the PIC32MX460F512L.|right]] |
||
The [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2591 Microchip PIC32] is a family of complex and powerful microcontrollers that can be purchased for less than $10 in quantities of one. This microcontroller offers many peripherals useful for mechatronics purposes, such as several channels for analog-to-digital conversion, digital I/O, synchronous and asynchronous serial communication, pulse width modulation, etc. For our purposes, the primary advantages of the 32-bit PICs over the 8-bit PICs we have used (and will continue to use) are that they are faster (max clock rate of 80 MHz compared to 40 MHz), offer more program memory ( |
The [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2591 Microchip PIC32] is a family of complex and powerful microcontrollers that can be purchased for less than $10 in quantities of one. This microcontroller offers many peripherals useful for mechatronics purposes, such as several channels for analog-to-digital conversion, digital I/O, synchronous and asynchronous serial communication, pulse width modulation, etc. For our purposes, the primary advantages of the 32-bit PICs over the 8-bit PICs we have used (and will continue to use) are that they are faster (max clock rate of 80 MHz compared to 40 MHz), have more peripherals available, offer more program memory (flash) and data memory (RAM), and have significantly more computational horsepower due to the 32-bit address and data buses and single-cycle multiply for 32-bit math. The primary disadvantages are that they come only in surface mount packages, making them harder to work with for fast prototyping compared to the DIP (dual-inline packages) 8-bit PICs that can be plugged into a breadboard; and they must be powered by 2.3-3.6 V, unlike the 5 V of DIP 8-bit PICs and some DIP chips we would like to interface with. (Of course surface mount and lower operating voltages are vastly superior for commercial embedded products, and we will find ways to work around the disadvantages mentioned.) |
||
Particular numbers referenced on this page refer to the [http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en534177 PIC32MX460F512L] chip, which is the PIC32 used on the NU32 board. The NU32 development board is shown at right. The NU32 board was designed by Andy Long to easily plug into a standard prototyping breadboard (DIP profile), allowing easy prototyping with the PIC32. The NU32 board also has a voltage regulator, a USB connector, and a few LEDs and switches to allow you to get up and running quickly with only the assembled NU32 board, a USB cable, and a PC with free software downloaded from Microchip. See the [[Getting Started with PIC32 | getting started page]]. The NU32 board was created with inspiration from the [http://www.sparkfun.com/commerce/product_info.php?products_id=8971 UBW32 board]. We wanted a board that was a little bit smaller, so we sacrificed some pins we thought unnecessary for the majority of mechatronics projects. We also wanted a board that gave students some experience soldering non-surface-mount components. |
Particular numbers referenced on this page refer to the [http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en534177 PIC32MX460F512L] chip, which is the PIC32 used on the NU32 board. (You may wish to compare the capabilities of our PIC to others on [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2870 the Microchip PIC32 parametric table].) The NU32 development board is shown at right. The NU32 board was designed by Andy Long to easily plug into a standard prototyping breadboard (DIP profile), allowing easy prototyping with the PIC32. The NU32 board also has a voltage regulator, a USB connector, and a few LEDs and switches to allow you to get up and running quickly with only the assembled NU32 board, a USB cable, and a PC with free software downloaded from Microchip (once a "bootloader" is installed on the PIC to allow you to program it from your PC). See the [[Getting Started with PIC32 | getting started page]]. The NU32 board was created with inspiration from the [http://www.sparkfun.com/commerce/product_info.php?products_id=8971 UBW32 board]. We wanted a board that was a little bit smaller, so we sacrificed some pins we thought unnecessary for the majority of mechatronics projects. We also wanted a board that gave students some experience soldering non-surface-mount components. |
||
The purpose of this page is to provide a brief overview of PIC32 and NU32 hardware and programming for the beginner. Microchip provides many reference manuals, data sheets, application notes, and sample software, and there are many other helpful web resources to take you further. |
The purpose of this page is to provide a brief overview of PIC32 and NU32 hardware and programming for the beginner. Microchip provides many reference manuals, data sheets, application notes, and sample software, and there are many other helpful web resources to take you further. |
||
= PIC32 |
= PIC32 Hardware Overview = |
||
[[Image:PIC32MX4XX-pinout.png|thumb| |
[[Image:PIC32MX4XX-pinout.png|thumb|200px|Pinout of the PIC32MX4XX.|right]] |
||
Our PIC32MX460F512L features a max clock frequency of 80 MHz, 512K program memory (flash), 32K data memory (RAM), multiple interrupt sources and handling routines, 16 analog-to-digital input channels, many digital I/O channels (with outputs that can be configured for open-drain), USB 2.0, two I2C and two SPI synchronous serial communication modules, two UARTs for RS-232 or RS-485 asynchronous serial communication, five 16-bit counter/timers (configurable to give two 32-bit timers), five pulse-width modulation outputs, and a number of pins that can generate interrupts based on external signals, among other features. This PIC has 100 pins, many (but not all) of which are used or broken out by the NU32 board. |
Our PIC32MX460F512L features a max clock frequency of 80 MHz, 512K program memory (flash), 32K data memory (RAM), multiple interrupt sources and handling routines, 16 10-bit analog-to-digital input channels, many digital I/O channels (with outputs that can be configured for open-drain), USB 2.0, two I2C and two SPI synchronous serial communication modules, two UARTs for RS-232 or RS-485 asynchronous serial communication, five 16-bit counter/timers (configurable to give two 32-bit timers), five pulse-width modulation outputs, and a number of pins that can generate interrupts based on external signals, among other features. This PIC has 100 pins, many (but not all) of which are used or broken out by the NU32 board. |
||
To cram this much functionality into 100 pins, many of the pins serve multiple functions. For example, pin 20 can serve as a comparator input, an analog input, a change notification input which can generate an interrupt when the pin changes state, or a digital input or output. Which function a particular pin serves is determined by "Special Function Registers" (SFRs) that contain configuration bits specifying the desired use of the pin. Typically your program sets these configuration bits at the beginning of execution, and the functions of the pins are fixed while your program runs. (It is possible, though rarely needed, to change the configuration bits and change the function of pins |
To cram this much functionality into 100 pins, many of the pins serve multiple functions. For example, pin 20 can serve as a comparator input, an analog input, a change notification input which can generate an interrupt when the pin changes state, or a digital input or output. Which function a particular pin serves is determined by "Special Function Registers" (SFRs) that contain configuration bits specifying the desired use of the pin. Typically your program sets these configuration bits at the beginning of execution, and the functions of the pins are fixed while your program runs. (It is possible, though rarely needed, to change the configuration bits and change the function of pins on the fly.) |
||
A figure showing the pin-out of the PIC32MX4XX is shown at right. Shaded pins tolerate up to 5.5 V as inputs, and pins that are "checked" are brought out to the pins of the NU32 board, described below. Click on the image for higher resolution. |
|||
<br clear=all> |
|||
Below the different pin functions are briefly summarized. The most important functions for ME 333 are indicated in '''bold'''. To learn more about these functions, you can consult the data sheet, but for the most part you will learn how to use these functions by modifying sample programs. See also the Further Reading section at the bottom of the page. |
|||
{| border="1" |
{| border="1" |
||
Line 17: | Line 23: | ||
!! style="background:#efefef;" | Function |
!! style="background:#efefef;" | Function |
||
|- |
|- |
||
| ANx (x=0-15) || analog-to-digital (ADC) inputs |
| '''ANx (x=0-15)''' || analog-to-digital (ADC) inputs |
||
|- |
|- |
||
| AVDD, AVSS || positive supply and ground reference for ADC |
| AVDD, AVSS || positive supply and ground reference for ADC |
||
Line 23: | Line 29: | ||
| BCLK1, BLCK2 || clocks for infrared (IrDA) comm encoding and decoding for 2 UARTs |
| BCLK1, BLCK2 || clocks for infrared (IrDA) comm encoding and decoding for 2 UARTs |
||
|- |
|- |
||
| CxIN-, CxIN+, CxOUT (x=1,2) || |
| CxIN-, CxIN+, CxOUT (x=1,2) || comparator negative and positive input and output |
||
|- |
|- |
||
| CLKI, CLKO || |
| CLKI, CLKO || clock input and output (for particular clock modes) |
||
|- |
|- |
||
| CNx (x=0-21) || |
| CNx (x=0-21) || interrupts generated on change of these inputs |
||
|- |
|- |
||
| CVREF-, CVREF+, CVREFOUT || |
| CVREF-, CVREF+, CVREFOUT || comparator reference voltage low and high inputs, output |
||
|- |
|- |
||
| D+, D- || |
| D+, D- || USB communication lines |
||
|- |
|- |
||
| EMUCx, EMUDx (x=1,2) || |
| EMUCx, EMUDx (x=1,2) || used by an in-circuit emulator (ICE); not relevant in ME 333 |
||
|- |
|- |
||
| ENVREG || enable for on-chip voltage regulator that provides 1.8 V to internal core (set to VDD to enable on NU32) |
|||
| ENVREG || |
|||
|- |
|- |
||
| ICx (x=1-5) || |
| ICx (x=1-5) || input capture pins for measuring frequencies and pulse widths |
||
|- |
|- |
||
| INTx (x=0-4) || |
| '''INTx (x=0-4)''' || pins used to generate external interrupts |
||
|- |
|- |
||
| MCLR (overbar) || |
| MCLR (overbar) || master clear reset pin, resets PIC when low |
||
|- |
|- |
||
| '''OCx (x=1-5)''' || "output compare" pins, usually used to generate pulse trains (pulse width modulation) or individual pulses |
|||
| OCx (x=1-5) || |
|||
|- |
|- |
||
| OCFA, OCFB || fault protection for output compare pins; if a fault occurs, can be used to make OC outputs be high impedance (neither high nor low) |
|||
| OCFA, OCFB || |
|||
|- |
|- |
||
| OSC1, OSC2 || |
| OSC1, OSC2 || crystal or resonator connections for different clock modes |
||
|- |
|- |
||
| PGCx, PGDx (x=1,2) || |
| PGCx, PGDx (x=1,2) || used with in-circuit debugger (ICD) |
||
|- |
|- |
||
| PMALL, PMALH || |
| PMALL, PMALH || latch enable for parallel master port (not used on NU32) |
||
|- |
|- |
||
| PMAx (x=0-15) || |
| PMAx (x=0-15) || parallel master port address (not used on NU32) |
||
|- |
|- |
||
| PMDx (x=0-15) || |
| PMDx (x=0-15) || parallel master port data (not used on NU32) |
||
|- |
|- |
||
| PMENB, PMRD, PMWR || |
| PMENB, PMRD, PMWR || enable and read/write strobes for parallel master port (not used on NU32) |
||
|- |
|- |
||
| Rxy (x=A-G,y=0-15) || |
| '''Rxy (x=A-G,y=0-15)''' || digital I/O pins |
||
|- |
|- |
||
| RTCC || real-time clock alarm output |
|||
| SCKx, SCLx, SDAx (x=1,2) || |
|||
|- |
|- |
||
| '''SCLx, SDAx (x=1,2)''' || I2C serial clock and data input/output for I2C synchronous serial communication modules 1 and 2 |
|||
| SDIx, SDOx (x=1,2) || |
|||
|- |
|- |
||
| '''SCKx, SDIx, SDOx (x=1,2)''' || serial clock, serial data in, out for SPI synchronous serial communication modules 1 and 2 |
|||
| SS1, SS2 (overbar) || |
|||
|- |
|- |
||
| '''SS1, SS2 (overbar)''' || slave select (active low) for SPI communication |
|||
| TxCK (x=1-5) || |
|||
|- |
|- |
||
| '''TxCK (x=1-5)''' || input pins for counters when counting external pulses |
|||
| TCK, TDI, TDO, TMS || |
|||
|- |
|- |
||
| TCK, TDI, TDO, TMS || used for JTAG debugging (not used on NU32) |
|||
| TRCLK || |
|||
|- |
|- |
||
| TRDx (x=0-3) || |
| TRCLK, TRDx (x=0-3) || used for instruction trace controller (not used on NU32) |
||
|- |
|- |
||
| UxCTS, UxRTS, UxRX, UxTX (x=1,2) || |
| '''UxCTS, UxRTS, UxRX, UxTX (x=1,2)''' || UART clear to send, request to send, receive input, and transmit output for 2 UART modules |
||
|- |
|- |
||
| '''VDD''' || positive voltage supply for peripheral digital logic and I/O pins (3.3 V on NU32) |
|||
| VDD || |
|||
|- |
|- |
||
| VDDCAP || capacitor filter for internal 1.8 V regulator when ENVREG enabled |
|||
| VDDCAP || |
|||
|- |
|- |
||
| VDDCORE || |
| VDDCORE || external 1.8 V supply when ENVREG disabled |
||
|- |
|- |
||
| VREF-, VREF+ || can be used as negative and positive limit for ADC, set to 0 and 3.3 V on NU32 |
|||
| VREF-, VREF+ || |
|||
|- |
|- |
||
| VSS || |
| '''VSS''' || ground for logic and I/O |
||
|- |
|- |
||
| VBUS || |
| VBUS || monitors USB bus power |
||
|- |
|- |
||
| VUSB || |
| VUSB || power for USB transceiver |
||
|- |
|- |
||
| VBUSON || |
| VBUSON || output to control supply for VBUS |
||
|- |
|- |
||
| USBID || |
| USBID || USB on-the-go (OTG) detect |
||
|- |
|- |
||
|} |
|} |
||
Line 101: | Line 107: | ||
[[Image:PIC32MX4XX-blockdiagram.png|thumb|400px|Block diagram of the PIC32MX4XX.|right]] |
[[Image:PIC32MX4XX-blockdiagram.png|thumb|400px|Block diagram of the PIC32MX4XX.|right]] |
||
The figure at right is a block diagram of the architecture of the PIC32. The CPU interfaces with data memory (RAM) and the program flash memory (along with USB, a direct memory access controller, and |
The figure at right is a block diagram of the architecture of the PIC32. The CPU (which operates at 1.8V, provided by a voltage regulator internal to the PIC32 as it's used on the NU32 board) interfaces with data memory (RAM) and the program flash memory (along with USB, a direct memory access controller, and in-circuit debugger and JTAG interfaces that can be used for programming and debugging purposes). It also interfaces with ''peripherals'', which are what make microcontrollers useful for embedded control. These peripherals consist of PORTA ... PORTG, which are digital I/O ports; five 16-bit counters (can create 32-bit counters by chaining) that can be used for a variety of counting operations, and timing operations by counting clock ticks; analog-to-digital converter (ADC) multiplexed to 16 input pins; a real-time clock and calendar (RTCC) that can maintain accurate year-month-day-time; two comparators that compare which of two inputs has a higher voltage; UARTs for asynchronous serial communication (e.g., RS-232, RS-485); a "parallel master port" (PMP) for parallel communication; two I2C and two SPI synchronous serial communication modules; five pins for "input capture", where interrupts can be triggered by rising or falling edges; five pins for pulse-width modulation (or "output compare"); and 22 change notification pins to generate interrupts when signals change. |
||
Note that the peripherals are on two different buses: one is a bus clocked by the system clock SYSCLK, and the other is clocked by the peripheral bus clock PBCLK. These may be the same frequency, or PBCLK may be a lower frequency, depending on how you set clock configuration bits. The top of the figure shows the timing generation, which uses either an external crystal or timing circuit (for more accurate timing), or an internal circuit, to create SYSCLK, PBCLK, and 48 MHz USBCLK (which is used for USB communication). The NU32 board uses an external 8 MHz crystal oscillator to generate a SYSCLK and PBCLK of 80 MHz using a phase-locked loop (PLL) to multiply the frequency. This is set by the software, as discussed below, not by the physical design of the board. If the Watchdog Timer is used by your program, your program must periodically reset the timer counter. Otherwise the PIC will reset. This is a way to have the PIC recover and restart if your program has entered an unexpected state. |
|||
The CPU also interfaces with a "pre-fetch (cache) module." This module fetches blocks of program instructions from flash program memory in advance of their use by the CPU, to try to limit delays due to relatively slow flash memory. |
|||
<br clear=all> |
<br clear=all> |
||
= NU32 Development Board Overview = |
|||
[[Image:NU32BoardLayout.png|thumb|200px|Layout of the NU32 development board.|right]] |
|||
Here is a [[Media:NU32BoardSchematic.pdf|schematic]] of the NU32 development board, showing how the PIC32MX460F512L is used on the board, and showing which pins are made available to the user. The board layout is shown at right as and can be clicked on to view a high resolution image. It is also available as a [[Media:NU32BoardLayout.pdf|pdf file]]. This [[Media:NU32Pins.xls|excel spreadsheet]] details which of the PIC32 pins are used on the board, which are connected to pins available to the user, and which are not used. The mapping from the 58 pins on the NU32 board to pins on the PIC32 is also shown in the figure below. In total, 52 PIC pins are carried to the NU32 board pins. |
|||
The 27 PIC32 pins that are used on the board and not carried out to the board edge are 3, used for the USER switch; 30 and 31, the positive and negative references for the ADC (set to 3.3V and ground on the board); 51, 54, 55, 56, and 57, used for USB communication; 63 and 64, used for the oscillator; 85 and 86, related to the use of the PIC32's internal 1.8V regulator for the core; 93, 94, 98, and 99, which are used as digital outputs for the four LEDs on the board; and 100, used for the PRG switch. Also, VDD pins 2, 16, 37, 46, and 62 are connected to +3.3V on the board, and VSS pins 15, 36, 45, 65, and 75 are connected to ground. |
|||
The 21 PIC32 pins that are not connected at all are 1 (dig I/O); 4 and 5 (parallel port and dig I/O); 17, 38, 60, and 61 (JTAG debugging and dig I/O); 79, 80, 82, 83, 84, 87, 88, 89, and 90 (primarily parallel port); and 91, 92, 95, 96, and 97 (trace debugging). |
|||
Options for powering the NU32 board: |
|||
* Plug a USB cable in and slide the power switch to USB power (toward the outside of the board). The USB cable provides 5V power, with a typical current supply of around 500 mA. |
|||
* Plug a power jack (2.5 mm ID, 5.5 mm OD, center positive) into the barrel connector on the board and slide the power switch to side labeled 'EXT' (toward the inside of the board). There are two options for this power jack. |
|||
** Any regulated or unregulated voltage 5V or greater. In this case, you must solder a 5V voltage regulator into the pins lableled LM2940. One possibility that will fit in the designated space is the LM2940 in the TO-220 package. This is a low-dropout regulator that can source up to 1 A. (In this case, "low dropout" means that your input voltage only has to be at least 0.5 or 1V above 5V; some cheaper regulators require that the input voltage be 2V above 5V.) The back of the LM2940 should be to the outside of the board. |
|||
** 5V regulated power. In this case, you do not need a regulator, but you must solder a jumper between the first and third pins of the voltage regulator pins labeled LM2940. |
|||
* If you do not have a connector that plugs into the barrel connector, you can solder wires into the holes labeled V+ and GND on the outer edge of the board, right after pin 58. Connect these wires to your power supply. These wires now replace the jack connector in the bullet above. See the rest of the description there. |
|||
'''NOT RECOMMENDED:''' If none of the power connections above are available, it is possible to power the board by providing 5V at pins 1 or 58 of the NU32 board. These pins are are connected to the USB 5V when the power switch is in the USB position, and they are connected to the output of the 5V regulator when the power switch is in the EXT position. This method should be avoided, to prevent accidental wiring that could damage the PIC. |
|||
'''Note on using the 3.3V and 5V output pins:''' If the NU32 is powered by a USB cable, typically such a connection can only provide about 500 mA total. Take this into account when you decide how much current to try to draw from these pins. Even if the NU32 board is powered by a higher-current supply, such as a battery or a wall-powered adapter brick, keep in mind that the onboard 3.3V regulator can only source approximately 950 mA max. You should not try to draw more than, say, half that. Also, if your supply is unregulated and you are using a 5V regulator on the NU32 board, you must take into account your board's regulator's current limit. Usual rule of thumb: don't try to drive motors, which often draw hundreds of mA, up to a few amps in typical ME 333 applications, using current flowing through your NU32 board. |
|||
<br clear=all> |
|||
[[Image:NU32Pinout.png]] |
|||
now the board |
|||
<br clear=all> |
<br clear=all> |
||
= PIC32 Programming in C = |
= PIC32 Programming in C = |
||
'''Note: Code downloaded from Microchip is constantly evolving, and it is possible that the information below will be outdated for future code releases. This information is accurate for code downloaded from Microchip's website in December 2009. This version of the Microchip code is also archived on the mechatronics wiki. Also, sample code developed by us and others are generally modified from working code for different purposes, and therefore you may find unnecessary legacy code, programming inefficiency, or even incorrect code in some samples.''' |
|||
You should complete the exercise [[Getting Started with PIC32]] if you have not already. In that exercise, you |
|||
* download and install the MPLAB IDE (Integrated Development Environment) that you use for programming, compiling, debugging, and simulating your PIC code |
|||
* download and install the MPLAB C Compiler for PIC32 |
|||
* download the Microchip Applications Library |
|||
* install a "bootloader" on your PIC32 |
|||
* create a "Hello World" program for the NU32 that you compile to a .hex file, download to your PIC32, and run. |
|||
The bootloader is programmed to the PIC's flash memory using a programmer (such as Microchip's ICD). Once the bootloader is there, you should never have to use a programmer again (unless you accidentally overwrite the bootloader in flash memory by using the wrong procdefs.ld "linker" file). From that point on, you should be able to program your PIC simply using a USB cable to connect your PC to the NU32 board. |
|||
After you've installed all the software on your PC, you should have the following directories: |
|||
* C:\Microchip Solutions: This has a lot of demo code, among other things. The C:\Microchip Solutions\Microchip\Include directory contains .h files that you are likely to need for your programs. Also, C:\Microchip Solutions\USB Device - Bootloaders\HID - Bootloader has .hex bootloaders for different PICs. '''(Note: these .hex bootloaders don't work with the NU32 board, which is why we compiled our own bootloader.)''' It also has PC source software for USB communication with a PIC with the bootloader installed (for programming the PIC without a programmer device). |
|||
* C:\Program Files\Microchip: There is a '''lot''' of stuff under this directory. Two notable directories are MPLAB C32 and MPLAB C32 Suite. These directories look essentially exactly the same, unless I'm missing something. One directory of interest is C:\Program Files\Microchip\MPLAB C32\pic32_libs\include, which has plib.h (function definitions for the peripheral libraries) and subdirectories peripheral (with .h files for peripheral libraries) and proc (with .h files for different PICs containing type definitions and memory addresses specific to the PICs). Another directory of interest is C:\Program Files\Microchip\MPLAB C32\pic32_libs\peripheral, which has directories for each of the peripherals and .c, .inc, and .h source files for the libraries for these peripherals. |
|||
In addition, you have the HID Bootloader program in your PC's start menu. |
|||
When you created your first Hello World project, you went through the following steps: |
|||
# Created a new directory to hold the project, and put the files "HardwareProfile.h" and "HardwareProfile_NU32.h" "header" files into the directory. |
|||
# Used the Project Wizard to create a new project in that directory and specified that you would be using the PIC32MX460F512L microcontroller. |
|||
# Added the HardwareProfile.h and HardwareProfile_NU32.h to your project. (This allows your project to know it has to recompile if these files are changed.) |
|||
# Added procdefs.ld (a "linker" file) to your project. This file is '''different''' from the procdefs.ld file used for your bootloader. These files tell MPLAB where the code should be placed in program memory, and the two procdefs.ld are different so your Hello World program does not overwrite the bootloader code. (This is not the only linker file used, so we put it under "Other Files.") |
|||
# Added two search paths to "Include Search Path," (1) C:\Microchip Solutions\Microchip\Include and (2) the directory of your project, where you are creating your source code. |
|||
# Created a constant "PIC32_NU32" in the MPLAB PIC32 C Compiler tab. |
|||
# Wrote the main.c code for Hello World, added it to the project, and used Project->Build all to create a .hex file that you then loaded on to the PIC32 using the HID bootloader. |
|||
So what was the purpose of each of these steps? '''Steps 2 and 6''' defined constants that tell the compiler the microcontroller you are using and the board it is being used on. How are these constants used? Open up HardwareProfile.h, which you included in your project ('''step 3'''). Because you have defined __32MX460F512L__ ('''step 2'''), and because you have defined PIC32_NU32 ('''step 6'''), this file includes "HardwareProfile_NU32.h". Now take a look at the file HardwareProfile_NU32.h. The first thing it does is include "Compiler.h". We can find Compiler.h in C:\Microchip Solutions\Microchip\Include, which we included in our "Include Search Path" ('''step 5''') so the compiler would know where to find it. Let's come back to Compiler.h shortly. |
|||
OK, continuing through HardwareProfile_NU32.h, we see that our PIC will have a system frequency of 80 MHz. '''Note that this does not actually set what the PIC does with the oscillator we have provided.''' |
|||
Continuing with HardwareProfile_NU32.h, we see that a function "mInitAllLEDs()" is defined. It does two things: it sets the latch bits (LATE) and the "tri-state" bits (TRISE) of port E. LATE and TRISE are the values of Special Function Registers (SFRs) for the digital I/O peripherals and are defined elsewhere, as we will see soon. (See also [[PIC32MX: Digital Inputs]] and [[PIC32MX: Digital Outputs]] for more on using the digital I/O peripherals.) The command "LATE |= 0x000F" bitwise logically "ORs" the current bits of LATE with the bits of the hexadecimal value 0x000F. (This is equivalent to the command "LATE = LATE | 0x000F", and C programmers will notice that this syntax is similar to the syntax a += 3, which is equivalent to a = a + 3.) Note that 0x000F corresponds to a binary value of 0000 0000 0000 1111. So whatever the current values of LATE are, the last four bits (least significant bits) will be 1 after this operation. (Note that 0x000F has only 16 bits, but LATE is technically 32-bit. The first 16-bits are not used, however; see Section 12 of the [[Media:61132B_PIC32ReferenceManual.pdf|PIC32 Reference Manual]]). The command "TRISE &= 0xFFF0" sets whether the pins in port E will be inputs or outputs by doing a bitwise AND with 1111 1111 1111 0000. In other words, the first 12 bits will be unchanged, while the last four bits will be set to outputs (0 = output, 1 = input). These last four bits are going to be used to power our NU32 board LEDs, so they must be outputs. We then see the mnemonic names "mLED_x" given to the (output) values of these four bits. A number of functions are then defined to get the current values of the LEDs and to turn the LEDs on, turn them off, or toggle them. (Note that an output value of 0, or 0 voltage, corresponds to the LED being on; consult the NU32 schematic to see why this is the case.) Finally, functions are defined that will configure bits 4 and 5 of port E as inputs. These are used for the USER and PRG switches on the NU32 board. The constants swProgram and swUser return the current values of these inputs, 0 for low (ground), 1 for high (3.3V). |
|||
OK, now let's open Compiler.h from a few paragraphs earlier. We find that since we are using the C32 compiler, it includes the header files p32xxxx.h and plib.h. We will take a look at those shortly, but let's continue with Compiler.h. It also includes some standard C libraries, like stdio.h (libraries for input and output), stdlib.h, and string.h (for string manipulation). It makes a few more definitions which are beyond our scope for now. You might be interested to see the defined function "Nop()" which stands for "no operation," i.e., just waste a cycle. It is defined using an assembly code command using asm("nop"). In other words, if you were coding in assembly (and thank goodness you're not), you would type "nop." You can write low-level assembly code in C using the command asm(). If you are interested, you can always see the assembly code generated by your C code by using View->Disassembly Listing in the MPLAB IDE. |
|||
Let's go back and look at p32xxxx.h and plib.h, referenced by Compiler.h. They can be found under C:\Program Files\Microchip\MPLAB C32\pic32_libs\include. plib.h simply includes a bunch of .h files for the peripheral libraries: 10-bit ADC (adc10.h) which further makes use of definitions in ports.h; I2C serial communication (i2c.h); etc. All of these .h files are under C:\Program Files\Microchip\MPLAB C32\pic32_libs\include\peripheral. We can open one of these many .h files, and we'll see that they define functions that are designed to simplify our use of the peripheral. You can learn more about the use of these peripheral libraries in the [[Media:32-bit-Peripheral-Library-Guide.pdf|peripheral library guide]] (see also Further Reading at the end of this page). Also, you can see the source code for the peripherals to see how the higher-level peripheral functions are created from low-level functions by looking in C:\Program Files\Microchip\MPLAB C32\pic32_libs\peripheral. |
|||
If we now open p32xxxx.h, we find that it simply includes the file p32mx460f512l.h, which is under C:\Program Files\Microchip\MPLAB C32\pic32_libs\include\proc. If we open up this file... whoa! Finally we see where a lot of the data types and variables and constants are defined that have been used earlier. The details are well beyond our scope here, but we can look at the beginning of the file, where the variable WDTCON (WatchDog Timer CONfiguration) is defined as an unsigned integer (a 32-bit integer from 0 to 2^31-1). Also, the data type __WDTCONbits_t is defined, consisting of a set of structures, and then the variable WDTCONbits is defined of type __WDTCONbits_t. The rest of this very large file defines data types and variables for configuration bits, various constants, quantities associated with interrupts, addresses for peripherals specific to the particular PIC, etc. |
|||
OK, we've spent a lot of time tracing #include files to see where various things are defined, configuration bits set, etc. We could spend more time on this, but you get the idea. In the MPLAB IDE, you can click on Configure->Configuration Bits to set some of the Configuration Bits using the IDE, rather than in your source files. I think it is best to have it written in your source files so another programmer knows where to find them. So leave the checkbox "Configuration Bits set in code" checked. |
|||
One more thing that we have not yet mentioned: when you put the bootloader on your PIC, it configured some of the Special Function Registers (SFRs) of your PIC. In particular, open main.c of your bootloader project, and you will see a series of #pragma directives that get executed upon recognizing that you have defined the constant PIC32_NU32. (#pragma directives are compiler-specific instructions, in this case for PIC microcotnrollers, not general C language instructions.) Notice, for example, that FPLLMUL is set to MUL_20 ('''where is this defined?'''), meaning that the PLL (phase-locked loop) in the PIC multiplies the external crystal frequency by 20 (8 MHz x 20 = 160 MHz), and then FPLLIDIV (PLL input divider) divides the frequency by 2, and FPLLODIV (PLL output divider) divides by 1, giving our final system clock of 80 MHz. This is where the actual hardware is configured to give us our actual clock frequency. The peripheral clock is set to the same frequency. USB communication requires a precise 48 MHz clock, and the USB PLL multiplies its input frequency by 12. Therefore, we must provide the USB PLL with a 4 MHz signal, and therefore the bootloader sets UPLLIDIV (USB PLL Input Divider) to 2, to divide the 8 MHz clock by 2. Much of the rest of main.c is devoted to code that allows you to program the PIC by USB communication. |
|||
OK, going back to the main.c file you created for your Hello World project. After all the includes, a constant SYS_FREQ is defined to be 80 million. '''(NOTE: You could accidentally type 8 million or 800 million, and nothing would work properly! Make sure you type 80 million. Ideally, this SYS_FREQ would be derived from the definitions in the bootloader's main.c file, so you wouldn't have to type again.)''' Then SYSTEMConfigPerformance(SYS_FREQ) is called. This function is defined in C:\Program Files\Microchip\MPLAB C32\pic32_libs\include\peripheral, and one of its purposes is to define some timing constants to hopefully optimize the performance of your PIC (e.g., the use of the pre-fetch cache). Then the LED functions defined in HardwareProfile_NU32.h are used to initialize the LEDs and turn them on or off according to whether the USER button is pushed. |
|||
Finally, what happens when you "Build All" ('''step 7''')? The compiler compiles any of the individual source files that have been modified since the last Build into .o files, called object code. The linker then puts everything together using a default linker file as well as your procdefs.ld ('''step 4''') and assigns the code to specific addresses in program memory. |
|||
So, to summarize, this was the chain of #include files: |
|||
* The Hello World main.c program included HardwareProfile.h. |
|||
** HardwareProfile.h does little but include HardwareProfile_NU32.h and Compiler.h. |
|||
*** HardwareProfile_NU32.h defines initialization functions to set 4 pins of Port E as digital outputs and 2 as digital inputs; defines convenient names for these pins; and defines functions for turning the NU32 LEDs on and off. |
|||
*** Compiler.h provides a few definitions and includes some standard C libraries (stdio.h, stdlib.h, string.h) as well as p32xxxx.h and plib.h. |
|||
**** plib.h includes the peripheral libraries (e.g., adc10.h, i2c.h, etc.), which you can learn more about in [[Media:32-bit-Peripheral-Library-Guide.pdf|this peripheral library guide]] (314 page pdf). |
|||
**** p32xxxx.h includes p32mx460f512l.h. |
|||
***** p32mx460f512l.h is a big file and makes many of the microcontroller-specific definitions. This includes defining data types and variable names for the peripheral SFRs (e.g., LATE, PORTE, and TRISE, as mentioned above) and some convenient names for addresses and interrupt numbers and vectors. It also includes ppic32mx.h., which defines some other mnemonic variable names. |
|||
Finally, the bootloader main.c file defined some of the configuration bits for the clock circuitry, to set the SYSCLK and PBCLK to 80 MHz, and the USBCLK to 48 MHz, given that we have an 8 MHz crystal. |
|||
= Further Reading = |
= Further Reading = |
||
There are many references out there to learn more about the hardware and programming of the PIC32. Some of these are more accessible than others. A good book that discusses both the hardware and programming of the PIC32 at an introductory to intermediate level is DiJasio's [http://www.amazon.com/Programming-32-bit-Microcontrollers-Exploring-Technology/dp/0750687096 Programming 32-bit Microcontrollers in C: Exploring the PIC32] (see also a [http://www.scribd.com/doc/16601628/Programming-32bit-Microcontrollers-in-C pdf version] of the book available for download). It was published in 2008, soon after PIC32's were released. It does not make use of many peripheral library functions, but instead provides low-level code to develop your own libraries. Still, it is a good first book to understand how the PIC32 works. |
|||
links to microchip manuals, data sheets, books, external sources, etc. |
|||
I think these are the three most useful Microchip reference documents: |
|||
* [[Media:61132B_PIC32ReferenceManual.pdf|PIC32 Reference Manual]] (1138 pages, 11 MB pdf): Lots of useful and detailed information on the PIC32 architecture and how the peripherals work, including detailed description of their SFRs. |
|||
* [[Media:61143E_PIC32DataSheet.pdf|PIC32 Data Sheet]] (646 pages, 8 MB pdf): Has overlap with the Reference Manual, but the Reference Manual contains some information you can't find here, and the Data Sheet contains some information you can't find in the Reference Manual. |
|||
* [[Media:32-bit-Peripheral-Library-Guide.pdf|Peripheral Library Guide]] (314 page pdf): Manual describing the use of the peripheral library functions described in plib.h. |
|||
There is also a [[Media:61143F_PIC32ShortDataSheet.pdf|"short" PIC32 Data Sheet]] (172 pages, 3 MB pdf). You can also visit the [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2601 Microchip documentation page]. |
|||
To better understand how to program the PIC32, your best bet is to modify sample code in the Microchip distribution (see in particular the code in C:\Program Files\Microchip\MPLAB C32\examples), on this wiki, and elsewhere on the web. Andy Long created this [[Media:Introduction_to_Programming_the_PIC32.pdf|introductory presentation on programming the PIC32 digital I/O and ADC peripherals]] you might find useful. You might also wish to look at some of the many [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1469 Microchip Application Notes]. It is also useful to look at the .h files, particularly for the peripheral library, much like we did above. You can also look at the peripheral source code to see what exactly the peripheral libraries do in the cases that the functions are not completely described in the .h files. The [[Media:MPLAB_C32_User_Guide.pdf|MPLAB C32 C Compiler User's Guide]] (120 page pdf) contains information on programming the PIC32 in C, and the [[Media:MPLAB_C32_Libraries.pdf|MPLAB C32 Libraries Manual]] (150 page pdf) discusses some standard C libraries as well as libraries for functions such as Fast Fourier Transforms, FIR and IIR filters, and functions on arrays. |
|||
As you find other useful resources for programming, feel free to add them here! |
Latest revision as of 12:29, 23 March 2010
The Microchip PIC32 is a family of complex and powerful microcontrollers that can be purchased for less than $10 in quantities of one. This microcontroller offers many peripherals useful for mechatronics purposes, such as several channels for analog-to-digital conversion, digital I/O, synchronous and asynchronous serial communication, pulse width modulation, etc. For our purposes, the primary advantages of the 32-bit PICs over the 8-bit PICs we have used (and will continue to use) are that they are faster (max clock rate of 80 MHz compared to 40 MHz), have more peripherals available, offer more program memory (flash) and data memory (RAM), and have significantly more computational horsepower due to the 32-bit address and data buses and single-cycle multiply for 32-bit math. The primary disadvantages are that they come only in surface mount packages, making them harder to work with for fast prototyping compared to the DIP (dual-inline packages) 8-bit PICs that can be plugged into a breadboard; and they must be powered by 2.3-3.6 V, unlike the 5 V of DIP 8-bit PICs and some DIP chips we would like to interface with. (Of course surface mount and lower operating voltages are vastly superior for commercial embedded products, and we will find ways to work around the disadvantages mentioned.)
Particular numbers referenced on this page refer to the PIC32MX460F512L chip, which is the PIC32 used on the NU32 board. (You may wish to compare the capabilities of our PIC to others on the Microchip PIC32 parametric table.) The NU32 development board is shown at right. The NU32 board was designed by Andy Long to easily plug into a standard prototyping breadboard (DIP profile), allowing easy prototyping with the PIC32. The NU32 board also has a voltage regulator, a USB connector, and a few LEDs and switches to allow you to get up and running quickly with only the assembled NU32 board, a USB cable, and a PC with free software downloaded from Microchip (once a "bootloader" is installed on the PIC to allow you to program it from your PC). See the getting started page. The NU32 board was created with inspiration from the UBW32 board. We wanted a board that was a little bit smaller, so we sacrificed some pins we thought unnecessary for the majority of mechatronics projects. We also wanted a board that gave students some experience soldering non-surface-mount components.
The purpose of this page is to provide a brief overview of PIC32 and NU32 hardware and programming for the beginner. Microchip provides many reference manuals, data sheets, application notes, and sample software, and there are many other helpful web resources to take you further.
PIC32 Hardware Overview
Our PIC32MX460F512L features a max clock frequency of 80 MHz, 512K program memory (flash), 32K data memory (RAM), multiple interrupt sources and handling routines, 16 10-bit analog-to-digital input channels, many digital I/O channels (with outputs that can be configured for open-drain), USB 2.0, two I2C and two SPI synchronous serial communication modules, two UARTs for RS-232 or RS-485 asynchronous serial communication, five 16-bit counter/timers (configurable to give two 32-bit timers), five pulse-width modulation outputs, and a number of pins that can generate interrupts based on external signals, among other features. This PIC has 100 pins, many (but not all) of which are used or broken out by the NU32 board.
To cram this much functionality into 100 pins, many of the pins serve multiple functions. For example, pin 20 can serve as a comparator input, an analog input, a change notification input which can generate an interrupt when the pin changes state, or a digital input or output. Which function a particular pin serves is determined by "Special Function Registers" (SFRs) that contain configuration bits specifying the desired use of the pin. Typically your program sets these configuration bits at the beginning of execution, and the functions of the pins are fixed while your program runs. (It is possible, though rarely needed, to change the configuration bits and change the function of pins on the fly.)
A figure showing the pin-out of the PIC32MX4XX is shown at right. Shaded pins tolerate up to 5.5 V as inputs, and pins that are "checked" are brought out to the pins of the NU32 board, described below. Click on the image for higher resolution.
Below the different pin functions are briefly summarized. The most important functions for ME 333 are indicated in bold. To learn more about these functions, you can consult the data sheet, but for the most part you will learn how to use these functions by modifying sample programs. See also the Further Reading section at the bottom of the page.
Pin Label | Function |
---|---|
ANx (x=0-15) | analog-to-digital (ADC) inputs |
AVDD, AVSS | positive supply and ground reference for ADC |
BCLK1, BLCK2 | clocks for infrared (IrDA) comm encoding and decoding for 2 UARTs |
CxIN-, CxIN+, CxOUT (x=1,2) | comparator negative and positive input and output |
CLKI, CLKO | clock input and output (for particular clock modes) |
CNx (x=0-21) | interrupts generated on change of these inputs |
CVREF-, CVREF+, CVREFOUT | comparator reference voltage low and high inputs, output |
D+, D- | USB communication lines |
EMUCx, EMUDx (x=1,2) | used by an in-circuit emulator (ICE); not relevant in ME 333 |
ENVREG | enable for on-chip voltage regulator that provides 1.8 V to internal core (set to VDD to enable on NU32) |
ICx (x=1-5) | input capture pins for measuring frequencies and pulse widths |
INTx (x=0-4) | pins used to generate external interrupts |
MCLR (overbar) | master clear reset pin, resets PIC when low |
OCx (x=1-5) | "output compare" pins, usually used to generate pulse trains (pulse width modulation) or individual pulses |
OCFA, OCFB | fault protection for output compare pins; if a fault occurs, can be used to make OC outputs be high impedance (neither high nor low) |
OSC1, OSC2 | crystal or resonator connections for different clock modes |
PGCx, PGDx (x=1,2) | used with in-circuit debugger (ICD) |
PMALL, PMALH | latch enable for parallel master port (not used on NU32) |
PMAx (x=0-15) | parallel master port address (not used on NU32) |
PMDx (x=0-15) | parallel master port data (not used on NU32) |
PMENB, PMRD, PMWR | enable and read/write strobes for parallel master port (not used on NU32) |
Rxy (x=A-G,y=0-15) | digital I/O pins |
RTCC | real-time clock alarm output |
SCLx, SDAx (x=1,2) | I2C serial clock and data input/output for I2C synchronous serial communication modules 1 and 2 |
SCKx, SDIx, SDOx (x=1,2) | serial clock, serial data in, out for SPI synchronous serial communication modules 1 and 2 |
SS1, SS2 (overbar) | slave select (active low) for SPI communication |
TxCK (x=1-5) | input pins for counters when counting external pulses |
TCK, TDI, TDO, TMS | used for JTAG debugging (not used on NU32) |
TRCLK, TRDx (x=0-3) | used for instruction trace controller (not used on NU32) |
UxCTS, UxRTS, UxRX, UxTX (x=1,2) | UART clear to send, request to send, receive input, and transmit output for 2 UART modules |
VDD | positive voltage supply for peripheral digital logic and I/O pins (3.3 V on NU32) |
VDDCAP | capacitor filter for internal 1.8 V regulator when ENVREG enabled |
VDDCORE | external 1.8 V supply when ENVREG disabled |
VREF-, VREF+ | can be used as negative and positive limit for ADC, set to 0 and 3.3 V on NU32 |
VSS | ground for logic and I/O |
VBUS | monitors USB bus power |
VUSB | power for USB transceiver |
VBUSON | output to control supply for VBUS |
USBID | USB on-the-go (OTG) detect |
The figure at right is a block diagram of the architecture of the PIC32. The CPU (which operates at 1.8V, provided by a voltage regulator internal to the PIC32 as it's used on the NU32 board) interfaces with data memory (RAM) and the program flash memory (along with USB, a direct memory access controller, and in-circuit debugger and JTAG interfaces that can be used for programming and debugging purposes). It also interfaces with peripherals, which are what make microcontrollers useful for embedded control. These peripherals consist of PORTA ... PORTG, which are digital I/O ports; five 16-bit counters (can create 32-bit counters by chaining) that can be used for a variety of counting operations, and timing operations by counting clock ticks; analog-to-digital converter (ADC) multiplexed to 16 input pins; a real-time clock and calendar (RTCC) that can maintain accurate year-month-day-time; two comparators that compare which of two inputs has a higher voltage; UARTs for asynchronous serial communication (e.g., RS-232, RS-485); a "parallel master port" (PMP) for parallel communication; two I2C and two SPI synchronous serial communication modules; five pins for "input capture", where interrupts can be triggered by rising or falling edges; five pins for pulse-width modulation (or "output compare"); and 22 change notification pins to generate interrupts when signals change.
Note that the peripherals are on two different buses: one is a bus clocked by the system clock SYSCLK, and the other is clocked by the peripheral bus clock PBCLK. These may be the same frequency, or PBCLK may be a lower frequency, depending on how you set clock configuration bits. The top of the figure shows the timing generation, which uses either an external crystal or timing circuit (for more accurate timing), or an internal circuit, to create SYSCLK, PBCLK, and 48 MHz USBCLK (which is used for USB communication). The NU32 board uses an external 8 MHz crystal oscillator to generate a SYSCLK and PBCLK of 80 MHz using a phase-locked loop (PLL) to multiply the frequency. This is set by the software, as discussed below, not by the physical design of the board. If the Watchdog Timer is used by your program, your program must periodically reset the timer counter. Otherwise the PIC will reset. This is a way to have the PIC recover and restart if your program has entered an unexpected state.
The CPU also interfaces with a "pre-fetch (cache) module." This module fetches blocks of program instructions from flash program memory in advance of their use by the CPU, to try to limit delays due to relatively slow flash memory.
NU32 Development Board Overview
Here is a schematic of the NU32 development board, showing how the PIC32MX460F512L is used on the board, and showing which pins are made available to the user. The board layout is shown at right as and can be clicked on to view a high resolution image. It is also available as a pdf file. This excel spreadsheet details which of the PIC32 pins are used on the board, which are connected to pins available to the user, and which are not used. The mapping from the 58 pins on the NU32 board to pins on the PIC32 is also shown in the figure below. In total, 52 PIC pins are carried to the NU32 board pins.
The 27 PIC32 pins that are used on the board and not carried out to the board edge are 3, used for the USER switch; 30 and 31, the positive and negative references for the ADC (set to 3.3V and ground on the board); 51, 54, 55, 56, and 57, used for USB communication; 63 and 64, used for the oscillator; 85 and 86, related to the use of the PIC32's internal 1.8V regulator for the core; 93, 94, 98, and 99, which are used as digital outputs for the four LEDs on the board; and 100, used for the PRG switch. Also, VDD pins 2, 16, 37, 46, and 62 are connected to +3.3V on the board, and VSS pins 15, 36, 45, 65, and 75 are connected to ground.
The 21 PIC32 pins that are not connected at all are 1 (dig I/O); 4 and 5 (parallel port and dig I/O); 17, 38, 60, and 61 (JTAG debugging and dig I/O); 79, 80, 82, 83, 84, 87, 88, 89, and 90 (primarily parallel port); and 91, 92, 95, 96, and 97 (trace debugging).
Options for powering the NU32 board:
- Plug a USB cable in and slide the power switch to USB power (toward the outside of the board). The USB cable provides 5V power, with a typical current supply of around 500 mA.
- Plug a power jack (2.5 mm ID, 5.5 mm OD, center positive) into the barrel connector on the board and slide the power switch to side labeled 'EXT' (toward the inside of the board). There are two options for this power jack.
- Any regulated or unregulated voltage 5V or greater. In this case, you must solder a 5V voltage regulator into the pins lableled LM2940. One possibility that will fit in the designated space is the LM2940 in the TO-220 package. This is a low-dropout regulator that can source up to 1 A. (In this case, "low dropout" means that your input voltage only has to be at least 0.5 or 1V above 5V; some cheaper regulators require that the input voltage be 2V above 5V.) The back of the LM2940 should be to the outside of the board.
- 5V regulated power. In this case, you do not need a regulator, but you must solder a jumper between the first and third pins of the voltage regulator pins labeled LM2940.
- If you do not have a connector that plugs into the barrel connector, you can solder wires into the holes labeled V+ and GND on the outer edge of the board, right after pin 58. Connect these wires to your power supply. These wires now replace the jack connector in the bullet above. See the rest of the description there.
NOT RECOMMENDED: If none of the power connections above are available, it is possible to power the board by providing 5V at pins 1 or 58 of the NU32 board. These pins are are connected to the USB 5V when the power switch is in the USB position, and they are connected to the output of the 5V regulator when the power switch is in the EXT position. This method should be avoided, to prevent accidental wiring that could damage the PIC.
Note on using the 3.3V and 5V output pins: If the NU32 is powered by a USB cable, typically such a connection can only provide about 500 mA total. Take this into account when you decide how much current to try to draw from these pins. Even if the NU32 board is powered by a higher-current supply, such as a battery or a wall-powered adapter brick, keep in mind that the onboard 3.3V regulator can only source approximately 950 mA max. You should not try to draw more than, say, half that. Also, if your supply is unregulated and you are using a 5V regulator on the NU32 board, you must take into account your board's regulator's current limit. Usual rule of thumb: don't try to drive motors, which often draw hundreds of mA, up to a few amps in typical ME 333 applications, using current flowing through your NU32 board.
PIC32 Programming in C
Note: Code downloaded from Microchip is constantly evolving, and it is possible that the information below will be outdated for future code releases. This information is accurate for code downloaded from Microchip's website in December 2009. This version of the Microchip code is also archived on the mechatronics wiki. Also, sample code developed by us and others are generally modified from working code for different purposes, and therefore you may find unnecessary legacy code, programming inefficiency, or even incorrect code in some samples.
You should complete the exercise Getting Started with PIC32 if you have not already. In that exercise, you
- download and install the MPLAB IDE (Integrated Development Environment) that you use for programming, compiling, debugging, and simulating your PIC code
- download and install the MPLAB C Compiler for PIC32
- download the Microchip Applications Library
- install a "bootloader" on your PIC32
- create a "Hello World" program for the NU32 that you compile to a .hex file, download to your PIC32, and run.
The bootloader is programmed to the PIC's flash memory using a programmer (such as Microchip's ICD). Once the bootloader is there, you should never have to use a programmer again (unless you accidentally overwrite the bootloader in flash memory by using the wrong procdefs.ld "linker" file). From that point on, you should be able to program your PIC simply using a USB cable to connect your PC to the NU32 board.
After you've installed all the software on your PC, you should have the following directories:
- C:\Microchip Solutions: This has a lot of demo code, among other things. The C:\Microchip Solutions\Microchip\Include directory contains .h files that you are likely to need for your programs. Also, C:\Microchip Solutions\USB Device - Bootloaders\HID - Bootloader has .hex bootloaders for different PICs. (Note: these .hex bootloaders don't work with the NU32 board, which is why we compiled our own bootloader.) It also has PC source software for USB communication with a PIC with the bootloader installed (for programming the PIC without a programmer device).
- C:\Program Files\Microchip: There is a lot of stuff under this directory. Two notable directories are MPLAB C32 and MPLAB C32 Suite. These directories look essentially exactly the same, unless I'm missing something. One directory of interest is C:\Program Files\Microchip\MPLAB C32\pic32_libs\include, which has plib.h (function definitions for the peripheral libraries) and subdirectories peripheral (with .h files for peripheral libraries) and proc (with .h files for different PICs containing type definitions and memory addresses specific to the PICs). Another directory of interest is C:\Program Files\Microchip\MPLAB C32\pic32_libs\peripheral, which has directories for each of the peripherals and .c, .inc, and .h source files for the libraries for these peripherals.
In addition, you have the HID Bootloader program in your PC's start menu.
When you created your first Hello World project, you went through the following steps:
- Created a new directory to hold the project, and put the files "HardwareProfile.h" and "HardwareProfile_NU32.h" "header" files into the directory.
- Used the Project Wizard to create a new project in that directory and specified that you would be using the PIC32MX460F512L microcontroller.
- Added the HardwareProfile.h and HardwareProfile_NU32.h to your project. (This allows your project to know it has to recompile if these files are changed.)
- Added procdefs.ld (a "linker" file) to your project. This file is different from the procdefs.ld file used for your bootloader. These files tell MPLAB where the code should be placed in program memory, and the two procdefs.ld are different so your Hello World program does not overwrite the bootloader code. (This is not the only linker file used, so we put it under "Other Files.")
- Added two search paths to "Include Search Path," (1) C:\Microchip Solutions\Microchip\Include and (2) the directory of your project, where you are creating your source code.
- Created a constant "PIC32_NU32" in the MPLAB PIC32 C Compiler tab.
- Wrote the main.c code for Hello World, added it to the project, and used Project->Build all to create a .hex file that you then loaded on to the PIC32 using the HID bootloader.
So what was the purpose of each of these steps? Steps 2 and 6 defined constants that tell the compiler the microcontroller you are using and the board it is being used on. How are these constants used? Open up HardwareProfile.h, which you included in your project (step 3). Because you have defined __32MX460F512L__ (step 2), and because you have defined PIC32_NU32 (step 6), this file includes "HardwareProfile_NU32.h". Now take a look at the file HardwareProfile_NU32.h. The first thing it does is include "Compiler.h". We can find Compiler.h in C:\Microchip Solutions\Microchip\Include, which we included in our "Include Search Path" (step 5) so the compiler would know where to find it. Let's come back to Compiler.h shortly.
OK, continuing through HardwareProfile_NU32.h, we see that our PIC will have a system frequency of 80 MHz. Note that this does not actually set what the PIC does with the oscillator we have provided.
Continuing with HardwareProfile_NU32.h, we see that a function "mInitAllLEDs()" is defined. It does two things: it sets the latch bits (LATE) and the "tri-state" bits (TRISE) of port E. LATE and TRISE are the values of Special Function Registers (SFRs) for the digital I/O peripherals and are defined elsewhere, as we will see soon. (See also PIC32MX: Digital Inputs and PIC32MX: Digital Outputs for more on using the digital I/O peripherals.) The command "LATE |= 0x000F" bitwise logically "ORs" the current bits of LATE with the bits of the hexadecimal value 0x000F. (This is equivalent to the command "LATE = LATE | 0x000F", and C programmers will notice that this syntax is similar to the syntax a += 3, which is equivalent to a = a + 3.) Note that 0x000F corresponds to a binary value of 0000 0000 0000 1111. So whatever the current values of LATE are, the last four bits (least significant bits) will be 1 after this operation. (Note that 0x000F has only 16 bits, but LATE is technically 32-bit. The first 16-bits are not used, however; see Section 12 of the PIC32 Reference Manual). The command "TRISE &= 0xFFF0" sets whether the pins in port E will be inputs or outputs by doing a bitwise AND with 1111 1111 1111 0000. In other words, the first 12 bits will be unchanged, while the last four bits will be set to outputs (0 = output, 1 = input). These last four bits are going to be used to power our NU32 board LEDs, so they must be outputs. We then see the mnemonic names "mLED_x" given to the (output) values of these four bits. A number of functions are then defined to get the current values of the LEDs and to turn the LEDs on, turn them off, or toggle them. (Note that an output value of 0, or 0 voltage, corresponds to the LED being on; consult the NU32 schematic to see why this is the case.) Finally, functions are defined that will configure bits 4 and 5 of port E as inputs. These are used for the USER and PRG switches on the NU32 board. The constants swProgram and swUser return the current values of these inputs, 0 for low (ground), 1 for high (3.3V).
OK, now let's open Compiler.h from a few paragraphs earlier. We find that since we are using the C32 compiler, it includes the header files p32xxxx.h and plib.h. We will take a look at those shortly, but let's continue with Compiler.h. It also includes some standard C libraries, like stdio.h (libraries for input and output), stdlib.h, and string.h (for string manipulation). It makes a few more definitions which are beyond our scope for now. You might be interested to see the defined function "Nop()" which stands for "no operation," i.e., just waste a cycle. It is defined using an assembly code command using asm("nop"). In other words, if you were coding in assembly (and thank goodness you're not), you would type "nop." You can write low-level assembly code in C using the command asm(). If you are interested, you can always see the assembly code generated by your C code by using View->Disassembly Listing in the MPLAB IDE.
Let's go back and look at p32xxxx.h and plib.h, referenced by Compiler.h. They can be found under C:\Program Files\Microchip\MPLAB C32\pic32_libs\include. plib.h simply includes a bunch of .h files for the peripheral libraries: 10-bit ADC (adc10.h) which further makes use of definitions in ports.h; I2C serial communication (i2c.h); etc. All of these .h files are under C:\Program Files\Microchip\MPLAB C32\pic32_libs\include\peripheral. We can open one of these many .h files, and we'll see that they define functions that are designed to simplify our use of the peripheral. You can learn more about the use of these peripheral libraries in the peripheral library guide (see also Further Reading at the end of this page). Also, you can see the source code for the peripherals to see how the higher-level peripheral functions are created from low-level functions by looking in C:\Program Files\Microchip\MPLAB C32\pic32_libs\peripheral.
If we now open p32xxxx.h, we find that it simply includes the file p32mx460f512l.h, which is under C:\Program Files\Microchip\MPLAB C32\pic32_libs\include\proc. If we open up this file... whoa! Finally we see where a lot of the data types and variables and constants are defined that have been used earlier. The details are well beyond our scope here, but we can look at the beginning of the file, where the variable WDTCON (WatchDog Timer CONfiguration) is defined as an unsigned integer (a 32-bit integer from 0 to 2^31-1). Also, the data type __WDTCONbits_t is defined, consisting of a set of structures, and then the variable WDTCONbits is defined of type __WDTCONbits_t. The rest of this very large file defines data types and variables for configuration bits, various constants, quantities associated with interrupts, addresses for peripherals specific to the particular PIC, etc.
OK, we've spent a lot of time tracing #include files to see where various things are defined, configuration bits set, etc. We could spend more time on this, but you get the idea. In the MPLAB IDE, you can click on Configure->Configuration Bits to set some of the Configuration Bits using the IDE, rather than in your source files. I think it is best to have it written in your source files so another programmer knows where to find them. So leave the checkbox "Configuration Bits set in code" checked.
One more thing that we have not yet mentioned: when you put the bootloader on your PIC, it configured some of the Special Function Registers (SFRs) of your PIC. In particular, open main.c of your bootloader project, and you will see a series of #pragma directives that get executed upon recognizing that you have defined the constant PIC32_NU32. (#pragma directives are compiler-specific instructions, in this case for PIC microcotnrollers, not general C language instructions.) Notice, for example, that FPLLMUL is set to MUL_20 (where is this defined?), meaning that the PLL (phase-locked loop) in the PIC multiplies the external crystal frequency by 20 (8 MHz x 20 = 160 MHz), and then FPLLIDIV (PLL input divider) divides the frequency by 2, and FPLLODIV (PLL output divider) divides by 1, giving our final system clock of 80 MHz. This is where the actual hardware is configured to give us our actual clock frequency. The peripheral clock is set to the same frequency. USB communication requires a precise 48 MHz clock, and the USB PLL multiplies its input frequency by 12. Therefore, we must provide the USB PLL with a 4 MHz signal, and therefore the bootloader sets UPLLIDIV (USB PLL Input Divider) to 2, to divide the 8 MHz clock by 2. Much of the rest of main.c is devoted to code that allows you to program the PIC by USB communication.
OK, going back to the main.c file you created for your Hello World project. After all the includes, a constant SYS_FREQ is defined to be 80 million. (NOTE: You could accidentally type 8 million or 800 million, and nothing would work properly! Make sure you type 80 million. Ideally, this SYS_FREQ would be derived from the definitions in the bootloader's main.c file, so you wouldn't have to type again.) Then SYSTEMConfigPerformance(SYS_FREQ) is called. This function is defined in C:\Program Files\Microchip\MPLAB C32\pic32_libs\include\peripheral, and one of its purposes is to define some timing constants to hopefully optimize the performance of your PIC (e.g., the use of the pre-fetch cache). Then the LED functions defined in HardwareProfile_NU32.h are used to initialize the LEDs and turn them on or off according to whether the USER button is pushed.
Finally, what happens when you "Build All" (step 7)? The compiler compiles any of the individual source files that have been modified since the last Build into .o files, called object code. The linker then puts everything together using a default linker file as well as your procdefs.ld (step 4) and assigns the code to specific addresses in program memory.
So, to summarize, this was the chain of #include files:
- The Hello World main.c program included HardwareProfile.h.
- HardwareProfile.h does little but include HardwareProfile_NU32.h and Compiler.h.
- HardwareProfile_NU32.h defines initialization functions to set 4 pins of Port E as digital outputs and 2 as digital inputs; defines convenient names for these pins; and defines functions for turning the NU32 LEDs on and off.
- Compiler.h provides a few definitions and includes some standard C libraries (stdio.h, stdlib.h, string.h) as well as p32xxxx.h and plib.h.
- plib.h includes the peripheral libraries (e.g., adc10.h, i2c.h, etc.), which you can learn more about in this peripheral library guide (314 page pdf).
- p32xxxx.h includes p32mx460f512l.h.
- p32mx460f512l.h is a big file and makes many of the microcontroller-specific definitions. This includes defining data types and variable names for the peripheral SFRs (e.g., LATE, PORTE, and TRISE, as mentioned above) and some convenient names for addresses and interrupt numbers and vectors. It also includes ppic32mx.h., which defines some other mnemonic variable names.
- HardwareProfile.h does little but include HardwareProfile_NU32.h and Compiler.h.
Finally, the bootloader main.c file defined some of the configuration bits for the clock circuitry, to set the SYSCLK and PBCLK to 80 MHz, and the USBCLK to 48 MHz, given that we have an 8 MHz crystal.
Further Reading
There are many references out there to learn more about the hardware and programming of the PIC32. Some of these are more accessible than others. A good book that discusses both the hardware and programming of the PIC32 at an introductory to intermediate level is DiJasio's Programming 32-bit Microcontrollers in C: Exploring the PIC32 (see also a pdf version of the book available for download). It was published in 2008, soon after PIC32's were released. It does not make use of many peripheral library functions, but instead provides low-level code to develop your own libraries. Still, it is a good first book to understand how the PIC32 works.
I think these are the three most useful Microchip reference documents:
- PIC32 Reference Manual (1138 pages, 11 MB pdf): Lots of useful and detailed information on the PIC32 architecture and how the peripherals work, including detailed description of their SFRs.
- PIC32 Data Sheet (646 pages, 8 MB pdf): Has overlap with the Reference Manual, but the Reference Manual contains some information you can't find here, and the Data Sheet contains some information you can't find in the Reference Manual.
- Peripheral Library Guide (314 page pdf): Manual describing the use of the peripheral library functions described in plib.h.
There is also a "short" PIC32 Data Sheet (172 pages, 3 MB pdf). You can also visit the Microchip documentation page.
To better understand how to program the PIC32, your best bet is to modify sample code in the Microchip distribution (see in particular the code in C:\Program Files\Microchip\MPLAB C32\examples), on this wiki, and elsewhere on the web. Andy Long created this introductory presentation on programming the PIC32 digital I/O and ADC peripherals you might find useful. You might also wish to look at some of the many Microchip Application Notes. It is also useful to look at the .h files, particularly for the peripheral library, much like we did above. You can also look at the peripheral source code to see what exactly the peripheral libraries do in the cases that the functions are not completely described in the .h files. The MPLAB C32 C Compiler User's Guide (120 page pdf) contains information on programming the PIC32 in C, and the MPLAB C32 Libraries Manual (150 page pdf) discusses some standard C libraries as well as libraries for functions such as Fast Fourier Transforms, FIR and IIR filters, and functions on arrays.
As you find other useful resources for programming, feel free to add them here!