chipKIT® Development Platform

Inspired by Arduino™

Programming ChipKit Pic32 with MPLAB X

Created Sun, 22 Jun 2014 07:37:19 +0000 by rascalito


rascalito

Sun, 22 Jun 2014 07:37:19 +0000

Hello!

I'm an absolute beginner with Uno32 (PIC) and I would like to get started with MPLAB X. Is there any tutorial for that?I have a PicKit3 and I bought a connector for the board. If there is some sample code somewhere, it would be great.

Thanks for any hint.

Pascal

NB: I dont'w want to use ARDUINO.


majenko

Sun, 22 Jun 2014 11:48:56 +0000

Ok, so you want an introduction to programming the PIC32 microcontroller. Forget all references to "chipKIT" or "Uno32" as they are completely irrelevant when you are working with MPLAB-X.

There are a few things you will need to get yourself started:

  1. The Uno32 user manual

It contains a useful table giving you the board's IO pin number and the chip's IO pin name. You will want the IO pin names (and their functions, also listed in that table) in order to use them in MPLAB-X. It may be useful to print that table out.

  1. The data sheet for the chip

The chip is the PIC32MX320F128H. The data sheet will tell you all about what peripherals are in the chip, and a list of all the registers for controlling the peripherals. It doesn't, however, tell you really how to do anything much with those peripherals - however, it is an essential document to have on hand.

  1. The PIC32 Family Reference Manual (FRM)

This is a collection of about 30 or so PDF documents which describe the workings of all the peripherals and low level functions of the chip in great detail, including example code.

  1. The source to the bootloader

You won't be using a bootloader, but the source to the bootloader contains the settings for the chip. Yes, you can spend time crafting your own config bits (and MPLAB-X contains an easy to use editor for them), but it's easier to just copy and paste them from a known working system.

Most of the documents are listed in this thread: [url]http://chipkit.net/forum/viewtopic.php?f=17&t=2517[/url] The bootloader source with the config settings in is here: [url]https://raw.githubusercontent.com/chipKIT32/PIC32-avrdude-bootloader/master/bootloaders/BoardConfig.h[/url] - it's the #pragma bits you're interested in.

From then on, it's basically programming in C and reading/writing registers.

Microchip also do some libraries that may be of use to you. There's "plib", the "peripheral library" that contains interfaces to various peripherals, though mostly they are just wrappers around register reads and writes. There's the "MLA" - the Microchip Library for Applications, which is packed full of example code and usefule library routines. Also, Microchip have released a new library system called Harmony, which is essentially plib and MLA combined, with more routines and support for more chips (MZ).


rascalito

Mon, 23 Jun 2014 02:23:18 +0000

Hello!

Thanks a lot! I think it's close to what I want, but I don't really know how to start.

What I did:

  • Installed MPLAN X and the proper compiler XC32
  • Plugged the PicKit to the UNO32 board -> Can the UNO board be powered from PicKit3? If not I need an external power supply, but then I cannot fit a power jack and the pic kit at the same time, so I will assume pic kit can power the board.
  • Downloaded the BoardConfig.h file from the link you listed above
  • Created a new program, choosed XC32, pickkit3, etc... and made a new main file. I have included the BoardConfig.h in the main (that does nothing for the time being) and compiled.

As the first error was #error: board.cpu configuration not defined, I have looked at the code and added #define BOARD_CHIPKIT_UNO32 at the top of the file (just after revision history).

Now as it says "SYSKEY undeclared", I think it needs some header file specific to the PIC32MX320F128. I searched for header files, and found out that there is a file p32mx320f128h.h. I have included first between <>, and as it didn't work, between "" just in case, but the IDE replies not such file or directory. Do I have to set a path somewhere? When installing, I checked "add xxxx to path", so I guess it should be found automatically.

Thanks for any hint.

Pascal


rascalito

Tue, 24 Jun 2014 03:43:29 +0000

Hello!

I have tried to understand how to set paths with MPLABX.

First using the cmd-option trick, I could have info about the include paths where MPLABX searches.

/Applications/microchip/xc32/v1.32/bin/../lib/gcc/pic32mx/4.5.1/include /Applications/microchip/xc32/v1.32/bin/../lib/gcc/pic32mx/4.5.1/include-fixed /Applications/microchip/xc32/v1.32/bin/../pic32mx/include

Now I have searched on my disk and found out that the file p32mx320f128h.h is located in /Applications/microchip/xc32/v1.32/pic32mx/include/lega-c/proc/p32mx320f128h.h

I have tried to look at MPLABX preferences and spent some time looking at all the possible options, but I don't find any place likely to allow me to add a path. I have tried to copy the file p32mx320f128h.h locally. It doesn't help and I get an error at the following line : #include "ppic32mx.h" It cannot find this file, so I added ppic32mx.h locally, but then it does not find serial.h, and I have the impression it will be an endless process until I can compile an application.

