Updating TPMnC0V on S08DZ60

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

Updating TPMnC0V on S08DZ60

1,122 Views
mayfly
Contributor III
Hi,

I want to be able update the TPMnC0V 'on-the-fly' to modify the pulse width of a center-aligned pwm. I am able to change the value if: TPMnC0V !>= Modulus, but once it becomes >= the modulus, I can't adjust the value unless I set a value of TPMnC0V=0. This seems wrong (i.e. I'm doing something wrong). In the code below, once TPMnC0V >= modulus, the interrupt won't trigger, but I am updating TPMnC0V outside of the interrupt. Any thoughts/answers would be appreciated.

Code:
--------------------------------------------------------------------------------------//#include#include // for EnableInterrupts macro#define PRESCALAR 0 //7 // gives base pwm frequency#define MODULUS 32768 // pwm frequency = base pwm frequency / modulus#define DUTY50 16389#define MAX_DUTY MODULUS#define tLED1 PTCD_PTCD5#define tSW1 PTBD_PTBD6#define tSW2 PTBD_PTBD7unsigned int tpm2c0int = DUTY50;--------------------------------------------------------------------------------------//void main(void){unsigned char tpm2c0vh, tpm2c0vl;unsigned char changed_flag = 0;unsigned char temp_pot_value = 0;PTADD = 0; //initialize as input (Data Direction Rregister// Configures PTB3 and PTC5 as output (USER LED1 & LED2)PTBDD = 0x08;PTCDD = 0x20;tLED1 = 1;//Initialize timer TPM2 channel, assumes not touched since reset!TPM2SC_CLKSA = 1;//Select BUS clockTPM2SC_CLKSB = 0;TPM2SC_PS = PRESCALAR;//clock source divided by prescalar/TPM2MOD = MODULUS;//set Counter modulusTPM2SC_CPWMS = 1; //set center aligned//configure PWM mode and pulseTPM2C0SC_MS0B = 1; //don't care for center aligned //MS0B=1, MS0A=0; Edge align PWM//TPM2C0SC_MS0A = 1; //don't care for center aligned or edge alignedTPM2C0SC_ELS0B = 1; // 1 = Select high as true, 0 = Select low as trueTPM2C0SC_ELS0A = 0; // 0 = Select high as true, 1 = Select low as trueTPM2C0V = tpm2c0int;TPM2C0SC_CH0IE = 1;TPM2C0SC = TPM2C0SC;EnableInterrupts;for(;;){__RESET_WATCHDOG(); //kicks the dogif(!tSW1){if(tpm2c0int MAX_DUTY-1){tpm2c0int++;changed_flag = 1;}}if(!tSW2){if(tpm2c0int > 0){tpm2c0int --;changed_flag = 1;}}if(changed_flag == 1){TPM2C0V = tpm2c0int;changed_flag = 0;}}// loop forever}//-----------------------------------------------------------------------interrupt 12 void T2CH0_cpwm (void){unsigned char dummy;dummy = TPM2C0SC_CH0F;TPM2C0SC_CH0F = 0;tLED1=~tLED1;dummy = TPM2SC;TPM2SC &= 0x7F;}//-----------------------------------------------------------------------

 

Message Edited by Alban on 2007-01-29 02:20 PM

Labels (1)
0 Kudos
1 Reply

227 Views
mayfly
Contributor III
This 'phenomena' is documented in the S08DZ60 documentation and seems to be CPWM specific. After re-reading the documentation for the nth time, I found the answer:

Writes to any registers: TPMxMODH, TPMxMODL, TPMxCnVH, TPMxCnVL, actually write to buffer registers. Values are transferred to the corresponding timer channel registers only after both 8-bit bytes of the 16-bit register have been written *AND* the timer counter reverses direction from up-counting to down-counting at the end of the terminal count in the modulus register (ie overflows wrt the previous MODULUS value).

Stepping through the code produces the same behavior as described in the documentation.

Something in the code that may have unintended results is this sequence:
TPM2C0V = tpm2c0int;
TPM2C0SC_CH0IE = 1;
TPM2C0SC = TPM2C0SC;

The documentation states that: "Writing to TPMxCnSC cancels any values written to the channel value registers...". I am not sure what 'cancel' means (zeros out the TPMxCnV or only zeros the buffer registers or both or something else?), but the above sequence suggests that TPM2C0V will get canceled (whatever 'cancel' means) by the write to TPM2C0SC. I have seen a couple of sample/demo programs use this same code sequence but they do not use CPWM, so maybe it doesn't matter in those cases.
0 Kudos