Hi,
I configured PORTA1 as TPM2-CH(0) as the PWM pulse output and find a problem. The duty pulse level is reversed and I could not figure out what is going wrong. I expected duty pulse 600 counts would be high and the rest time 6000 counts should be low but the real pulse out is reversed.
Here is my code. Could some body help me to solve the problem?
void PWM_init(void) //added by Albert 2019.06.17
{
CLOCK_EnableClock(kCLOCK_Tpm2);
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TPMSRC_MASK) | SIM_SOPT2_TPMSRC(1U)); //=1=48MHz
PORTA->PCR[1] =BIT8+BIT9;
TPM2->SC &=~(BIT3+BIT4); //disable timer
TPM2->SC = TPM_SC_PS(0);//prescale =1 TPM2-SC=1 ,disable the counter
TPM2->CNT =0U; //clear counter value
TPM2->MOD =6600U; //Modulo, PWM=400Hz set PWM period 60K =400Hz
TPM2->CONTROLS[0].CnSC =BIT3+BIT5; //BIT3+BIT5=Edge Aligned duty cycle output; BIT2+BIT4 =50% toggle on match
TPM2->CONTROLS[0].CnV =600U; //duty pulse
TPM2->CONF =TPM_CONF_TRGSEL(0);
TPM2->SC |=BIT3; //Start timer
}
int main(void) {
/* Init board hardware. */
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
// initialize the system
system_manager_init(&s_sensor);
PWM_init();
while(1) {
// and off we go...
// GPIOC->PTOR |=BIT4;//RS485_TX_ON;
system_manager_process(&s_sensor);
}
}
Hi Albert Zhou,
According to the description of "Table 23-5. Mode, Edge, and Level Selection", your configuration seems ok.
Maybe you should check if the invert mode is enabled on your oscilloscope.
Best Regards,
Robin
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Robin,
I know this code works on the other board with same MCU. I use the same scope to check the PWM output. The other board has the correct PWM output.
I know there is four functions declared before the PWM_init(). I wonder there are some code I need to added in the PWM_init() in order to make this function work.
Thanks for your response.
Albert Zhou
You can check the register value of TPM2 and PORTA during debug.
The MCUXPresso SDK_2.6.0_MKL27Z64xxx4 using PTA1 as LPUART function, so I didn't call BOARD_InitDebugConsole() and modify the codes in BOARD_InitPins().
Best Regards,
Robin
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Robin,
I know if I use SDK board the code will function right as expected. I guess there must be something interferences the configuration of my code.
Do you know the function BOARD_BootClockRUN()?
the BOARD_InitPins() cod eas below:
void BOARD_InitPins(void) {
CLOCK_EnableClock(kCLOCK_PortA); /* Port A Clock Gate Control: Clock enabled */
CLOCK_EnableClock(kCLOCK_PortB); /* Port B Clock Gate Control: Clock enabled */
CLOCK_EnableClock(kCLOCK_PortC); /* Port C Clock Gate Control: Clock enabled */
CLOCK_EnableClock(kCLOCK_PortD); /* Port D Clock Gate Control: Clock enabled */
CLOCK_EnableClock(kCLOCK_PortE); /* Port E Clock Gate Control: Clock enabled */
CLOCK_EnableClock(kCLOCK_Tpm2);
PORT_SetPinMux(PORTA, 0U, kPORT_MuxAlt7); // PTA0 = SWD_CLK (SWD_CLK)
PORT_SetPinMux(PORTA, 1U, kPORT_MuxAlt3); // PTA1 = PWM out (TPM2_CH0)
// PTA2 nc
PORT_SetPinMux(PORTA, 3U, kPORT_MuxAlt7); // PTA3 = SWD_DIO (SDW_DIO)
PORT_SetPinMux(PORTA, 4U, kPORT_MuxAsGpio); // PTA4 = CPG1 (GPIO A4)
PORT_SetPinMux(PORTA, 18U, kPORT_MuxAlt3); // PTA18 = MBRx (LPUART1_RX)
PORT_SetPinMux(PORTA, 19U, kPORT_MuxAlt3); // PTA19 = MBTx (LPUART1_TX)
PORT_SetPinMux(PORTA, 20U, kPORT_MuxAlt7); // PTA20 = RESET_b (RESET_b)
PORT_SetPinMux(PORTB, 0U, kPORT_PinDisabledOrAnalog); // PTB0 = mV_h (ADC0_SE8)
PORT_SetPinMux(PORTB, 1U, kPORT_PinDisabledOrAnalog); // PTB1 = VB (ADC0_SE9?) [pin 21]
PORT_SetPinMux(PORTC, 1U, kPORT_PinDisabledOrAnalog); // PTC1 = ORP (ADC0_SE15)
PORT_SetPinMux(PORTC, 2U, kPORT_PinDisabledOrAnalog); // PTC2 = TEMP_H (ADC0_SE11)
PORT_SetPinMux(PORTC, 3U, kPORT_MuxAsGpio); // PTC3 = CPG0 (GPIO C3)
PORT_SetPinMux(PORTC, 4U, kPORT_MuxAsGpio); // PTC4 = MODBUS_EN (GPIO C4)
PORT_SetPinMux(PORTC, 5U, kPORT_MuxAsGpio); // PTC5 = LDO_HpH_SEL (GPIO C5)
PORT_SetPinMux(PORTC, 6U, kPORT_MuxAsGpio); // PTC6 = reed switch (GPIO C6)
PORT_SetPinMux(PORTC, 7U, kPORT_MuxAsGpio); // PTC7 = ?? ("E202")
PORT_SetPinMux(PORTD, 4U, kPORT_MuxAsGpio); // PTD4 = MBTXEN (GPIO D4)
PORT_SetPinMux(PORTD, 5U, kPORT_MuxAsGpio); // PTD5 = CPLH (GPIO D5)
PORT_SetPinMux(PORTD, 6U, kPORT_MuxAlt3); // PTD6 = ?? ("E209") (LPUART0_RX)
PORT_SetPinMux(PORTD, 7U, kPORT_MuxAlt3); // PTD7 = ?? ("E210") (LPUART0_TX)
PORT_SetPinMux(PORTE, 0U, kPORT_MuxAsGpio); // PTE0 = ?? ("E204")
PORT_SetPinMux(PORTE, 16U, kPORT_PinDisabledOrAnalog); // PTE16 = pH/DO (ADC0_SE1)
PORT_SetPinMux(PORTE, 30U, kPORT_PinDisabledOrAnalog); // PTE32 = PWM_FB (ADC_SE23)
// Configure loop current PWM (whether or not probe uses current loop)
SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TPMSRC_MASK) | SIM_SOPT2_TPMSRC(1U)); //=1=48MHz
// SIM->SOPT4 = ((SIM->SOPT4 &
// (~(SIM_SOPT4_TPM2CH0SRC_MASK))) // Mask bits to zero which are setting //
// | SIM_SOPT4_TPM2CH0SRC(SOPT4_TPM2CH0SRC_TPM2_CH0) // TPM2 Channel 0 Input Capture Source Select: TPM2_CH0 signal //
// );
//
// configure LPUART1 (used for Modbus i/o)
SIM->SOPT5 = ((SIM->SOPT5 &
(~(SIM_SOPT5_LPUART1TXSRC_MASK | SIM_SOPT5_LPUART1RXSRC_MASK))) /* Mask bits to zero which are setting */
| SIM_SOPT5_LPUART1TXSRC(SOPT5_LPUART1TXSRC_LPUART_TX) /* LPUART1 Transmit Data Source Select: LPUART1_TX pin */
| SIM_SOPT5_LPUART1RXSRC(SOPT5_LPUART1RXSRC_LPUART_RX) /* LPUART1 Receive Data Source Select: LPUART1_RX pin */
);
// PORTA->PCR[1] =BIT8+BIT9;
TPM2->SC &=~(BIT3+BIT4); //disable timer
TPM2->SC = TPM_SC_PS(0);//prescale =1 TPM2-SC=1 ,disable the counter
TPM2->CNT =0U; //clear counter value
TPM2->MOD =6600U; //Modulo, PWM=400Hz set PWM period 60K =400Hz
TPM2->CONTROLS[0].CnSC =BIT3+BIT5; //BIT3+BIT5=Edge Aligned duty cycle output; BIT2+BIT4 =50% toggle on match
TPM2->CONTROLS[0].CnV =600U; //duty
TPM2->CONF =TPM_CONF_TRGSEL(0);
TPM2->SC |=BIT3; //Start timer
}
and the BOARD_BootClockRUN(), do you think those code interferences the TPM2CH0?
void BOARD_BootClockRUN(void)
{
/* Set the system clock dividers in SIM to safe value. */
CLOCK_SetSimSafeDivs();
/* Set MCG to HIRC mode. */
CLOCK_SetMcgliteConfig(&mcgliteConfig_BOARD_BootClockRUN);
/* Set the clock configuration in SIM module. */
CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN);
/* Set SystemCoreClock variable. */
SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
}