Can anyone tell me how to add a new path? Is there a real beginner tutorial somewhere that does not assume I'm familiar with the IDE and explains every possible step?

Thanks,

Pascal


majenko

Tue, 24 Jun 2014 07:58:12 +0000

You shouldn't need to set any paths.

The standard include

#include &lt;p32xxxx.h&gt;

should include everything for you.

Most of what is in the BoardConfig.h file you don't want. Just find the section for the UNO32 and copy and paste the #pragma lines into the top of your program. Don't include BoardConfig.h.


rascalito

Tue, 24 Jun 2014 09:30:08 +0000

Hello!

Thanks for your reply. I think I got closer. I have copied the part specific to UNO32. I can't claim I fully understand what it does, but at least it compiles this time. Something I am wondering about: there is a line like this:

#if	defined(PUT_CONFIG_BITS_HERE)

then a series of configuration pragmas, and the final endif.

What should I do with it?

I have tried both versions, with and without the if defined statement.

The result is: [color=#FF0040]Target device was not found. You must connect to a target device to use PICkit 3. [/color]

What should I do next? I have (of course) selected pic3, plugged it on the PC and to the UNO32 board. As it didn't work, I tried to solder the connectoer (I read somewhere that it could work without soldering the connector, but just in case...). Same result: device not found.

I just noticed that there are 2 report panes. One is pickit3 and the other is UnoTest(Build Load...) where UnoTest is the name of my program In this latter panel, it says: [color=#FF0000]The programmer could not be started: Failed to program the target device [/color]

Is there another trick to know in order to load a program to the target board?

Thanks,

Pascal


majenko

Tue, 24 Jun 2014 19:40:56 +0000

Have you turned on the power?

Unless you're powering the board externally you will need to enable self power mode on the PICKIT3. Go in to the priject preferences, select the pk3, then choose power from the drop-down list. In there you can tell it to power the board from the pk3.


rascalito

Wed, 25 Jun 2014 08:23:32 +0000

Hello Majenko!

That made all the difference. It works! I managed to blink the user leds on ports F and G.

I will try to use a graphic LCD now.

Thanks!

Pascal


majenko

Wed, 25 Jun 2014 09:40:42 +0000

Good luck with that :)

Glad it's blinking anyway. It's so much more rewarding (and great for personal knowledge) to work with the bare metal instead of abstracted layers of API code.


rascalito

Thu, 26 Jun 2014 03:20:39 +0000

Hello!

Glad it's blinking anyway. It's so much more rewarding (and great for personal knowledge) to work with the bare metal instead of abstracted layers of API code.

Yes, I agree. But my impression is that the plib itself prevents to really understand what happens. Maybe because I'm not used to it... For example, if I look at chapter 23 (SPI) of Pic32 documentation, table 23-3 shows a summary of the SPI registers. If I take for instance the first line SPIxCON, I should be able to configure SPI by setting for example for SPI1: SPI1CON |= 0x00000040; and it would set the clock polarity. But the system does not understand what SPI1CON is. So until I find out the variable name or define myself a place in the memory where it's located, no way to set it up directly.

Well, now here is today's problem. I have tried to setup SPI. I have used a file I downloaded from Microchip, and which is called burst_master.c. It shows how to setup SPI. What I am doing is just sending 0xAA (easy to spot on the scope) and then delay. I used SPI_CHANNEL1 and I found the pattern on pin TX (pin 3 on connector IOH, which is labeled "1" (TX). That's fine, but I don't find any clock. Well, I do find one clock on pin labeled 40, pin 14 of connector IOH, but it's a fixed 20 MHZ clock.

Any hint to setup a SPI? I also tried to configure with SPI_CHANNEL2, but in this case I find no signal at all.

Just in case, here is the code. NB: In this code, SPI_CHANNEL2 is used. This is the non-working (no signal anywhere) version. With SPI_CHANNEL1, I get MOSI on TX.

Thanks for any hint!

Pascal

//  
//  File:   UnoSpi.c
//  Author: pascal
//	
//	What it does: just (tries to) set up a SPI and send bytes.
//	
//  Created on June 25, 2014, 4:11 PM
#include &lt;p32xxxx.h&gt;
#include &lt;plib.h&gt;
#include "Uno32Config.h"

#define	LED4	0x0001
#define	LED5	0x0040

#define MILLISECOND	(SYS_FREQ/10000)

void SpiInit(void);
void SpiSend(char * buf, int len);
void Delay(int ms);
char test_buf[4] = {0xAA, 0x00, 0xAA, 0x00};

//  blink_leds application code
void main(void) {
	unsigned int i = 0;
	unsigned portf, portg;
	SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
	SpiInit();
	while(1) {
		SpiSend(test_buf, 1);
		Delay(1);
	}
}

void SpiInit(void) {
	SpiInitDevice(SPI_CHANNEL2, 1, 1, 1);
}


void SpiInitDevice(SpiChannel chn, int isMaster, int frmEn, int frmMaster) {
	SpiOpenFlags	oFlags = SPI_OPEN_MODE8 | SPI_OPEN_SMP_END;	// SPI open mode
	if(isMaster) {
		oFlags |= SPI_OPEN_MSTEN;
	}
    if(frmEn) {
		oFlags |= SPI_OPEN_FRMEN;
		if(!frmMaster) {
			oFlags|=SPI_OPEN_FSP_IN;
		}
	}
    // Open SPI module, use SPI channel 1, use flags set above, Divide Fpb by 4
    // Not using SS in this example
    SpiChnOpen(chn, oFlags, 4);
}

void Delay(int ms) {
	int i = MILLISECOND;
	int j = 0;
	for(j = 0 ; j &lt; ms ; ++j) {
		while(i--) {};
	}
}

void SpiSend(char * buf, int len) {
	SpiChnPutS(1, buf, len);
}

And the config file Uno32Config.h

//  
//  File:   Pic32Config.h
//  Author: pascal
//
//  What it does: keeps defs out of the main code
//
//  Created on June 25, 2014, 4:11 PM

#ifndef _UNO_32_CONFIG_H_
#define	_UNO_32_CONFIG_H_

#ifdef	__cplusplus
extern "C" {
#endif

// application defines
#define SYS_FREQ		(80000000)
//    Oscillator Settings
#pragma config FNOSC    = PRIPLL                        // Oscillator selection
#pragma config POSCMOD  = XT                            // Primary oscillator mode
#pragma config FPLLIDIV = DIV_2                         // PLL input divider
#pragma config FPLLMUL  = MUL_20                        // PLL multiplier
#pragma config FPLLODIV = DIV_1                         // PLL output divider
#pragma config FPBDIV   = DIV_1                         // Peripheral bus clock divider
#pragma config FSOSCEN  = ON                            // Secondary oscillator enable
//*    Clock control settings
#pragma config IESO     = OFF                           // Internal/external clock switchover
#pragma config FCKSM    = CSDCMD                        // Clock switching (CSx)/Clock monitor (CMx)
#pragma config OSCIOFNC = OFF                           // Clock output on OSCO pin enable
//*    Other Peripheral Device settings
#pragma config FWDTEN   = OFF                           // Watchdog timer enable
#pragma config WDTPS    =  PS1024                       // Watchdog timer postscaler
//*    Code Protection settings
#pragma config CP       = OFF                           // Code protection
#pragma config BWP      = OFF                           // Boot flash write protect
#pragma config PWP      = OFF                           // Program flash write protect
//*    Debug settings
#pragma config ICESEL   = ICS_PGx2                      // ICE pin selection
//#endif
#define CAPABILITIES    (blCapBootLED | blCapDownloadLED | blCapUARTInterface | blCapAutoResetListening | blCapVirtualProgramButton | CAPCOMMON)
// BTN / LED sense
#define LedOn       High
#define BntOn       High
// Boot LED
#define BLedLat     G
#define BLedBit     6
// Download LED
#define DLedLat     F
#define DLedBit     0
// Virtual program button
#define VPBntLat    C
#define VPBntBit    12
// Other capabilities
#define LISTEN_BEFORE_LOAD          2000                // no less than 2 seconds
#define BOOTLOADER_UART             1                   // avrdude program UART
#define BAUDRATE                    115200              // avrdude baudrate
#define _CPU_NAME_                  "32MX320F128H"
#define VEND                        vendDigilent
#define PROD                        prodChipKITUno32
#define F_CPU                       80000000UL
#define F_PBUS                      F_CPU
#define FLASH_BYTES                 0x20000             // 128K
#define FLASH_PAGE_SIZE             4096
#define LoadFlashWaitStates()       (CHECON = 2)

#ifdef	__cplusplus
}
#endif

#endif	//  _UNO_32_CONFIG_H_

majenko

Thu, 26 Jun 2014 08:41:06 +0000

SPI2 should be the one to choose - that is presented on pins 11-13, (clock on 13).

Personally I have never really got on with plib and prefer to directly manipulate the registers.

You should have access to the SPI2CON register without problems. The p32xxxx.h file should automatically include the correct header for your selected chip which will provide access to all those registers.


rascalito

Thu, 26 Jun 2014 09:16:08 +0000

Hello!

Thanks for your useful hints. Great! I'm going to write my own brew of SPI initialisation. It may take time since it's on my spare time, but it will definitely help me to understand the internals even if my implementation is not as good as plib.

Thanks again!

Pascal

PS: Indeed, I could access SPI2CON and SPI1CON as well. I don't know what I did this morning, probably a typo of some kind.


majenko

Thu, 26 Jun 2014 10:30:58 +0000

SP1ICON? ;)

