Table of Contents

PIC24F

The PIC24F is a versital microprocessor with lots of nice peripherals such as DAC, multiple UARTS and PWM. I used it for the LTP Lidar.

Documentation Notes

The PIC24 from Microchip has two types of documentation. The first is the device specific datasheet and the second is a general set of documentation for the PIC24 family of chips. Sometimes, especially when looking for a detailed explanation of how a peripheral works, the general family documentation is more helpful.

General

Every project has <xc.h> includes. In it there are a bunch of ifdefs that include your device specific header. Search for it and you will find it!

There used to be compiler libraries for the peripherals of the PIC24 but they have become depracated 1). Instead perhiphal functions are generated by MCC (MPLAB Code Configurator). Here is great website with info on I2C and the MCC I2C commands link.

Delay

You can use the delay functions of the xc16 compiler but you have to define the following before including the right header file. It is this:

#define FOSC    (32000000ULL)
#define FCY     (FOSC/2)
 
#include <libpic30.h>

Then you can use:

__delay_us()
__delay_ms()

PWM

Getting PWM to work on the PIC24 is tricky. We make use of the MCCP/SCCP peripheral that has a tremendous amount of functionality which also makes it tricky to use.

Capture/Compare/PWM/Timer Modules (MCCP and SCCP)

The PIC24 has a periphal group called the MCCP and SCCP. The data sheet here has specific register information link.

This document gives a detailed description of this peripheral group link.

Go to Section 64.7 of the PIC24 Family document.

To make a simple PWM signal use the MCCP module in output compare with Dual Edge Mode. The Dual Edge Mode allows us to reset the OC (output compare) pin, set the pulse width and along with the 16 bit timer length.

We use dual edge buffered MCCP1 mode to generate our PWM signal. The buffered part is that so that we can update the PWM values while the PWM is running, and the peripheral takes care of loading the next values at the end of a cycle.

SPI

I learned a lot about SPI in the LTP Lidar project because it didn't work right off the bat. It is not that complicated and the easy setup in MCC (MPLAB Code Configurator) gives you all the stuff you need. You just use the MSSP1_SPI_Exchange8bit(address) function to read and write data.

Some notes:

UART

To use the UART you can set it up on the the MCC (MPLAB Code Configurator).

Check the box that diverts printf to the UART. This allows us to use printf which can print out strings and is easier to use than the one byte function we get from the configurator.

To use printf we need to #include <stdio.h>

Read about the xc16 printf implmementation link.

To use the MCC generated UARTx_GetStatus() function you have to AND the enum! They are flags and not unique values. So tricky!!!

The PIC24F only has a 4 byte serial buffer. Getting the pic to do a serial read requires me to get out of my comfort zone and work with interrupts. I need to set up an interrupt every time there is a byte and add it to my running buffer. This really shouldn't be that hard and should make the code work pretty easily.

I need to set the URXISEL<1:0> to 00 which will generate an interrupt whenever there is 1 or more characters in the buffer.

There is information about the UART in both the PIC24F Family Reference manual and also the PIC24FV16KM204 Family Reference Manual link.

This is all forcing me to learn about interrupt functions. Reading about it in Chapter 7 of the C30 Compiler User's Guide link.

I think I can use a macro for the UART Rx interrupt. See Section 8.3.4 in the Interrupts manual link.

Im trying to find the correct preproccessor macro for the ISR of the UARTRx interrupt. In doing so, I read this in the C Compiler Manual:

If an interrupt handler does not require any of the optional parameters of the
interrupt attribute, then a simplified syntax may be used. The
following macros are defined in the device-specific header files:

I found out I can just use the autogenerated UART handler instead of writing my own ISR. Which may be worse than writing my own ISR because there is a lot of bullshit with it.