Changing PWM frequency and bit resolution

Overview

You have to bypass the analogWrite function in the abstraction layer and talk directly to the hardware to do this. You will need to program one of the timers, and one or more of the output compares to do this. The Output Compare units in the PIC32 can work from either Timer2 or Timer3. The analogWrite code uses Timer2. If you don’t need analogWrite to work, I would use Timer2. If you need analogWrite to work as well, use Timer3. The Output Compare sets the pin when the timer resets. The timer then counts up from 0. The Output Compare resets the pin when the the value in the timer matches the value in the ouput compare register. The counter continues to count up until the count value matches the value in the period register. The timer then resets and it all starts over again. Also at the end of a period the contents of the duty cycle buffer register(OCxRS) is loaded into the duty cycle register(OCxR). The frequency of the resulting PWM signal is determined by the clock speed of the timer, and the value in the period register. The clock speed of the timer is determined by the peripheral bus frequency and the prescaler selected. The peripheral bus frequency is 80 MHz (at least this is the default set by the boot loader). The prescaler can be selected to be 1:1, 1:2, 1:4, up to 1:256. So for example, with a 1:8 prescaler selected, the 80 MHz would be divided down to 10 MHz and that is the timer clock frequency (i.e. the timer counts up 1 every 100ns). The value in the period register determines when the counter resets. So, for example if you set the period register to 10000, you would get a reset at 10000*100ns, or every 1 ms. This is a frequency of 1 kHz. To get a 12-bit PWM, you could load the period register with 4096 (2^12). With the 1:8 prescaler, this would give a frequency of about 2.4 kHz.

Code

