Homework for Weeks 8~9 – Timer & PWM Application Programming

1. Introduction to STM32 timing function
The timer function of STM32 is a powerful tool that can be used to implement timing operation and control in embedded systems. STM32 microcontrollers typically have multiple timers, each with multiple different configurations and functions. The following is some basic introduction to STM32 timer functions:

  1. Timer types: STM32 microcontrollers typically have several different types of timers, including advanced timers (TIM2-TIM5), basic timers (TIM6-TIM7), and watchdog timers (TIM1-TIM3 and TIM15-TIM17 ). Each type of timer has its specific uses and characteristics.
  2. Timer Modes: Each timer can be configured in one of several modes, such as up-counting mode, down-counting mode, center-aligned mode, etc. Depending on the desired timing behavior, the appropriate mode can be selected.
  3. Counting range: The counting range of the timer can be configured as needed. The counting period can range from 0 to 2^32-1, which allows the timer to be used in a variety of different application scenarios.
  4. Trigger input: Some timer types also have a trigger input, which enables them to trigger timing from an external signal. This is useful for applications that need to synchronize with external events.
  5. Capture Compare Feature: The timer can be configured to trigger an interrupt or update the output when a specific count value is reached. This allows the timer to be used to generate millisecond-level timing or for tasks such as PWM control.
  6. Synchronization: STM32 timers can be synchronized with each other, which allows them to work together to achieve more complex functions. For example, you can use the output signal of one timer to trigger the start or stop of another timer.
  7. Timer chain: STM32 also supports timer chain, which allows multiple timers to be connected together and work synchronously. This is useful for applications that require precise time synchronization.
  8. Countdown function: The STM32 timer also supports a countdown function, which can trigger an event after a certain time interval. This is useful for scenarios where a specific action needs to be triggered after a certain amount of time.
  9. Interrupt control: STM32’s timer supports interrupt control, which means that an interrupt can be triggered when the timer reaches a specific value, and then specific tasks can be performed in the interrupt handler.
  10. Calibration: The STM32 timer also has a calibration function, which can adjust the timer frequency to achieve more accurate timing. This is useful for applications requiring high precision timing.
    In general, the STM32 timer function is very powerful and can be flexibly configured according to different application requirements. By using these functions, various timing operations and control tasks can be easily implemented.
    2. Introduction to PWM functions
    PWM (Pulse Width Modulation) is pulse width modulation, referred to as pulse width modulation. PWM is an analog control method that modulates the bias of the transistor base or MOS tube gate according to changes in the corresponding load to change the conduction time of the transistor or MOS tube, thereby changing the output of the switching regulated power supply. PWM is a method of digitally encoding analog signal levels. Through the use of high-resolution counters, the duty cycle of the square wave is modulated to encode the level of a specific analog signal. The PWM signal is still digital because at any given moment, full DC power is either fully present (ON) or completely absent (OFF). As long as the bandwidth is sufficient, any analog value can be encoded using PWM. In STM32, the PWM function is commonly used in applications such as controlling motor speed, adjusting LED brightness, and generating audio signals. By adjusting the duty cycle of PWM (the proportion of high-level time to the total cycle), the average voltage or power of the output signal can be controlled.
    3. Create project
    Based on the original basic project, we add a c file and a header file to the “Hardware” file column on the left.

    Add basic function statements in “PWM.h”
#ifndef __PWM_H
#define __PWM_H
#include "stm32f10x.h" // Device header




#endif

4. Configuration function analysis
4.1 In STM32, APB1 controls the enablement of TIM2, and it is necessary to control TIM2 to the internal clock mode. The related functions configured are:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//APB1 enable.
TIM_InternalClockConfig(TIM2);//TIM2 identifies the internal clock mode

4.2 To configure the time base unit, you need to define a structure variable, and then extract its structure members for configuration respectively. The statement that declares the structure is

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;//Configuration structure

According to the formula, the clock frequency is 72MHZ/(PSC + 1)/(ARR + 1). After calculation, when PSC is set to 719, ARR is set to 99, the clock frequency is 1000HZ, which is 0.001s, that is, each The level existence time is 0.001s

//Configure time base unit
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;//Configuration structure
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//Specify clock frequency division, select no frequency division
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //Select counting mode, count up
TIM_TimeBaseInitStruct.TIM_Period=100-1;//Period, the value of ARR automatic reloading
TIM_TimeBaseInitStruct.TIM_Prescaler= 720-1; //PSC prescaler value
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//The value of the repetition counter will only be used by advanced timers
TIM_TimeBaseInit(TIM2, & amp;TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);

4.3 It is necessary to configure the enable interrupt and set it to the output comparison mode, so that the activated clock signal can be output compared to obtain the PWM waveform. The output comparison structure is defined as

TIM_OCInitTypeDef TIM_OCInitStruct;//Output comparison structure definition

The code that can be interrupted is as follows:

