CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

DSPIC30F2020 PWM problem
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

DSPIC30F2020 PWM problem
PostPosted: Mon Feb 03, 2014 12:39 pm     Reply with quote

// Programming skills: beginner
// Compiler: 4.105

Currently I'm trying to get pwm working on a 30F2020 which isn't as easy as I expected it to be. Below my test code:
Code:

#include<30F2020.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES FRC_PLL                  //Internal Fast RC oscillator with PLL
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES FRANGE_HIGH              //Frequency Range for FRC 14.55MHz
#FUSES NOOSCIO                  //OSC2 is clock output
#FUSES NOPR                     //Pimary oscillaotr disabled
#FUSES NOWINDIS                 //Watch Dog Timer in Window mode
#FUSES WPRES128                 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES PUT128                   //Power On Reset Timer value 128ms
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES ICSP1                    //ICD uses PGC1/PGD1 pins

#use delay(clock=58200000)       // =14.55MHZ *4 (interne rc oscillator)

void main()
{
   setup_compare(1,COMPARE_PWM | COMPARE_TIMER2 );
   setup_timer2(TMR_INTERNAL | TMR_DIV_BY_8,0 );
   setup_compare(2,COMPARE_PWM | COMPARE_TIMER3 );
   setup_timer3(TMR_INTERNAL | TMR_DIV_BY_8,0 );
   
   setup_spi( FALSE );
   setup_wdt(WDT_ON);



   while (true)
   {
   output_high(PIN_e4);
   Delay_ms(10);
   output_low(PIN_e4);
   Delay_ms(10);
   set_pwm_duty(1,231);
   set_pwm_duty(2,231);
   }
}


Pin E4 is for testing purposes and I see a square wave on this pin, indicating that the PIC is running.

I'm not sure on which pin the PWM signal should occur. In an example I found here for another controller pwm1 should be on OC1 but in my case it is constant 5V.

The goal is to get a phase shift controller so I want to be able to adjust the phase shift between the two pwm channels. Sadly there isn't much information in the manual/help file.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Mon Feb 03, 2014 3:32 pm     Reply with quote

CCS assumes that you have CCS manual, microchip manual and appropriate header files to hand. You often need all three.

Microchip manual gives E0/1 for PWM1 outputs, E2/3 for PWM2.

You've not set a period for either timer.

Hope this helps.

Mike
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 8:02 am     Reply with quote

Thanks for your comment Mike. You are totally right, I forgot to set a period for each timer, quite dumb Embarassed
I now have set it to a frequency of about 28.5 kHz and I have a PWM signal at F6 and D0.

The E0 up to E3 are for the power PWM I believe.

Anyway, I now have two pwm signals. I tried to phase shift them by starting them a few microseconds after each other but that doesn't work. So the next problem is how to create a phase shift.
In the microchip manual I have read about a phase shift register which can be set . Perhaps I need to figure out how I can set registers with CCS.

I have looked in the compiler help and at a manual I found on Internet but the: setup_compare(1,COMPARE_PWM | COMPARE_TIMER2 ); command isn't described in both of them.
The header file is the 30f2020.h file I assume? I don't get much wiser reading that file neither.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 8:33 am     Reply with quote

I don't use your PIC, so I'm guessing a little.

You're using two timers, for each PWM.
As I understand it the PWMs are driven by their timer.
The PWMs are, in effect, sync'd to the timers.
To phase shift the PWM's you could start one timer then the other after a delay.
The power PWM's (motor PWM's) are designed for a more controlled phase shift.

You could tweak the PWM phase by incrementing one timer's period, let it overflow once, then decrementing that timer's period back to its previous value.

Mike
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 8:57 am     Reply with quote

Hi Mike,

I tried to set the one pwm duty after the other but setting the timer with a delay sounds quite logic. Will give it a try.

I just was reading the datasheet and came to the conclusion that the power-pwm have a phase shift function. So that is probably the correct way to go I guess.
Haven't used power pwm before so that is all new to me. But always eager to learn something new!
Ttelmah



Joined: 11 Mar 2010
Posts: 19457

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 9:20 am     Reply with quote

The duty won't change the phase.
The duty only updates when the PWM next resets. This is done so that multiple PWM's will always update together. Mike's comment is spot on.

Basically reset one timer, wait for the time required for your phases, then reset the other.

Best Wishes
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 10:08 am     Reply with quote

I have tried Mike his option to delay the timer and that works indeed. But as mentioned before, the power pwm should have a function for setting the phase. So I want to try that option too. But sadly the manual doens't describe anything about it.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 10:52 am     Reply with quote

Quote:
The header file is the 30f2020.h file I assume? I don't get much wiser reading that file neither.

So I want to try that option too. But sadly the manual doens't describe anything about it.


Sorry, meant to say this before. The .h file gives you all the allowed options etc. for the compiler with the correct syntax.
In general the options follow the microchip format, so you can usually work out what each one is supposed to do.
With very recent chips there may be bugs or CCS has not got round to it. Either way you will have to write directly to the registers.

