Super dsPIC30F4011 example program

This is an example program for the dsPIC30F4011. It covers digital i/o, analog input, PWM output, UART Tx/Rx, timer interrupts. I’m using this as the starting point for a variety of example programs on my Robotics 3.1 module blog, http://roboted.wordpress.com.

//
// This is a dsPIC30F4011 demo program featuring digital i/o,
// analog input, PWM output, serial Tx/Rx, timer interrupt.
//
// It does the following:
//
//  1. 1Hz LED flash on RD0 and RD1 for 4 seconds
//  2. Smoothly pulse an LED at 0.5 via PWM
//  3. Sample the 9 analog inputs every 2 seconds
//  4. Transmit the measured samples via UART
//  5. Transmit the state of digital inputs RC13-15 via UART
//  6. Checks if a '1' or '0' was received via UART & turns RD0-1 on/off
//  7. All the while, flash an LED at 4Hz using a timer interrupt
//
// written by Ted Burke - last updated 4-11-2011
//
// PLEASE NOTE:
//
// The stdio.h functions, such as printf, require a 'heap' to be
// allocqated (basically, a heap is a block of memory reserved for
// data storage). I set my heap size to 512 in MPLAB's project
// settings dialog box, as follows:
//
//     Project->Build Options...->Project->MPLAB LINK30->Heap size = 512
//

#include <libpic30.h>
#include <p30f4011.h>
#include <stdio.h>
#include <math.h>

// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

// Function prototypes
void configure_pins();
unsigned int read_analog_channel(int n);

// Function prototype for Timer 1 interrupt service routine
void __attribute__((__interrupt__, __auto_psv__)) _T1Interrupt(void);

int main()
{
	// variable declarations
	int n;          // Counter variable
	double omega;   // Phase angle variable
	int v[9];       // Array to store analog input voltages
	char c;         // Character to receive text via UART

	// Set up digital i/o, analog input, PWM, UART and interrupt
	configure_pins();

	// Flash LEDs on RD0 and RD1 at 1Hz for 4 seconds
	for (n=0 ; n<4 ; ++n)
	{
		_LATD0 = 0; _LATD1 = 0;
		__delay32(15000000);
		_LATD0 = 1; _LATD1 = 1;
		__delay32(15000000);
	}

	// Smoothly pulse an LED at 0.5Hz using the PWM channels.
	// Sample the 9 analog inputs every 2 seconds and send the
	// readings to the PC via the UART.
	omega = 0;
	while(1)
	{
		// Update phase of LED brightness cycle
		omega = omega + 0.01;
		if (omega >= 1)
		{
			omega -= 1;

			// At the end of each LED pulse cycle, read the
			// 9 analog inputs.
			for (n=0 ; n<9 ; ++n) v[n] = read_analog_channel(n);

			// Transmit the measured voltages to the PC via the UART.
			// This message is about 51 characters long, so it should take
			// about 13.281ms to transmit at 38400 baud.
			printf("AN0-8=");
			for (n=0 ; n<9 ; ++n) printf("%04d,", v[n]);

			// Print the state of digital inputs RC13-15
			// This message is about 15 characters long, so it should take
			// about 3.906ms to transmit at 38400 baud.
			printf(" RC13-15=%d,%d,%d\r\n", _RC13, _RC14, _RC15);
		}

		// 20ms delay
		__delay32(600000);

		// Update the duty cycles on PWM channels 1 and 2 to
		// change the 'brightness' of the LEDs.
		PDC1 = PTPER + (PTPER * sin(2 * 3.14159265 * omega));
		PDC2 = PTPER - (PTPER * sin(2 * 3.14159265 * omega));

		// Check if any characters were received via UART
		if (U1STAbits.URXDA == 1)
		{
			// If a '1' or '0' were received, set RD0 and RD1
			c = U1RXREG;
			if (c == '1') {_LATD0 = 1; _LATD1 = 1;}
			if (c == '0') {_LATD0 = 0; _LATD1 = 0;}
		}
	}

	return 0;
}

