Motor PWM example for the dsPIC30F4011

The following program is an example of PWM output from the six motor PWM pins on the dsPIC30F4011. The duty cycle of each of the three PWM channels is controlled by an analog input. The duty cycle of each channel should vary between 0-100%. All three PWM channels are configured in complementary mode – i.e. the two pins in each channel are always at opposite logic levels. The PWM period is supposed to be 20ms, but I still have to confirm on a scope that this is actually the case.

// This program is an example of the motor PWM facility on the
// dsPIC30F4011.
// Written by Ted Burke - last updated 4-12-2010

#include <libpic30.h>
#include <p30f4011.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);

int main()
	int voltage;

	// Set up which pins are which

		// Analog input 0 controls PWM 1 duty cycle.
		voltage = read_analog_channel(0);
		PDC1 = (int)((voltage / 1023.0) * 2 * PTPER);

		// Analog input 1 controls PWM 2 duty cycle.
		voltage = read_analog_channel(1);
		PDC2 = (int)((voltage / 1023.0) * 2 * PTPER);

		// Analog input 2 controls PWM 3 duty cycle.
		voltage = read_analog_channel(2);
		PDC3 = (int)((voltage / 1023.0) * 2 * PTPER);

	return 0;

void configure_pins()
	// Configure RD0 as a digital output
	LATD = 0;
	TRISD = 0b11111110;

	// Configure analog inputs
	TRISB = 0x01FF;      // Port B all inputs
	ADPCFG = 0xFF00;     // Lowest 8 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 = 0.1us
	ADCON1bits.ADON = 1; // Turn ADC ON

	// Configure PWM for free running mode
	// PWM period = Tcy * prescale * PTPER = 0.33ns * 64 * 9470 = 20ms
	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 = 0;         // 0% duty cycle on channel 1 (max is 65536)
	PDC2 = 0;         // 0% duty cycle on channel 2 (max is 65536)
	PDC3 = 0;         // 0% duty cycle on channel 3 (max is 65536)
	PTMR = 0;         // Clear 15-bit PWM timer counter
	_PTEN = 1;        // Enable PWM time base

// 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.
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;
This entry was posted in Uncategorized. Bookmark the permalink.

13 Responses to Motor PWM example for the dsPIC30F4011

  1. Mo says:

    Do you know how can I generate phase shifted PWM with dspic30f4011?


    • batchloaf says:

      Hi Mo,

      I suggest using the output compare module. It allows you to specify the start and stop time of each pulse on four separate channels. You can find some examples on my Robotics blog, including the following:

      Sorry for the long delay in replying. This comment slipped through the net.


      • ahmed says:

        hello Ted thank you for the code but please can yougive me’ the link for dawnload this library because I tried it in c compiler and the code is dos’nt work should I use MPLAB ?

      • batchloaf says:

        Hi Ahmed,

        This code is a few years old now, so the C compiler has been updated. It should probably still work with the XC16 C compiler which you can download from However, you should change the header file “p30f4011.h” to “xc.h” which is the way you do it in XC16. It should work in MPLAB too, since that actually uses XC16 to do the compiling.


  2. John says:

    Hi Ted,
    Can you help me with the conversion? I tried to display the ADC readings onto a LCD but I cant display the correct integer reading. I used the code from cytron’s website but at most I can only display BCD. Here’s cytron’s BCD conversion: lcd_putchar(ui_decimal[uc_digit – 1] + 0x30);

    • batchloaf says:

      Hi John,

      The reason they’re adding 0x30 (equal to 48 decimal) to every character is that if you look at the table of ascii character values, you’ll see that the characters “0” to “9” are represented by ascii values from 48 to 57. See here:

      So all you need to do with your ADC value is break it down into individual digits values, add 48 to each one and send it to the LCD. I’m assuming you have the lcd_putchar function.

      Here’s a rough idea of how you might do it:

      int v; // analog voltage reading
      int d3, d2, d1, d0; // four digits
      // Read analog voltage
      v = read_analog_channel(0);
      // Calculate individual digits
      d3 = (v / 1000) % 10; // Thousands digit
      d2 = (v / 100) % 10;  // Hundreds digit
      d1 = (v / 10) % 10;   // Tens digit
      d0 = v % 10;          // Ones digit
      // Convert each character to ascii and display on LCD
      lcd_putchar(d3 + 48);
      lcd_putchar(d2 + 48);
      lcd_putchar(d1 + 48);
      lcd_putchar(d0 + 48);

      The “%” sign in those digit calculations is the modulo operator in C. It basically divides the number on the left by the number on the right, but gives you the remainder. If you haven’t come across it before, just google “C modulo operator examples”.

      Hope that helps.


  3. a says:

    sir ,

    how i get pwm …….by using matlab ……which block set i have to use …in dspic 30f4011

  4. miss2802 says:

    Hi Sir,
    I want to generate 3 PWM signals using q dsPIC30f in Matlab/Simulink, please can you help me with some documents,
    Thanks in advance

  5. Hafiz Idris says:

    Hi Ted,
    I really love and inspire by your job, I need your help Ted. I am really new for this kind of programming and microcontroller and I need to made PWM by using DSPIC30F4011 with 0.4 duty cycle and 20KHz frequency , and I would appreciate and grateful if you can write me a very simple but complete code for that spec.
    Thank you Ted

    • batchloaf says:

      Hi Hafiz,

      Please try this out:

      // This dsPIC30F4011 program generates 20kHz PWM with 40% duty cycle
      // Written by Ted Burke - last updated 19-4-2017
      #include <xc.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
      int main()
          // Configure PWM for free running mode
          PWMCON1 = 0x00FF; // Enable all PWM pairs in complementary mode
          _PTCKPS = 0;      // prescale=1:1 (0=1:1, 1=1:4, 2=1:16, 3=1:64)
          PTPER = 1500;     // 50us PWM period for 20kHz PWM
          PDC1 = 1200;      // 40% duty cycle on PWM channel 1 (pin 37)
          _PTEN = 1;        // Enable PWM time base
              // Nothing here because PWM module does all the work!

      The output should be 20 kHz PWM with a 40% duty cycle on PWM1H (pin 37). Let me know if it works or not.


  6. Suman Kumar says:

    Hello Ted, This is Suman from India Bangalore. I am learning dspic33f, but i am not able to configure oscillator and pwm configuration for dsPIC33FJ16GS504. I had gone through basics of pic16f, but dspic i am not able at all.
    I am using this microcontroller for pure sine wave inverter project. Right now i am in initial stage , so i am only trying single pwm with adjustable duty cycle on adc read.

    Please help me to generate 100 khz pwm with adjustable duty. If you can send me some document on dspic33f configuration and code i will be very grateful.

    Thank you

    • ashvin pambhar says:

      i want to generate PWM signal by using dsPIC33FJ16GS504 controller if you have any c code related to that or any kind of information related to that play share with me.
      thank you

Leave a Reply

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

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

Google photo

You are commenting using your Google 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 )

Connecting to %s