By the way, you also have access to the SPI2CONbits.* structures. Here's my initialization code for an I2C codec chip running on SPI1 of a PIC32MX470F512L chip:

// Configure the SPI port to take its clock from the REFCLK and
    // operate in I2S mode
    SPI1CONbits.ON = 0;
    SPI1CONbits.FRMEN = 0;
    SPI1CONbits.FRMSYNC = 0;
    SPI1CONbits.FRMPOL = 0;
    SPI1CONbits.MSSEN = 0;
    SPI1CONbits.FRMSYPW = 0;
    SPI1CONbits.FRMCNT = 0b000;
    SPI1CONbits.MCLKSEL = 1; // REFCLK
    SPI1CONbits.SPIFE = 0;
    SPI1CONbits.ENHBUF = 1;
    SPI1CONbits.SIDL = 0;
    SPI1CONbits.DISSDO = 0;
    SPI1CONbits.MODE32 = 0; // 16 bit per channel
    SPI1CONbits.MODE16 = 0; // 16 bit per channel
    SPI1CONbits.SMP = 0;
    SPI1CONbits.CKE = 0;
    SPI1CONbits.SSEN = 0;
    SPI1CONbits.CKP = 0;
    SPI1CONbits.MSTEN = 1; // Master mode
    SPI1CONbits.DISSDI = 1; // No SDI for now
    SPI1CONbits.STXISEL = 0b11;
    SPI1CONbits.SRXISEL = 0b00;

    SPI1CON2bits.SPISGNEXT = 0;
    SPI1CON2bits.FRMERREN = 0;
    SPI1CON2bits.SPIROVEN = 0;
    SPI1CON2bits.SPITUREN = 0;
    SPI1CON2bits.IGNROV = 0;
    SPI1CON2bits.IGNTUR = 1;
    SPI1CON2bits.AUDEN = 1; // Enable audio mode
    SPI1CON2bits.AUDMONO = 0; // Stereo audio
    SPI1CON2bits.AUDMOD = 0b00; // I2S mode

    SPI1BRG = 3; // 192000Hz SPI clock = 4 bytes per sample @ 48000sps

    SPI1CONbits.ON = 1; // Turn it on

