I just can't get the PWM working. Trying to use PTB3 and PTB2 to drive two separate heaters. The frequency should be 10k. The duty cycle is set to be about 50%. Below is the function that I developed to set it up. What am I missing? I plugged PTB3 into an oscilloscope, and it was a flat line. The oscilloscope is definitely working. Thanks a lot.
void PWM_setup(
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
SIM_SCGC6 |= (1<<26);
SIM_SOPT2 |= (1<<24); /* Select main clock source for the TPM module */
TPM2_SC = (000001011);
TPM2_CONF |= 0xC0;
PORTB_PCR3 = PORT_PCR_MUX(3);
PORTB_PCR2 = PORT_PCR_MUX(3);
TPM2_CNT = 111; //Causes CNT to start counting.
TPM2_MOD = (1001011000); //PWM period
TPM2_C0V = 101011000; //Duty cycle
TPM2_C1V = 101011000;
TPM2_C0SC = 00101100;
TPM2_C1SC = 00101100;
}
EDIT: The problem was that I was writing an int into the register, not a binary. Embarrassing, but I'll leave this up as an example of how to set up PWM.
Solved! Go to Solution.
Hi Keri
I configure PWM using the uTasker project interface as described in http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF
The attached binary can be loaded to a FRDM-KL25Z (assuming you are working on this board) and generates (exact) 10kHz signals on PTB2 and PTB3 (one 50% and one 76%).
There is a command line menu on the OpenSDA virtual COM port which allows memory to be displayed in the I/O sub-menu so that you can look at register setups (or use the debugger to do the same).
Comparing your code with this reference I suggest checking the following points:
- you set up the TMP to be clocked by MCGFLL so verify that the FLL is enabled. If you use PLL instead of FLL you should also set the SIM_SOPT2_PLLFLLSEL bit in SIM_SOPT2
- the attached binary uses PLL as source (48MHz) and the following register settings to generate the PWM signals:
FTM2_SC = 0x0c
FTM2_MOD = 0x12b
FTM2_CONF = 0xc0;
FTM2_C0SC = 0x28
FTM2_C0V = 0x96
FTM2_C1SC = 0x28
FTM2_C1V = 0xd3
- a write to the counter is not needed to start the counting because the counter starts as soon as a clock source is programmed in FTMx_SC
- I would always write FTMx_SC as final command and not first.
Regards
Mark
Kinetis: µTasker Kinetis support
KL25: µTasker Kinetis FRDM-KL25Z support / µTasker Kinetis TWR-KL25Z48M support
For the complete "out-of-the-box" Kinetis experience and faster time to market
Hi Keri
I configure PWM using the uTasker project interface as described in http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF
The attached binary can be loaded to a FRDM-KL25Z (assuming you are working on this board) and generates (exact) 10kHz signals on PTB2 and PTB3 (one 50% and one 76%).
There is a command line menu on the OpenSDA virtual COM port which allows memory to be displayed in the I/O sub-menu so that you can look at register setups (or use the debugger to do the same).
Comparing your code with this reference I suggest checking the following points:
- you set up the TMP to be clocked by MCGFLL so verify that the FLL is enabled. If you use PLL instead of FLL you should also set the SIM_SOPT2_PLLFLLSEL bit in SIM_SOPT2
- the attached binary uses PLL as source (48MHz) and the following register settings to generate the PWM signals:
FTM2_SC = 0x0c
FTM2_MOD = 0x12b
FTM2_CONF = 0xc0;
FTM2_C0SC = 0x28
FTM2_C0V = 0x96
FTM2_C1SC = 0x28
FTM2_C1V = 0xd3
- a write to the counter is not needed to start the counting because the counter starts as soon as a clock source is programmed in FTMx_SC
- I would always write FTMx_SC as final command and not first.
Regards
Mark
Kinetis: µTasker Kinetis support
KL25: µTasker Kinetis FRDM-KL25Z support / µTasker Kinetis TWR-KL25Z48M support
For the complete "out-of-the-box" Kinetis experience and faster time to market
That was very helpful, thanks!
For posterity, here's my final function.
void PWM_set(void){
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
SIM_SCGC6 |= (1<<26);
SIM_SOPT2 = (1<<24);
PORTB_PCR3 = PORT_PCR_MUX(3);
PORTB_PCR2 = PORT_PCR_MUX(3);
TPM2_SC = 0x0c;
TPM2_MOD = 0x12b;
TPM2_CONF = 0xc0;
TPM2_C0SC = 0x28;
TPM2_C0V = 0x12b;
TPM2_C1SC = 0x28;
TPM2_C1V = 00010;
}