The following code will initialize Timer2 with the 1:8 prescaler and a period value of 4096
T2CONCLR = T2_ON          // Turn the timer off
T2CON = T2_PS_1_8;        // Set prescaler
TMR2 = 0;                 // Clear the counter
PR2 = 4096;               // Set the period
T2CONSET = T2_ON;         // Turn the timer on
The following code will set output compare 1 to use Timer2 and a PWM value that would give a 50% duty cycle.
OC1R = 2048;              // Load initial value into duty cycle register
OC1RS = 2048;             // When a period finishes the contents of OC1RS is loaded to OC1R
OC1CON = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE; // Set Timer2 as source | enable pwm mode without fault protection
OC1CONSET = OC_ON;
This example code is taken (and slightly modified) from the code for analogWrite. This is in the file wiring_analog.c in the core files. These statements are all writing directly to the peripheral registers for Timer2 and Output Compare 1. For more complete details, you should refer to the Timer and Output Compare sections of the PIC32 Family Reference Manual that can be downloaded from the Microchip web site.
VN:F [1.9.22_1171]
Rating: 6.6/10 (9 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Debugging with ejtagproxy and GDB

Debugging without MPLAB is possible through ejtagproxy. You need a compatible ICSP adapter, like PICkit2 or PICkit3 (full list of compatible adapters is available on project homepage). Note that you can’t use PICkit2 with MPLAB, but it works with ejtagproxy. Obtain source, build. Obtain stock GDB source. Configure with –target=mipsel-elf32 . Build. Start ejtagproxy:
$ ejtagproxy
GDB proxy for Microchip PIC32 processors, Version 1.0.25
Copyright (C) 2012 Serge Vakulenko

EJTAGproxy comes with ABSOLUTELY NO WARRANTY; for details
use `--warranty' option. This is Open Source software. You are
welcome to redistribute it under certain conditions. Use the
'--copying' option for details.
ejtagproxy: waiting on TCP port 2000
Start GDB and point it to ELF file of your application:
$ pic32-gdb ~/repos/chipKIT-minimal-application/src/main.elf
(gdb)
Set the target to ejtagproxy:
(gdb) target remote localhost:2000
You should notice that ICSP adapter is now connected to target board. On my chipKIT Max32 this also results in board reset. The ejtagproxy willl print something like:
adapter: PICkit2 Version 2.32.0
processor: Microchip PIC32MX795F512L
processor: reset occured
hardware: 6 breakpoints, 2 watchpoints
oscillator: internal Fast RC
And GDB will connect to target:
Remote debugging using localhost:2000
0xbfc00000 in ?? ()
(gdb)
Now you can set breakpoints, watchpoints, etc. and run the application.
(gdb) break main
Breakpoint 1 at 0x9d00136c: file main.c, line 12.
(gdb) c
Continuing.
Unfortunately, when ejtagproxy is connected to target board everything is much slower than normally, so you have to wait a moment…
Breakpoint 1, main () at main.c:12

12			loop();
As you can see breakpoint was successfully activated in main() function. Now it’s possible to do further analysis:
(gdb) i reg
         zero       at       v0       v1       a0       a1       a2       a3
R0   00000000 ffbfffff ffffffff ffffffff 00000000 00000000 a000001c bf800000 
           t0       t1       t2       t3       t4       t5       t6       t7
R8   9d0011f0 00000000 00000020 04000000 00000000 00000000 00000000 00000000 
           s0       s1       s2       s3       s4       s5       s6       s7
R16  00000000 00100000 00000000 00000000 00000000 00000002 00000000 00000000 
           t8       t9       k0       k1       gp       sp       s8       ra
R24  00000000 00000000 00000000 00000000 a00081f0 a001ffe8 a001ffe8 9d001208 
           sr       lo       hi      bad    cause       pc
     00100000 00000019 00000001 cc37facd a0800034 9d00136c 
          fsr      fir
     can't read register 160 (fsr)
(gdb) disassemble 
Dump of assembler code for function main:
  0x9d00135c <+0>:	addiu	sp,sp,-24
  0x9d001360 <+4>:	sw	ra,20(sp)
  0x9d001364 <+8>:	sw	s8,16(sp)
  0x9d001368 <+12>:	move	s8,sp
=> 0x9d00136c <+16>:	jal	0x9d001328 <loop>
  0x9d001370 <+20>:	nop
  0x9d001374 <+24>:	j	0x9d00136c <main+16>
  0x9d001378 <+28>:	nop
End of assembler dump.
(gdb) stepi
loop () at main.c:1
1	void loop(void) {
(gdb) disassemble 
Dump of assembler code for function loop:
=> 0x9d001328 <+0>:	addiu	sp,sp,-16
  0x9d00132c <+4>:	sw	s8,12(sp)
  0x9d001330 <+8>:	move	s8,sp
  0x9d001334 <+12>:	li	v0,1
  0x9d001338 <+16>:	sw	v0,0(s8)
  0x9d00133c <+20>:	lw	v0,4(s8)
  0x9d001340 <+24>:	addiu	v0,v0,2
  0x9d001344 <+28>:	sw	v0,4(s8)
  0x9d001348 <+32>:	move	sp,s8
  0x9d00134c <+36>:	lw	s8,12(sp)
  0x9d001350 <+40>:	addiu	sp,sp,16
  0x9d001354 <+44>:	jr	ra
  0x9d001358 <+48>:	nop
End of assembler dump.
(gdb)
VN:F [1.9.22_1171]
Rating: 8.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Development without MPIDE or MPLAB

It is possible to create pure C / assembly code for chipKIT boards without MPIDE or MPLAB.

Compiler

Newlib-based chipKIT compiler Example minimal application (contains Makefile, linker scripts, startup code, trivial C app)

Uploading to board

See “Using avrdude from Linux console” section in avrdude and the chipkit article. Example minimal application above has uploading with avrdude integrated into Makefile.

Debugging

Debugging with ejtagproxy and GDB.
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

embedXcode

embedXcode: Use MPIDE with Apple Xcode

eX

The MPIDE is great and provides plug-and-play and instant gratification but, sometimes, complex sketches require a more powerful IDE. Also, some niceties are welcomed, as syntax colouring, line numbering, function highlighting, code-sense, template with parameters for a function, check-as-you-type, click-to-error, tool-tip texts, object browser, self documentation, version management, repository management, code snippets, Git repository management and even debugging…

I’m using Xcode because I own a MacBook. Xcode is flexible enough to deliver code-sense with just being provided the paths of the source libraries. And the main benefit is faster development.

Modular Set of Makefiles

The paradigm is that a sketch consists on a standard C++ code, and thus processed accordingly. embedXcode requires the prior installation of the IDEs like MPIDE, as they include everything, including tool-chain, framework and utilities. embedXcode relies on a modular set of makefiles, which can be used with other IDEs. I use Xcode because I own a MacBook, but I tested the set of makefiles successfully with NetBeans. As at today, embedXcode supports the most popular Processing-based Wiring-derived Arduino-like platforms: chipKIT MPIDE, Arduino (23 + 1.0 + 1.5), Digistark, DFRobot BLuno, LaunchPad (MSP430, FR5739 and Stellaris LM4F), LeafLabs Maple, Microduino, Teensy 3 and Wiring.

Easy Installation

  • Install MPIDE normally and run it once
  • Double-click on the embedXcode installation package to install the template
  • Launch Xcode

Dedicated Website and Forum Thread

The dedicated website includes:

Also check the MPIDE on Xcode thread on the chipKIT forum.

VN:F [1.9.22_1171]
Rating: 9.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Programming Microchip starter kits from MPIDE

Running on Microchip Starter Kits

MPIDE has been expanded explicitly to support all of the Microchip starter kits such as:
  • PIC32 Starter Kit
  • PIC32 USB Starter Kit
  • PIC32 Ethernet Starter Kit
  • Explorer 16 Starter Kit
Currently for all of these boards you will need some sort of USB to serial adapter. For all but the Exp-16 I use an FTDI cable that breaks out to pins. I connect those to pins on the expansion board for uart1. The PIC32 USB Starter Kit and PIC32 Ethernet Starter Kits are also compatible with the USB PIC32 bootloader. The Explorer-16 has an on-board DB-9 RS-232 connector. This is connected to UART2. The bootloader is configured to use UART2 for the Explorer-16 and the Serial ports for Arduino are remapped so that Serial.print goes to uart2 and Serial1.print goes to uart1. This is all done automatically so the user does not have to worry about it at all. In order to install the bootloader on any of these boards, you have to have one of the Microchip compatible programmers such as the MPLAB ICD 3 or PICkit 3. Ideally you should download MPLAB X IDE from microchip (http://www.microchip.com/mplabx) and use that to compile and burn the bootloader. The bootloader source and pre-compiled hex files are all on github. (https://github.com/chipKIT32/pic32-Arduino-Bootloader)

Using other PIC32 boards

As far as using MPIDE with other boards, the answer is YES, it should work with ANY PIC32 there is. The only limit might be it won’t work on chips smaller than 32K, And that’s because it hasn’t been tried on anything smaller. To get it to work on other boards, a few things have be be done.
  • First, the bootloader has to be burned onto the target board. The source is on github and MPLAB is used to compile and burn the bootloader. The multi-platform MPLAB-X was used on a Mac, but other versions should work as well.
  • If you using a chip that has not already been added to avrdude.conf, that has to be done.
  • You need to add a new entry to boards.txt and then you will be able to program the board directly from MPIDE.
VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

USB Bootloader

The PIC32-avrdude-bootloader communicates over either a serial port (UART) or the USB port (on those pic32 chips that support USB.)  It can be built for either serial or USB communication with the PC. The bootloader communicates with the avrdude executable on the PC side of the connection. The following boards have been tested using the PIC32-avrdude-bootloader:
  • Microchip PIC32 USB starter kit
  • Microchip PIC32 Ethernet starter kit
  • UBW32 – MX460
  • UBW32 – MX795
  • Fubarino SD
  • Fubarino Mini
In order to use this bootloader, you can either download the full source from github, or just pick and choose the HEX file that is right for your board. There are three bootloaders that have been created for chipKIT and chipKIT compatible boards:
  • PIC32-avrdude-bootloader – This new bootloader for MPIDE/chipKIT PIC32 boards is buildable for all currently available  chipKIT boards (UNO32, MAX32, uC32) as well as other PIC32 based boards like the UBW32 and Fubarino boards.
  • pic32-Arduino-USB-Bootloader-original – This is the original version of the bootloader that works only if compiled with the C32 v1.xx version due to changes in the way that newer version of C32/XC32 handles the linker scripts files.
  • pic32-Arduino-Bootloader – This is the older original version of the bootloader which supports only Digilent uno and mega pic32 boards.This bootloader is compatible with v5.8 of avrdude.
  • For Digilent pic32 boards, it is highly recommended to download the Digilent official bootloader from the Digilent website at http://www.digilentinc.com/.
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Running StickOS BASIC on a chipKIT board

Have you ever wished you could examine and manipulate the pins and peripherals of your MCU *interactively*, while it was live and connected to your embedded circuit, rather than using just “reset and run” debugging? If so, StickOS BASIC may be for you! With StickOS BASIC, you can log in to your MCU using nothing but a terminal emulator, and then take full control of the MCU from a command-line, just as if you had an In-Circuit Emulator. StickOS can run either in “slave” mode, tethered to and controlled by a host computer as a glorified intelligent I/O port, or it can run in “master” mode, programmed in BASIC, interactively debugged, and even configured to autorun its BASIC program autonomously. In StickOS BASIC, it is trivial to examine and manipulate I/O pins. I/O pins can be configured for digital input or output, analog input or output, servo output, or frequency output. Once a pin is configured, it can be bound to a BASIC variable, and from then on, examining or manipulating the pin is as simple as examining or manipulating the bound variable. For example, to configure pin 3 for servo output, bind it to the variable “motor1”, and then set it up for a 1ms (1000us) PWM pulse width is as easy as (interactively, at the command-line, or in a program):
    > dim motor1 as pin 3 for servo output
    > let motor1=1000
    > _
In StickOS BASIC, it is equally trivial to use timers, UARTs, advanced I2C or SPI peripherals, as well as HD44780-compatible LCDs and simple scanned keypads. And most importantly, it can all be done interactively — no more guessing what your MCU is up to! The StickOS debugger supports command-line program interruption, breakpoints, assertions, watchpoints, live variable (and pin) manipulation and examination, execution tracing and single-stepping, sampling profiling, and even edit-and-continue! When you’re ready to move up, you can then port your BASIC program to C using the MPLAB X StickOS Skeleton project, and take advantage of all the same pin/peripheral configuration, flash manipulation, etc., used by StickOS BASIC. A detailed introduction to StickOS on the chipKIT boards is here: http://www.cpustick.com/chipkit.htm An overview of the StickOS BASIC language features is in the Quick Reference guide, here: http://www.cpustick.com/downloads/quickref.v1.82.pdf More information and downloads for the chipKIT boards are available here: http://www.cpustick.com/downloads.htm
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Using USB

The PIC32MX3xx series parts do not have a USB controller. The other PIC32 series (i.e. PIC32MX4xx/5xx/6xx/7xx) all have a USB controller. The Uno32 uses a PIC32MX320F128H and therefore does not have a USB controller. The Uno32 and Max32 have standard FTDI serial to USB interface chips (FT232R) to keep consistent with the Arduino way of interfacing. However, it is also nice to be able to use the built in USB port. Many other PIC32 boards have this USB port brought out to a standard connector such as the Microchip USB Starter Kit and the Digilent Cerebot 32MX4 and Cerebot 32MX7. The latest version of HardwareSerial.cpp now supports the first serial port (Serial.begin(), Serial.print() etc) can be reconfigured to use the USB port instead. In order to take full advantage of this, first you have to program the board with the USB bootloader, then use the appropriate board setting in the BOARDS menu. If you are using a custom board in the boards file you can just add the following to your board description: custom_pic32.compiler.define=-D_USE_USB_FOR_SERIAL_ When using the USB for Serial, UART1 becomes Serial0 Serial1 etc, are still there normal configurations Serial.begin(baudrate); //The baudrate is ignored, when doing real USB, there is no baudrate. Receive is interrupt driven and behaves EXACTLY like regular Serial. NO CODE CHANGES REQUIRED. If you want to see how this is done, look at HardwareSerial.h and HardwareSerial.cpp, the actual usb code is in HardwareSerial_cdcacm.c and HardwareSerial_usb.c. The USB code was written by Rich T (http://www.cpustick.com/) More documentation will be provided on how to do this soon. (Created 7/3/2011)
VN:F [1.9.22_1171]
Rating: 9.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

Header Files

Header files listed in alphabetical order. Files are denoted as either (AVR) or (PIC32) specific, if they apply to both platforms they are marked as (AVR|PIC32). For headers that are marked (AVR|PIC32) they can be either “generic” or “ported”. Generic files will work on either platform without modification where ported files are different for AVR or PIC32.

avr/interrupt.h (AVR)

avr/io.h (AVR)

avr/progmem.h (AVR)

avr/pgmspace.h (AVR)

Tools to access program space of the AVR processor, not needed on PIC32, but some macros can be used in its place to make AVR code run on a PIC32. <source>
  1. if defined(__PIC32MX__)
   // neither PROGMEM or PSTR are needed for PIC32, just define them as null
   #define PROGMEM
   #define PSTR(s) (s)
 
   #define pgm_read_byte(x)	        (*((char *)x))
   #define pgm_read_byte_near(x)	(*((char *)x))
   #define pgm_read_byte_far(x)	(*((char *)x))
   #define pgm_read_word(x)    	(*((short *)x))
   #define pgm_read_word_near(x)	(*((short *)x))
   #define pgm_read_workd_far(x)	(*((short *)x))

   #define	prog_void	 const void
   #define	prog_char	 const char
   #define	prog_uchar	 const unsigned char
   #define	prog_int8_t	 const int8_t
   #define	prog_uint8_t	const uint8_t
   #define	prog_int16_t	const int16_t
   #define	prog_uint16_t	const uint16_t
   #define	prog_int32_t	const int32_t
   #define	prog_uint32_t	const uint32_t
   #define	prog_int64_t	const int64_t
   #define	prog_uint64_t	const uint64_t
  1. else
  2. include <avr/pgmspace.h>
  3. endif
</source>

coffee.h

The start of all good programming sessions.

cpudefs.h

Ethernet/Ethernet.h

Ethernet/Client.h

i2cmaster.h

plib.h (PIC32)

Contains type definitions for PIC32 registers.

SdFat.h

Servo.h (?)

SPI.h (AVR|PIC32) ported

Library to provide SPI communications.

stdint.h (AVR|PIC32) ported

stdio.h

wire.h (?)

wiring.h (?)

WProgram.h (?)

 
VN:F [1.9.22_1171]
Rating: 7.0/10 (3 votes cast)
VN:F [1.9.22_1171]
Rating: -1 (from 1 vote)