// This function sets up digital i/o, analog input, PWM,
// UART and timer interrupt.
void configure_pins()
{
	// Configure all four port D pins (RD0, RD1, RD2, RD3)
	// as digital outputs
	LATD = 0;
	TRISD = 0b1111111111110000;

	// Configure all three port C pins (RC13, RC14, RC15)
	// as digital inputs
	TRISC = 0b1111111111111111;

	// Configure AN0-AN8 as analog inputs
	TRISB = 0x01FF;      // All 9 port B pins are inputs
	ADPCFG = 0xFE00;     // Lowest 9 PORTB pins are analog inputs
	ADCON1 = 0;          // Manually clear SAMP to end sampling, start conversion
	ADCON2 = 0;          // Voltage reference from AVDD and AVSS
	ADCON3 = 0x0005;     // Manual Sample, ADCS=5 -> Tad = 3*Tcy
	ADCON1bits.ADON = 1; // Turn ADC ON

	// Configure PWM for free running mode
	//
	//   PWM period = Tcy * prescale * PTPER = 0.33ns * 64 * PTPER
	//   PWM pulse width = (Tcy/2) * prescale * PDC
	//
	PWMCON1 = 0x00FF; // Enable all PWM pairs in complementary mode
	PTCON = 0;
	_PTCKPS = 3;      // prescale=1:64 (0=1:1, 1=1:4, 2=1:16, 3=1:64)
	PTPER = 9470;     // 20ms PWM period (15-bit period value)
	PDC1 = PTPER;     // 50% duty cycle on PWM channel 1
	PDC2 = PTPER;     // 50% duty cycle on PWM channel 2
	PDC3 = PTPER;     // 50% duty cycle on PWM channel 3
	PTMR = 0;         // Clear 15-bit PWM timer counter
	_PTEN = 1;        // Enable PWM time base

	// Configure Timer 1
	// In this example, I'm setting PR1 and TCKPS for 8Hz
	T1CON = 0;            // Clear the Timer 1 configuration
	TMR1 = 0;             // Reset Timer 1 counter
	PR1 = 14648;          // Set the Timer 1 period (max 65535)
	T1CONbits.TCS = 0;    // Select internal clock (Fosc/4)
	T1CONbits.TCKPS = 3;  // Prescaler (0=1:1, 1=1:8, 2=1:64, 3=1:256)
	_T1IP = 1;            // Set the Timer 1 interrupt priority
	_T1IF = 0;            // Clear the Timer 1 interrupt flag
	_T1IE = 1;            // Enable Timer 1 interrupt
	T1CONbits.TON = 1;    // Turn on Timer 1

	// Set up UART
	// Default is 8 data bits, 1 stop bit, no parity bit
	U1BRG = 48;            // 38400 baud @ 30 MIPS
	U1MODEbits.UARTEN = 1; // Enable UART
	U1STAbits.UTXISEL = 1; // interrupt when TX buffer is empty
	U1STAbits.UTXEN = 1;   // Enable TX
}

// This function reads a single sample from the specified
// analog input. It should take less than 2.5us if the chip
// is running at about 30 MIPS.
// Because the dsPIC30F4011 has a 10-bit ADC, the value
// returned will be between 0 and 1023.
unsigned int read_analog_channel(int channel)
{
	ADCHS = channel;          // Select the requested channel
	ADCON1bits.SAMP = 1;      // Start sampling
	__delay32(30);            // 1us delay @ 30 MIPS
	ADCON1bits.SAMP = 0;      // Start Converting
	while (!ADCON1bits.DONE); // Should take 12 * Tad = 1.2us
	return ADCBUF0;
}

// Timer 1 interrupt service routine
void __attribute__((__interrupt__, __auto_psv__)) _T1Interrupt(void)
{
	// Clear Timer 1 interrupt flag
	_T1IF = 0;

	// Toggle LEDs on RD2 and RD3
	if ( _LATD2) {_LATD2 = 0; _LATD3 = 1; }
	else { _LATD2 = 1; _LATD3 = 0; }
}

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

4 Responses to Super dsPIC30F4011 example program

  1. sheilamae says:

    could you also send us sample program of DSPIC30F4011 for improved input current distortion? thank you.

    • batchloaf says:

      Hi Sheila Mae,

      Sorry, but I’m not really sure what you’re asking because “improved input current distortion” could mean a lot of different things. What exactly are you trying to do? Are you having a specific problem with my sample code?

      If the problem that you’re having is that your supply voltage is affected when certain PIC output pins switch on and off (due to changing current demand), then try placing a large capacitor between the PIC’s VDD and VSS pins. It might help a bit. By large, I suppose I’m thinking about 100uF or bigger. Is that the problem you’re having? If so, it’s a circuit design issue more than a software issue. I’m not saying there’s nothing you can do in code, but the problem originates primarily in the circuit rather than in the code.

      Regards,
      Ted

  2. Jorge says:

    Hello, I just wanted to say that your website is about the best dsPIC and XC16 reference that I have found so far. Through your examples, I was able to learn all the basics of dspic and now I’m using it for my bachelor research project.

    Thank you!
    Jorge

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s