2020-09-14 11:26 AM
Please help these issues. Below issues 1 and 2 do not seem to affect each other.
Goal: creating an one-pulse PWM output using TIM1 with output not changing state at the end of the pulse in idle. For example, in the scope capture (attached) I need to have ch1,2 to stay low from the point 63us and beyond (idle). Chn4 to stay high from the point 63us and beyond (idle).
Tools: STM8S105C Discovery board. using STVD, Cosmic compiler, library for Discovery board
Results/Issues:
1. Attached is scope captures of TIM1 chn1,2,4
2. Issue1: measured freq is ~15.8KHz (63us). I expect 100Hz (10ms) per code below. Although, I can change the freq correctly with TIM1_TimeBaseInit(). For example, if I double the freq in the code, I’ll see double freq on scope. Measured duty cycle is correct. It looks like clock for TIM1 is not 16MHz. But I can’t find where the culprit is.
3. Issue2: parameter OCIDLESTATE doesn’t change state of output in idle when assigned to SET or RESET in TIM1_OC1Init(). Is it possible to achieve the goal with STM8S105C?
4. Measured TIM2 freq and DC is correct. So clock freq for TIM2 is correctly 16MHz, why not TIM1 clock?
void main(void)
{
CLK_DeInit();
CLK_LSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_LSIRDY) == FALSE);
CLK_HSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
CLK_ClockSwitchCmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, ENABLE);
GPIO_DeInit(GPIOD);
GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_IN_PU_IT);
EXTI_DeInit();
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD,EXTI_SENSITIVITY_RISE_FALL);
// TIM1 PWM Configuration
TIM1_DeInit();
TIM1_TimeBaseInit(160,TIM1_COUNTERMODE_UP,999,0); //Set TIM1 Frequency to 100Hz (10ms)
TIM1_OC1Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, 100, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET); //10% pulse
TIM1_OC1PreloadConfig(ENABLE);
TIM1_OC2Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, 499, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET); //50% pulse
TIM1_OC2PreloadConfig(ENABLE);
TIM1_OC4Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, 899, TIM1_OCPOLARITY_LOW, TIM1_OCIDLESTATE_SET); //90% pulse
TIM1_OC4PreloadConfig(ENABLE);
TIM1_ARRPreloadConfig(ENABLE);
TIM1_SelectOnePulseMode(TIM1_OPMODE_SINGLE);
TIM1_CtrlPWMOutputs(ENABLE);
TIM1_Cmd(ENABLE);
//TIM2 interrupt every 100us ------------------
TIM2_DeInit();
TIM2_TimeBaseInit(TIM2_PRESCALER_16, 99); //100us, 5Khz
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
TIM2_Cmd(ENABLE);
//---------------------------------------------
enableInterrupts();
while (1);
}
Update:
I have update info on the issue1. What I changed was enabling TIM1 every time there is an Ext interrupt at portD pin.
1. Commenting out TIM1_Cmd(ENABLE); in TIM1 PWM configuration code
2. Adding TIM1_Cmd(ENABLE); in INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6)
INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6)
{
TIM1_Cmd(ENABLE);
}
My observation: After reset, on the 1st TIM1_Cmd(ENABLE), TIM1 behaves like issue1 (wrong freq) in my previous email. After that, TIM1 behaves correctly as designed in term of freq and duty cycle. In the attached scope captures "TIM1_onepulsePWM_2" and "TIM1_onepulsePWM_2zoom", scope ch1 is the ext interrupt at port D. “TIM1_onepulsePWM_2zoom.jpg�? is the zoom in at the 1st instance of TIM1_Cmd(ENABLE).
Does anyone have explanation for this?
I still have the issue2.
Update 9/22/20: I add this update for those who is seeing the same issue1.
The issue1 is that the first PWM output has the wrong freq. Solution is setting bit UG of reg EGR before enable the timer. For my code, TIM1->EGR |= TIM1_EGR_UG; is inserted before TIM2_Cmd(ENABLE); (see below). This fixes the problem.
TIM1_CtrlPWMOutputs(ENABLE);
TIM1->EGR |= TIM1_EGR_UG; //setting bit UG
TIM1_Cmd(ENABLE);