Startup Without Peripheral Libraries – dsPIC33CK

Startup without peripheral libraries series

The dsPIC is one of the easier MCUs in this series to get running.  Much like the PIC32MK, the default startup scripts are hidden in the compiler directory and included by default.  Generally, they do not need to be touched.  Almost all of the register definitions are included the standard device header file xc.h.  This provides the register values both as a full register variable and as a bit fields.  The compiler contains some built in functions that are required to switch clocks.  These functions are documented in the compiler reference.

This example uses the internal 8MHz fast oscillator and PLL to run the system clock at 180MHz.  I then set up Timer 1 and interrupts.

The steps are as follows:

  1. Set up the proper configuration bits for the clock and features being used – MPLAB X contains a gui to help.  The PLL cannot be changed while being actively used for the clock.  So, I start the system up just using the FRC oscillator, then configure the PLL, then switch the clock to the PLL.
  2. Next, I configure Timer1 and enable interrupts
  3. The sysInit function is called before the main loop
#include <xc.h>


#pragma config FNOSC = FRC
#pragma config IESO = OFF
#pragma config POSCMD = NONE
#pragma config OSCIOFNC = ON
#pragma config FCKSM = CSECMD
#pragma config PLLKEN = ON
#pragma config WINDIS = OFF
#pragma config FWDTEN = ON_SW
#pragma config ICS = PGD1
#pragma config JTAGEN = OFF
#pragma config DMTDIS = OFF

void sysInit (void)
{
   //-----------------------------------------------------
   // Configure clock - 360 MHZ -> 90 MHz fclk
   //-----------------------------------------------------
   CLKDIVbits.FRCDIV = 0;
   CLKDIVbits.PLLPRE = 1;
   PLLFBDbits.PLLFBDIV = 190;
   PLLDIVbits.POST1DIV = 4;
   PLLDIVbits.POST2DIV = 1;

   // Start clock switch to PLL
   __builtin_write_OSCCONH(0x01);
   __builtin_write_OSCCONL(OSCCON | 0x01);
   // wait for clock switch
   while (OSCCONbits.OSWEN != 0);
   // Wait for PLL to lock
   while (OSCCONbits.LOCK != 1);

   //-----------------------------------------------------
   // Timer 1 - use FRC @ 8MHz -> 1ms tick
   //-----------------------------------------------------
   T1CONbits.TON = 0;
   T1CONbits.TECS = 3; // use FRC
   T1CONbits.TCS = 1; // use TECS clock selection
   T1CONbits.TCKPS = 1; // /8
   TMR1 = 0;
   PR1 = 1000;
   IPC0bits.T1IP = 2; // priority 2
   IFS0bits.T1IF = 0; // clear timer1 int flag
   IEC0bits.T1IE = 1; // enable timer1 int
   T1CONbits.TON = 1; // turn on timer1

   INTCON2bits.GIE = 1; // global interrupt enable

}