PWM won't show up on pin

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

PWM won't show up on pin

Jump to solution
756 Views
mahnac
Contributor II

I would like to use PWM to change the intensity of an LED, but the PWM signal from TPM1CH3 won't show up on the pin! I'm using the Tower development board with the S08MM128. Here is the code I've loaded onto the MCU:

 

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
void initSys(void);
void initMCG(void);
void initMCU(void);
void Pwm1_Init(void);
void Pwm1_Start(unsigned int dutyCycle);
void Pwm1_Stop(void);

/** PWM frequency in Hz */
#define PWM_FREQ ((unsigned long)(20000)) //Hz
#define BUS_FREQ ((unsigned long)(24000000))
#define TPM1_PRESCALER (1) //preescaler of 1
#define TPM1_PRESCALER_VALUE (0b000) //preescaler of 1
#define TPM1_TICK_FREQ ((unsigned long)(BUS_FREQ/TPM1_PRESCALER))
#define TPM1C3SC_VALUE (TPM1C3SC_MS3B_MASK|TPM1C3SC_ELS3B_MASK)
#define TPM1_SC_VALUE ((unsigned char)(TPM1_PRESCALER_VALUE)
#define TPM1_MOD_VALUE ((unsigned int)(TPM1_TICK_FREQ/PWM_FREQ))
#define TMP1_CLEAR_OV_FLAG() TPM1SC_TOF = 0x00
#define TPM_MAX_VAL (unsigned long)(TPM1_TICK_FREQ/PWM_FREQ)
#define TPM1C3_PIN_DD PTDDD_PTDDD5
#define TPM1C3_PIN_D PTDD_PTDD5
#define TPM1_START() TPM1SC_CLKSx = 0x1
#define TPM1_STOP() TPM1SC_CLKSx = 0x0
/**************************************************************************
* MAIN ROUTINE
**************************************************************************/
void main(void)
{
unsigned int PWMValue = 100;
initSys();
Pwm1_Init();
for(;:smileywink:
{
Pwm1_Start(PWMValue);
Pwm1_Stop();
}
}

void Pwm1_Init(void)
{
TPM1C3_PIN_D = 0;
TPM1C3_PIN_DD = 1;

TPM1SC = TPM1_SC_VALUE;
TPM1MOD = TPM1_MOD_VALUE;

TPM1C3SC = TPM1C3SC_VALUE;

PTFDD_PTFDD2 = 1;
}

void Pwm1_Start(unsigned int dutyCycle)
{
TPM1C3_PIN_D = 0;
TPM1C3SC = TPM1C3SC_VALUE;

if (dutyCycle == 0)
{
return; //don't start pwm
}
else if(dutyCycle >= TPM_MAX_VAL)
{
TPM1C3_PIN_D = 1;
return; //don't start pwm
}
else
{
TPM1C3V = (dutyCycle);
TPM1CNT = 0;
asm (nop);
asm (nop);
asm (nop);

TPM1_START();
}
}

void Pwm1_Stop(void)
{
TPM1_STOP();
TPM1C3SC = 0;
TPM1C3_PIN_D = 0;
TPM1CNT = 0;
}

/**************************************************************************
* SYSTEM INITIALIZATION ROUTINES
**************************************************************************/
void initSys(void)
{
initMCU();
initMCG();
}
void initMCU(void)
{
//System Options 2 Register
SOPT2 = 0x10;
/*0b00010000
||||||||__ bit0: Analog Comparator output not connected to TPM1
|||||||___ bit1: RESERVED
||||||____ bit2: RESERVED
|||||_____ bit3: RESERVED
||||______ bit4: CLKOUT_EN BUSCLK is available on external pin PTC7
|||_______ bit5: RESERVED
||________ bit6: COP normal mode selected
|_________ bit7: --- */

//SIM Clock Set and Select Register
SIMCO = 0x04;
/*0b00000100
||||||||__ bit0: CS[0] CLKOUT = BUSCLK
|||||||___ bit1: CS[1]
||||||____ bit2: CS[2]
|||||_____ bit3: RESERVED
||||______ bit4: RESERVED
|||_______ bit5: RESERVED
||________ bit6: RESERVED
|_________ bit7: RESERVED */

//System Options 1 Register
SOPT1 = 0x23;
/*0b00100011
||||||||__ bit0: RESET# pin enabled
|||||||___ bit1: BKGD/MS pin enabled
||||||____ bit2: RESERVED
|||||_____ bit3: BLMS Satus (read only)
||||______ bit4: RESERVEd
|||_______ bit5: Stop mode enabled
||________ bit6: COPT[0] COP is disabled
|_________ bit7: COPT[1] */
}
void initMCG(void)
{
//FBE MODE
/* Assume 16MHz external clock source connected. */
// RANGE = 1; HGO = 1; ERCLKEN=1; EREFS = 1; BDIV = 000
MCGC2 = 0x36;
/*0b00110110
||||||||_ bit0: EREFSTEN external reference clock is disabled in stop
|||||||__ bit1: ERCKLEN MCGERCLK active
||||||___ bit2: EREFS Oscillator requested
|||||____ bit3: LP FLL not disabled in bypass modes
||||_____ bit4: HGO Configure crystal oscillator for high gain operation
|||______ bit5: RANGE High frequency range selected
||_______ bit6: BDIV[0]=0
|________ bit7: BDIV[1]=0 Divides clock by 1 */

// DIV32 =1
MCGC3 = 0x11;
/*0b00010001
||||||||_ bit0: VDIV[0]=0
|||||||__ bit1: VDIV[1]=0
||||||___ bit2: VDIV[2]=0
|||||____ bit3: VDIV[3]=0 ???
||||_____ bit4: DIV32 Divide-by-32 is enabled when RANGE=1
|||______ bit5: CME clock monitor is disabled
||_______ bit6: PLLS FLL is selected
|________ bit7: LOLIE no request on loss of lock */

// CLKS = 10; RDIV = 100; IREFS = 0;
MCGC1 = 0xA0;
/*0b10100000
||||||||_ bit0: IREFSTEN internal ref clk disabled in stop
|||||||__ bit1: IRCLKEN MCGIRCLK inactive
||||||___ bit2: IREFS external reference clock selected
|||||____ bit3: RDIV[0]=0
||||_____ bit4: RDIV[1]=0
|||______ bit5: RDIV[2]=1 divide factor = 512 (since RANGE=1,DIV32=1)
||_______ bit6: CLKS[0]=0
|________ bit7: CLKS[1]=1 external reference clock is selected */

// Wait for Reference Status bit to update
while (MCGSC_IREFST);
// Wait for clock status bits to update
while (MCGSC_CLKST != 0b10);

//PBE MODE

// PLLS =1; DIV32 = 1; VDIV = 1001
MCGC3 = 0x5c;
/*0b01011100
||||||||_ bit0: VDIV[0]=0
|||||||__ bit1: VDIV[1]=0
||||||___ bit2: VDIV[2]=1
|||||____ bit3: VDIV[3]=1 Multiply by 48
||||_____ bit4: DIV32 Divide-by-32 is enabled when RANGE=1
|||______ bit5: CME clock monitor is disabled
||_______ bit6: PLLS PLL is selected
|________ bit7: LOLIE no request on loss of lock */
// wait for PLL status bit to update
while (!MCGSC_PLLST);
// Wait for LOCK bit to set
while (!MCGSC_LOCK);

//PEE MODE

// CLKS = 00; RDIV = 100; IREFS = 0
MCGC1 = 0x20;
/*0b00100000
||||||||_ bit0: IREFSTEN internal ref clk disabled in stop
|||||||__ bit1: IRCLKEN MCGIRCLK inactive
||||||___ bit2: IREFS external reference clock selected
|||||____ bit3: RDIV[0]=0
||||_____ bit4: RDIV[1]=0
|||______ bit5: RDIV[2]=1 divide factor = 512 (since RANGE=1,DIV32=1)
||_______ bit6: CLKS[0]=0
|________ bit7: CLKS[1]=0 output of FLL or PLL is selected */
// Wait for clock status bits to update
while (MCGSC_CLKST != 0b11); ;

/* Now MCGOUT=48MHz, BUS_CLOCK=24MHz */
}

 

To summarize, the bus clock is at 24MHz and the external clock source is a 16MHz xtal.

The TPM Module is configured in edge-aligned PWM mode for TPM1CH3.  The modulo value is 1200, and I'm updating TPM1C3V with a value of 100.

 

On the Tower Development board, pin PTD5/SCL/TPM1CH3 is routed to A7 on the A side expansion port.  I have an oscilloscope hooked up to this pin and when I run the code I do not see the PWM signal.  Please help!

 

Thank you!

mahnac

Labels (1)
0 Kudos
1 Solution
512 Views
mahnac
Contributor II

I changed the clock source from the external clock to the BUSCLK and it works!  Not really sure why that would solve it, but I'm seeing the signal now.  Here's the updated code:

/** PWM frequency in Hz */#define PWM_FREQ      20000  //Hz#define BUS_FREQ        24000000#define TPM1_PRESCALER  1   //preescaler of 1    /*************************************************************************** MAIN ROUTINE**************************************************************************/void main(void){ unsigned int PWMValue = 1000; initSys(); TPM1MOD = (BUS_FREQ/TPM1_PRESCALER/PWM_FREQ);  TPM1C3SC = 0x28;  TPM1C3V = PWMValue; TPM1SC = 0x08;  //BUSCLK selected as source for(;;){}}

 

View solution in original post

0 Kudos
4 Replies
512 Views
bigmac
Specialist III

Hello Mahnac, and welcome to the forum.

 

The main problem seems to be your main loop.

 

for( ; ; ) {
   Pwm1_Start(PWMValue);
   Pwm1_Stop();
}

Your are continuously starting and stopping the PWM operation, so the output waveform will never start.

 

Another problem might be your TPM1_START() and TPM1_STOP() macros.  The register bit TPM1SC_CLKSx would seem an invalid name, unless it has been defined elsewhere.

 

To my mind, the following macro definitions would be more meaningful.

#define TPM1_PS      0                        // preescale 1#define TPM1_START() TPM1SC = 0x08 | TPM1_PS  // Select bus clock#define TPM1_STOP()  TPM1SC = 0x00

 On a similar basis, I would use -

#define TPM1C3SC_value  0x28   // PWM mode, high true pulse

 

Also note that, whilst the TPM module is enabled, this will override any of the GPIO settings.  You may initialise the GPIO pin for when the TPM module is disabled, but it is unnessary to manipulate the pin when the TPM module is running.

 

A final issue - when defining constants, don't use casts, but use the suffix 'U' for unsigned and/or 'L' for 32-bit, as needed.

e.g.  #define PWM_FREQ  20000UL

 

Regards,

Mac

 

0 Kudos
512 Views
mahnac
Contributor II

Hi bigmac

 

Thanks for the speedy response!  Here's what I tried next:

 

=> The CodeWarrior compiler didn't like "#define PWM_FREQ  20000UL" So I took out the typecasting all together.

=> I simply turned on the PWM, then entered an empty for loop forever.

=> I cleaned up the code a bit.  The updated code is shown below (I didn't include the system config code, that remains the same)

 

All of the registers are updating - after running Pwm1_Init() and Pwm1_Start(), TPM1MOD = 1200, TPM1C3SC = 40, TPM1C3V = 100, and TPM1SC = 24.  But I'm still not seeing the signal on the oscilloscope.  The only change is that before starting TPM1, the pin is pulled high (this might be because of another function?  It's also the SCL pin), and then after the clock source is indicted (TPM1_START()), the pin goes low.

 

Thanks again for your help!!

- mahnac

 

Here's the updated code:

#define PWM_FREQ      20000  //Hz#define BUS_FREQ        24000000#define TPM1_PRESCALER  1   //preescaler of 1    #define TPM_MAX_VAL    (BUS_FREQ/TPM1_PRESCALER/PWM_FREQ)     #define TPM1_START()  TPM1SC = 0x18;#define TPM1_STOP()   TPM1SC = 0x00;/*************************************************************************** MAIN ROUTINE**************************************************************************/void main(void){ unsigned int PWMValue = 100; initSys(); Pwm1_Init(); Pwm1_Start(PWMValue); for(;;){}}void Pwm1_Init(void){    TPM1MOD = (BUS_FREQ/TPM1_PRESCALER/PWM_FREQ);    TPM1C3SC = 0x28;}void Pwm1_Start(unsigned int dutyCycle){ TPM1C3SC = 0x28;  if (dutyCycle == 0) {  return; //don't start pwm } else if(dutyCycle >= TPM_MAX_VAL) {  return; //don't start pwm } else {  TPM1C3V = (unsigned int)(dutyCycle);  TPM1CNT = 0;   asm (nop);   asm (nop);  asm (nop);  TPM1_START(); }}

 


0 Kudos
513 Views
mahnac
Contributor II

I changed the clock source from the external clock to the BUSCLK and it works!  Not really sure why that would solve it, but I'm seeing the signal now.  Here's the updated code:

/** PWM frequency in Hz */#define PWM_FREQ      20000  //Hz#define BUS_FREQ        24000000#define TPM1_PRESCALER  1   //preescaler of 1    /*************************************************************************** MAIN ROUTINE**************************************************************************/void main(void){ unsigned int PWMValue = 1000; initSys(); TPM1MOD = (BUS_FREQ/TPM1_PRESCALER/PWM_FREQ);  TPM1C3SC = 0x28;  TPM1C3V = PWMValue; TPM1SC = 0x08;  //BUSCLK selected as source for(;;){}}

 

0 Kudos
512 Views
bigmac
Specialist III

Hello,


mahnac wrote:

I changed the clock source from the external clock to the BUSCLK and it works!  Not really sure why that would solve it, but I'm seeing the signal now.

 


Selecting the external clock for the TPM module requires that a square wave clock signal be applied to the TPMCLK pin.

 

Regards,

Mac

 

0 Kudos