Mike
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 11:01 am     Reply with quote

Mike,

For example: _bif void set_pwm_duty(unsigned int8 module, unsigned int16 duty);
This is mentioned in the 30f2020.h file.
I can't find anything about phase so I may assume that there is no option to directly adjust the phase shift?
Is there an explanation around on how to set the registers directly?

According to the datasheet it is register PHASE but how to tell what phase I need?
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 11:11 am     Reply with quote

I don't have the PCD compiler.

In previous versions, writing directly to registers was done with either #bit or #byte.
Both are described in the CCS manual. I would expect there to be something similar for PCD.

Mike

EDIT

I've just had a quick look in the PCD reference manual. Both #bit and #byte are there.

Yesterday, I also had look at the power PWM module in the Microchip manual.
There's rather a large number of registers to get right. Could take some time.
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Tue Feb 04, 2014 12:53 pm     Reply with quote

I appreciate your help, thanks for that!
I will read the manual and datasheet and see how things will go. Will get back here with the results within a few days.
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Wed Feb 05, 2014 3:11 am     Reply with quote

I'm experimenting with writing registers but I'm not sure if I write the registers correctly.

On page 144 of the datasheet the power supply register map is given. I want to write into the PTCON register which has address 0400. Bit 15 enables the pwm module so I want to force this to "1".

I try this as shown in the code below:
Code:

#include<30F2020.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES FRC_PLL                  //Internal Fast RC oscillator with PLL
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES FRANGE_HIGH              //Frequency Range for FRC 14.55MHz
#FUSES NOOSCIO                  //OSC2 is clock output
#FUSES NOPR                     //Pimary oscillaotr disabled
#FUSES NOWINDIS                 //Watch Dog Timer in Window mode
#FUSES WPRES128                 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES PUT128                   //Power On Reset Timer value 128ms
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES ICSP1                    //ICD uses PGC1/PGD1 pins
#use delay(clock=58200000)      // =14.55MHZ *4 (interne rc oscillator)

#byte PTCON = 0x0400             //Declare address of register PTCON
#byte PWMCON1 = 0x0408
#byte Phase1 = 0x0410     
#byte Phase2 = 0x0424     

void main()
{
   setup_compare(1,COMPARE_PWM | COMPARE_TIMER2 );
   setup_timer2(TMR_INTERNAL | TMR_DIV_BY_1,1024 );
   setup_compare(2,COMPARE_PWM | COMPARE_TIMER3 );
   setup_timer3(TMR_INTERNAL | TMR_DIV_BY_1,1024 );
   
   setup_spi( FALSE );
   setup_wdt(WDT_ON);
   set_pwm_duty(1,0);
   set_pwm_duty(2,0);
   
   PTCON = 0x8000;               //Enable PWM module
   PWMCON1 = 0x100;
   

while (true)
   {
   set_pwm_duty(1,512);
   delay_us(150);   
   set_pwm_duty(2,512);
   Phase1 = 0x0800;
   Phase2 = 0x0800;   
   }

}


First I assign the address 0400 to the variable PTCON with:
#byte PTCON = 0x0400 //Declare address of register PTCON

Then I want to enable the PWM module by:
PTCON = 0x8000; //Enable PWM module

Is this the way to go?

Anyone which can point me in the right way?
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Feb 05, 2014 4:12 am     Reply with quote

To control just one bit of a register its safer to use the #BIT option.
Writing to a complete register runs the risk of fouling up something else within that register.
In the case you're quoting just define PTEN as PTCON bit 15.

Then:-
PTEN = 1 ; // Enables
PTEN = 0 ; // Disables

The #BYTE is best for setting registers which count or hold compare values etc.
Say the MDC or PDCx, in the case where you are wanting to set all the bits at one time.

You can check on what is being written to registers with MPLABSIM.

Might be an idea to look at what the CCS compiler does with the registers when you set up the PWM.

Also Microchip does provide some sample code in the data sheet. That could be a useful guide as to which registers to set up.
Or you may find exactly what you want on Microchips website.

Best of luck.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19457

View user's profile Send private message

PostPosted: Wed Feb 05, 2014 8:32 am     Reply with quote

The phase registers are 16bit registers, so should be set with #word, not #byte

Use getenv - safer.

#word PHASE1=getenv("SFR:PHASE1")

Then for PTEN:

#bit PTEN=getenv("BIT:PTEN")

No need to look up addresses etc...

You need to setup the PWM, to use multi-phase mode, or the phase registers will be ignored.

Best Wishes
Diode



Joined: 27 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Wed Feb 05, 2014 1:44 pm     Reply with quote

Many thanks to both of you!

I now have PWM1 working on a frequency of 26kHz and I'm able to change the PWM frequency during my program. So the begin is there.
The functions Ttelmah gave work quite easily once you know that they exist. I never knew that you could "call" the registers by name, I thought that you needed to write the actual address of the register.
It makes it all much clearer.

See if I can get PMW2 working as well and then I can try if the phase shift does work. I find it enough for today.

Thanks again and I will keep you posted about the progress.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group