Dear all,
In the company where I work we use the we use that microcontroller for more than one circuit. Now we need to generate a pulse and we decided to work with PWM.
I looked to the AN3511 doc and I seen the source related.
I changed many times the sources, I can see the modulation in the pins 40, 41 (PWM1, PWM3) but nothing in the pin 43 (PWM7). Really I'm worried that I'll never see the pulse out of that pin...
Follow the source:
in mainfunction:
..
/* configure PWM */
PWMInit(SCALEDCLOCK,208);
/* show the output for selected channel */
/* all PWM channels are @ 30 Hz */
/* even channels through LEDs in EVB */ /* duty cycle */
PWMStart(3,200,100,LOWPOL,LEFTALIGNED); /* 50 % */
PWMStart(7,200,100,LOWPOL,LEFTALIGNED); /* 50 % */
..
/**********************************FUNCTIONS**********************************/
/*****************************************************************************
* PWMInit: Set channels ready to show a PWM output in pins *
* *
* Parameters: u8Clock: clock or sclaled clock source *
* u8ScaledValue: scaled value to use *
* *
* Return : none. *
*****************************************************************************/
void PWMInit(uint8 u8Clock, uint8 u8ScaledValue)
{
#ifdef MAI
// comment parts
/* associate odd PWM channels to a pin */
MCF_GPIO_PTDPAR = 0
| MCF_GPIO_PTDPAR_PTDPAR0 /* PWM channel 1 */
| MCF_GPIO_PTDPAR_PTDPAR1 /* PWM channel 3 */
| MCF_GPIO_PTDPAR_PTDPAR2 /* PWM channel 5 */
| MCF_GPIO_PTDPAR_PTDPAR3; /* PWM channel 7 */
/* associate even PWM channels to a pin */
MCF_GPIO_PTCPAR = 0
| MCF_GPIO_PTCPAR_TIN0_PWM0 /* PWM channel 0 */
| MCF_GPIO_PTCPAR_TIN1_PWM2 /* PWM channel 2 */
| MCF_GPIO_PTCPAR_TIN2_PWM4 /* PWM channel 4 */
| MCF_GPIO_PTCPAR_TIN3_PWM6;/* PWM channel 6 */
#endif
/* associate even PWM channels to a pin */
// Configure pins for PWM use
MCF_GPIO_PTAPAR = 0
| MCF_GPIO_PTAPAR_PTAPAR0(3) // PWM1 this work fine
| MCF_GPIO_PTAPAR_PTAPAR1(3)
| MCF_GPIO_PTAPAR_PTAPAR2(0)
| MCF_GPIO_PTAPAR_PTAPAR3(3); // PWM7 this is my pin
/* associate every channel with a source clock */
/* A, or B, SA or SB depending the channel */
MCF_PWM_PWMCLK = u8Clock;
/* change the prescaler of the clock source for every channel */
MCF_PWM_PWMPRCLK = 0
| MCF_PWM_PWMPRCLK_PCKA(BUSCLK_16)
| MCF_PWM_PWMPRCLK_PCKB(BUSCLK_16);
/* set scaled value for scaled clock, if are activated */
MCF_PWM_PWMSCLA = u8ScaledValue;
MCF_PWM_PWMSCLB = u8ScaledValue;
MCF_PWM_PWMCTL = 0;
return;
}
/*****************************************************************************
* PWMStart: Start selected PWM channel pin with selected duty and polarity *
* *
* Parameters: u8Channel: PWM channel to start *
* u8Period: PWM channel period *
* u8Duty: PWM channel duty cycle *
* u8Polarity: PWM channel polarity *
* u8AlignmentWM channel alignment *
* *
* Return : none. *
*****************************************************************************/
void PWMStart(uint8 u8Channel, uint8 u8Period, uint8 u8Duty,
uint8 u8Polarity, uint8 u8Alignment)
{
// MCF_PWM_PWME &= ~(1<<u8Channel); really is need ?
MCF_PWM_PWMPER(u8Channel) = u8Period; /* set PWM period */
MCF_PWM_PWMDTY(u8Channel) = u8Duty; /* set PWM duty cycle */
MCF_PWM_PWMPOL |= (u8Polarity<<u8Channel); /* set PWM polarity */
MCF_PWM_PWMCAE |= (u8Alignment<<u8Channel); /* set PWM alignment */
/* show the PWM channel in its respective pin*/
MCF_PWM_PWME |= (1<<u8Channel);
return;
}
thank you in advance.
// Andrea.
Andrea
What is the define for SCALEDCLOCK?
The pin configuration is standard for each pin so there doesn't seem to be any problem in that area, but the PWM clocking may not be correct.
PWMCLK needs to be set for each PWM channel (0..7) to configure where each takes its clock from (A or SA for channels 0, 1, 4 and 5 - B or SB clock for channels 2, 3, 6 and 7).
As is seen, the clock source control for PWM 3 is different to PWM 0 and 1; since you have no problems with 0 and 1 but do with 3 this may be an indication.
Regards
Mark
Dear Mark,
thank you for your answer,
/* PWM Scaled */
#define SCALEDCLOCK 0xFF
#define CLOCK 0x00
this is the define for scaled clock, did you suggest to use CLOCK instead ?
Best regards,
// Andrea.
Andrea
It looks as though all channels are using the divided clock source. I don't see any obvious problems.
What I have done is attach an SREC (project) for the M5213 which uses PWM1, 3 and 7 on the TA port - they are all set to about 1k and 50%. I set the RAM size to 16k and it doesn't use any Flash about 128k so it should run on your board with the M5211 too. Since I don't know what speed your device has, I set it up for 32MHz PLL from 8MHz clock so it should be able to run on any type too - so you can halt the operation with debugger and check all register setups, I also disabled the watchdog operation.
On my M5213EVB all outputs work nornally. If it works on your board (all 3 PWM outputs generate the signal) you can be sure that it i not a HW problem. You should be able to check the content of the pin set up (PTAPAR = 0xcf as reference) and the setup of the PWM registers to see what the SW problem could be. Note that this configuration uses a prescaler of 128 but then a scaler of only 1 (therefore the higher frequency).
I set it up using the PWM setup interface in the uTasker project which looks like this (this won't help a great deal since it is a higher level of abstraction) but the code is otherwise available in that project:
PWM_INTERRUPT_SETUP timer_setup;timer_setup.int_type = PWM_INTERRUPT; // PWM setup typetimer_setup.pwm_reference = 1; // PWM1timer_setup.pwm_mode = (PWM_PRESCALER_128 | PWM_SCALED_CLOCK_INPUT | PWM_POLARITY); // modetimer_setup.pwm_frequency = (unsigned char)(PWM_US_DELAY(PWM_FREQUENCY_VALUE(960 * 128))); // frequency 960Hztimer_setup.pwm_value = (unsigned char)_PWM_PERCENT(50, timer_setup.pwm_frequency); // 50%fnConfigureInterrupt((void *)&timer_setup); // configure and start PWM1timer_setup.pwm_reference = 3; // same setup for PWM3fnConfigureInterrupt((void *)&timer_setup); // configure and start PWM3timer_setup.pwm_reference = 7; // same setup for PWM7fnConfigureInterrupt((void *)&timer_setup); // configure and start PWM7
Regards
Mark
Dear Mark,
now I play with PWMCLK and Prescaled clock to understand why 2 channel's work and one no.
I see your code and I see something about interrupt but I don't use is now, just for a timer in temporise function.
I need to use interrupt for PWM too ?.
I can't load SREC in my project now, I use m68k under linux and load the binary output from objcopy through bdm device.
// Andrea.
Andrea
fnConfigureInterrupt() is used for setting up various peripherals (like timers, ADC, QSPI, edge ports etc.) which usually/often use interrupts - this is also used for PWM configuration without interrupt (some devices may be able to generate optional interrupts), so interrupts do not need to be used and are not used in this case.
If you can load binary files you can also use objcopy to convert the SREC to binary and then load it to your board. If you can debug, you can then check the content of PTA and PWM registers to see whether you can see a difference which explains why your code is not generating output on all channels.
In case you don't manage this, the following are the most register settings for the tested case:
PTAPAR = 0xcf (configures the 3 PWM pins to PWM mode)
PWME = 0x8a
PWMPOL = 0x8a
PWMCLK = 0x8a
PWMPRCLK = 0x77
PWMSCLA = 0x01
PWMSCLB = 0x01
PWMPER1 = 0x40
PWMPER3= 0x40
PWMPER7 = 0x40
PWMDTY1 = 0x20
PWMDTY3= 0x20
PWMDTY7= 0x20
When these are manually set and the PWME as last (to enable) you should also see the corresponding outputs.
Regards
Mark
Dear Mark,
after have very long played now the code seems to work, thank you for your time, but I need
another tips, how to synchronize PWM7 with PWM1, in other words I need the pulse from PWM1 then 30us start a
pulse from PWM7.
After some test I can't have the channels PWM1 and PWM7 synchronize beacuse they have different source
of clock this is true ?.
Best regards,
// Andrea.
Andrea
All PWM channels are driven from the internal clock and - when both clock dividers are equal - all clocks are in fact the same.
If all channels are activated at the same time [PWME = 0x8a in your case, written when the original value was 0x00] all outputs are synchronous.
If you want to have a specified delay from channel 1 to channel 7 this is possible by writing:
PWME = 0x8a;
PWMCNT7 = 0x05; // exampleof priming a count value in one channel
It is not possible to prime the count values before enabling the PWM output since the conter is held at 0x00 when the channel is not enabled but it is possible to change the value immediately after the PWM counters are activated (to avoid the possibility of the being unexpected counts taking place between the two instructions this can be performed with interrupts disabled).
The actual value to be written to the count value depends on the delay required and its resolution will depend on the value of PWMPER7 - when PWMPER7 is 0xff (it will usually be smaller) it would allow 1/256 resolution of the clock period. Thsi may or may not allow you to achieve the delay that you want with the required accuracy.
Regards
Mark
Dear Mark,
did you suggest to use output compare for this purpose ?
// Andrea.
Andrea
The PWM module has no output compare function (just period and duty compare).
I suggested modifying the counter value to introduce a controller offset between the PWM channels.
To generate single shot pulses other timer modules may be more suitable.
regards
Mark