Some bits, of course, will be different for your chip (no REFCLK for example) but you can see how much easier to read that is than setting bits with |= etc - but it is more long winded.

For your SPI you only need to really deal with the clock polarity and sample edge, the master mode, bit width, clock source, and turn it on. Most things as default are fine for basic SPI work.

Just remember to make turning it on your last operation ;)


Max44

Sat, 28 Jun 2014 17:18:49 +0000

Pascal,

I may have missed it, but I didn't see where you're configuring your I/O pins. Although I assume if you have LEDs blinking it must have been done somewhere. Even for SPI, you need to define the associated TRIS port register for input (default) or output.

I'm working with a WF32 in MPLAB X. The WiFi module works over a SPI port. The pins are configured as (for example):

//----------------------------
// MRF24WG0MA/B WiFi I/O pins
//----------------------------
//
// The WF32 MRF24G pins are
//
//      CS          RF12    MCU pin 40      ChipKit pin 54
//      SDI         RF5     MCU pin 50      ChipKit pin 56
//      SCK         RF13    MCU pin 39      ChipKit pin 53
//      SDO         RF4     MCU pin 49      ChipKit pin 55
//      RESET       RG0     MCU pon 90      ChipKit pin 59
//      INT         RA15    MCU pin 67      ChipKit pin 57
//      HIBERNATE   RG1     MCU Pin 89      ChipKit pin 58
//


#define WF_CS_TRIS			(TRISFbits.TRISF12)
#define WF_CS_IO			(LATFbits.LATF12)
#define WF_SDI_TRIS			(TRISFbits.TRISF5)
#define WF_SCK_TRIS			(TRISFbits.TRISF13)
#define WF_SDO_TRIS			(TRISFbits.TRISF4)
#define WF_RESET_TRIS                   (TRISGbits.TRISG0)
#define WF_RESET_IO			(LATGbits.LATG0)

Then, within your initialization routine, you would do something like:

// Set up the SPI module on the PIC for communications with the MRF24W
    WF_CS_TRIS     = 0;     // Drive SPI MRF24W chip select pin
    WF_CS_IO       = 1;

Maybe this will also help when you get around to those SPI initialization routines!

Max


svs_03

Tue, 31 May 2016 15:36:51 +0000

I tried with one of the above solutions by adding avrdude.exe and .conf file . also I added linker files for max 32 board. The fallowing are the errors it is showing . how to proceed????