Problems with adjusting the duty cycle of stm32f203 general timer output PWM wave[Copy link]
Question: I use the firmware library to program in stm32f103 to make the TIM3 of the general timer output four PWM waves. I want to use the button to adjust the duty cycle of PWM when the program is executed. My approach is to use an if statement to detect when the button is pressed. If the button is detected, the value of the CCR register increases. I put the if statement and the function of outputting PWM in parallel in the main function, and the original set PWM will be output, but pressing the button will not change the duty cycle; #include "stm32f10x.h" #include "bsp_led.h" #include "bsp_GeneralTim.h" uint16_t CCR1_Val = 999; int main(void) { /* key port configuration*/ LED_GPIO_Config(); /* timer initialization*/ GENERAL_TIM_GPIO_Config(); //Detect button press if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) == 0) { CCR1_Val += 100; //Add 100 to the value of CCR } //Output PWM GENERAL_TIM_Mode_Config(CCR1_Val,CCR2_Val,CCR3_Val,CCR4_Val); } But I put the if statement and the PWM output function into a while (1) loop. No matter how I press the button, the output PWM period is only a dozen microseconds, and the high level time is only a few microseconds less than the period. Why is this??????? #include "stm32f10x.h" #include "bsp_led.h" #include "bsp_GeneralTim.h" uint16_t CCR1_Val = 999; int main(void) { /* key port configuration*/ LED_GPIO_Config(); /* timer initialization*/ GENERAL_TIM_GPIO_Config(); while(1) { //Detect button press if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) == 0) { CCR1_Val += 100; //CCR value plus 100 } //Output PWM GENERAL_TIM_Mode_Config(CCR1_Val,CCR2_Val,CCR3_Val,CCR4_Val); } } The following is the timer sub-function #include "bsp_GeneralTim.h" void GENERAL_TIM_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; //Output comparison channel 1 GPIO initialization RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); } void GENERAL_TIM_Mode_Config(uint16_t CCR1_Val) { // Turn on the timer clock, that is, the internal clock CK_INT=72M GENERAL_TIM_APBxClock_FUN(RCC_APB1Periph_TIM3,ENABLE); /*--------------------Time base structure initialization-------------------------*/ // Configuration period, here configured as 20ms TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // Automatically reload the value of the register, accumulate TIM_Period+1 frequency and generate an update or interrupt TIM_TimeBaseStructure.TIM_Period=19999; // The clock that drives the CNT counter = Fck_int/(psc+1) TIM_TimeBaseStructure.TIM_Prescaler= 71; // Clock division factor, required for configuring dead time TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // Counter counting mode, set to count up TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // Repeat counter value, ignore it if not used TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // Initialize timer TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /*--------------------Output comparison structure initialization-------------------*/ // Duty cycle configuration TIM_OCInitTypeDef TIM_OCInitStructure; // Configure as PWM mode 1 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // Output enable TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // Output channel level polarity configuration TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // Output compare channel 1 TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure); TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable); // Enable counter TIM_Cmd(GENERAL_TIM, ENABLE); } The following is the key sub-function #include "bsp_led.h" void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOE, &GPIO_InitStructure); }
In the main loop, execute the function that only changes the duty cycle or period, and see if there is such a function in the library. Try not to change other settings.
Details
Published on 2018-2-3 14:18
First, the while (1) loop is necessary. You should have a debounce check when reading the keystrokes. Otherwise, the value of CCR1_Val will change frequently and be unstable.
Hello, thank you. But I don't use the buttons in the big loop, just output the originally set PWM wave, and it can't be output. I set the cycle to 20ms, but the output cycle is only a few microseconds. Why is this?
Details
Published on 2018-1-30 14:01
ienglgge posted on 2018-1-30 12:48 First of all, the while (1) loop is necessary. You should have a debounce judgment when reading the key. Otherwise, the value of CCR1_Val will change frequently. Unstable.
Hi, thank you, but I don’t use the key in the big loop, just output the originally set PWM wave, and it can’t be output. I set the period to 20ms, but the output period is only a few microseconds. Why is this?
The period is 20ms, but the output period is only a few microseconds. Increase the period. See the actual change. Note whether the actual duty cycle is the same as the setting.
Details
Published on 2018-1-31 13:52
This post was last edited by huo_hu on 2018-1-30 16:18 There is no need to repeatedly initialize the timer setting like you did. The result cannot be predicted during this period. Just pay the value to the channel register. In addition, your continuous accumulation of CCR1 is problematic. CCR1 overflows and returns to 0 instantly, which is definitely not the result you want. Key jitter will also have an impact. When the channel value is greater than the period, the output is an invalid level, which must also be considered. It is best to enable preloading when the channel is frequently assigned.
Hello, first of all, thank you. According to what you said, how should I achieve the result I want? How to turn on preloading?
Details
Published on 2018-2-1 08:58
平淡最真 posted on 2018-1-30 14:01 Hello, thank you. But I don't use the buttons in the big loop, just output the original PWM wave, and it can't be output. I set the cycle to 20ms...
The cycle is 20ms, but the output cycle is only a few microseconds. Increase the cycle. See the actual changes. Pay attention to whether the actual duty cycle is the same as the setting.
huo_hu posted on 2018-1-30 16:15 There is no such thing as repeatedly initializing the timer settings. The results cannot be predicted during this period. Just pay the value to the channel register. ...
Hello, first of all, thank you for following your instructions. How should I achieve the results I want? How do I turn on preloading?
ienglgge posted on 2018-1-31 13:52 The period is 20ms, but the output period is only a few microseconds. Increase the period. See the actual changes. Note whether the actual duty cycle is the same as the setting.
ienglgge posted on 2018-1-31 13:52 The cycle is 20ms, but the output cycle is only a few microseconds. Increase the cycle. See the actual changes. Pay attention to whether the actual duty cycle is the same as the setting.
Hi, I tried it according to what you said. No matter how I change the cycle, the output PWM cycle in while(1) does not change. It is always the original ten microseconds. I change the duty cycle, but the output duty cycle does not change. It is completely different from the setting. It is not running at all as I set it.
I don't know how you changed it. Don't judge the key. Just give a dead configuration. Look at different situations and output the results.
Details
Published on 2018-2-1 13:37
平淡最真 posted on 2018-2-1 09:23 Hi, I tried it as you said. No matter how I change the cycle, the output PWM cycle in while(1) remains unchanged, and is always the original ten microseconds. ...
I don't know how you changed it specifically. Don't judge the key. Just give a dead configuration. Look at the different situations and output the results.
ienglgge posted on 2018-2-1 13:37 I don't know how you changed it specifically. Don't judge the key. Just give a dead configuration. Look at different situations and output the results.
Give a dead configuration. As long as you don't put the PWM output function in the big loop, everything is normal
In the main loop, execute a function that only changes the duty cycle or period. Check the library to see if there is such a function. Try not to change other settings.
Details
Published on 2018-2-3 14:18
平淡最真 posted on 2018-2-2 20:28 Give a dead configuration, as long as you don't put the PWM output function in the big loop, everything will be normal
In the main loop, execute the function that only changes the duty cycle or period, and see if there is such a function in the library. Try not to change other settings.