//Enable update interrupt
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//Enable update interrupt to NVIC
  
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCStructInit( & amp;TIM_OCInitStruct);//Assign initial value to the structure to avoid errors due to uncompiled members that do not appear
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//Output comparison mode, select PWM1 mode
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//Output polarity, high level is effective
TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;//Set output enable
TIM_OCInitStruct.TIM_Pulse=0;//Set CCR
    TIM_OC1Init(TIM2, & amp;TIM_OCInitStruct);

4.4 You need to use LED lights, so you also need to add the GPIO configuration function. In addition, the corresponding GPIO pin of TIM needs to look up the definition table. The TIM2_CH1_ETR pin is multiplexed on PA0, so we configure PA0.

//Configure GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
\t
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//Change to multiplexed push-pull output, timer control pin output level
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, & amp;GPIO_InitStructure);
\t
GPIO_SetBits(GPIOA, GPIO_Pin_0);
//Start the timer
TIM_Cmd(TIM2,ENABLE);

4.5 The formula of PWM duty cycle is CCR/ARR + 1. Earlier we set the ARR to 99, so we can set the CCR to fluctuate from 0-100, so that the calculated duty cycle is 0-100%. The specific results will be displayed in the main function. We have just defined an output comparison function now. In the STM32 standard library, the system provides the setting CCR function as

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)

We can use this function to set a changing CCR value.
Here we write the following code

void PWM_SetCompare1(uint16_t Compare)
{<!-- -->
TIM_SetCompare1(TIM2,Compare);//Set the value of the CCR register and you can change the value of the CCR at any time
\t
\t
\t
}

4.6 Header files and final functions of C files
head File:

#ifndef __PWM_H
#define __PWM_H
#include "stm32f10x.h" // Device header

void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);


#endif

C file

#include "stm32f10x.h" // Device header

void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//APB1 enable.
TIM_InternalClockConfig(TIM2);//TIM2 identifies the internal clock mode
\t
\t
//Configure time base unit
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;//Configuration structure
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//Specify clock frequency division, select no frequency division
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //Select counting mode, count up
TIM_TimeBaseInitStruct.TIM_Period=100-1;//Period, the value of ARR automatic reloading
TIM_TimeBaseInitStruct.TIM_Prescaler= 720-1; //PSC prescaler value
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//The value of the repetition counter will only be used by advanced timers
TIM_TimeBaseInit(TIM2, & amp;TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
\t
//Enable update interrupt
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//Enable update interrupt to NVIC
  
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCStructInit( & amp;TIM_OCInitStruct);//Assign initial value to the structure to avoid errors due to uncompiled members that do not appear
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//Output comparison mode, select PWM1 mode
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//Output polarity, high level is effective
TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;//Set output enable
TIM_OCInitStruct.TIM_Pulse=0;//Set CCR
  TIM_OC1Init(TIM2, & amp;TIM_OCInitStruct);
\t
//TIM corresponding GPIO pin needs to look up the definition table, TIM2_CH1_ETR pin is multiplexed on PA0
//Configure GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
\t
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //Change to multiplexed push-pull output, timer control pin output level
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, & amp;GPIO_InitStructure);
\t
GPIO_SetBits(GPIOA, GPIO_Pin_0);
//Start the timer
TIM_Cmd(TIM2,ENABLE);
}
void PWM_SetCompare1(uint16_t Compare)
{<!-- -->
TIM_SetCompare1(TIM2,Compare);//Set the value of the CCR register and you can change the value of the CCR at any time
\t
\t
\t
}


5. Main function writing analysis
5.1 Main function code
In the for loop, the function that sets the CCR is constantly called, and the CCR is constantly changed to realize the breathing light. The final code is as follows:

#include "stm32f10x.h" // Device header
#include "Delay.h"
//#include "OLED.h"
#include "PWM.h"
#include "LED.h"
#include "Delay.h"
uint16_t Num;
int main(void)
{<!-- -->
// OLED_Init();
    PWM_Init();//Configuration function
// OLED_ShowString(1,1,"a:");
// OLED_ShowString(2,1,"b:");
while (1)
{<!-- -->//In the for loop, continuously call the function that sets the CCR to implement the breathing light
for(Num=0;Num<=100;Num + + )//The amplitude continues to increase
{<!-- -->
\t\t\t
PWM_SetCompare1(Num);
Delay_ms(10);//The flashing period can be changed through the delay function.
// OLED_ShowNum(1,6,Num,3);
}
for(Num=0;Num<=100;Num + + )//The amplitude continues to decrease
{<!-- -->
\t\t\t
PWM_SetCompare1(100-Num);
Delay_ms(10);
// OLED_ShowNum(2,6,100-Num,3);
}
\t\t
}
}


6. Burning results and waveform observation
Plug an LED light into the PA0 port, and the rest is the same as in the previous experiment.

Turn on the magic wand and set it as follows:


Open the keil debugging interface and click on the logic analyzer:

Click “SET UP” on the interface

Set the following in the pop-up interface (fill in “PORTA.0” in the upper column).

The result is as follows:

7. Summary
Through this experiment, I understood the operating principles of different basic timing interrupt modes, and also explored the output comparison function of the general timer.