 Hi, this is Saig from STMicroelectronics. In this video, I'm going to show you how to generate runtime variable frequency PWM signals using STM32's Advanced Timer Preferal. The objective for this video is to generate PWM with variable frequency value transitions during runtime for applications such as smooth motor control. Just a side note, for accessing all the materials discussed in this video, please visit the link in the description. For this hands-on, you will need a Nucleo H745, a micro USB cable for connecting the board to the host, and an oscilloscope for measuring the output PWM signal with the inserted dead time. For my setup, I will be using a 200 MHz dual channel mixed oscilloscope. I'm going to briefly discuss the low level setup of variable frequency PWM configuration, although in the laboratory, we won't be needing to worry about all of these details. In order to allow for smooth frequency and 30-second switching, the STM32 timer features separate preload registers for ARR and CCR registers. The corresponding preload register must be enabled by setting the OCXPE bit in the timer CCMRX register, as well for the auto-reload preload register by setting the ARPE bit in the timer CR1 register. Enabling the preload register prevents the software from updating the output frequency and period when the timer is still forming comparison operations. For this hands-on, we're going to output a unique duty cycle for each complementary channel. Since each channel has its own compare register, we can define a unique duty cycle. Duty cycle is defined by the content of the compare register, and the frequency period is defined by the ARR with the auto-reload register, and there are one per timer profile. Therefore, there can only be one frequency across all channels. For this exercise, we'll use center-aligned PWM, given it has advantage of lower ripple generation and power wasting compared to edge-aligned PWM. This is useful for motor control or power electronic application, such as inverter control. We'll use a repetition counter of three, meaning an update event is generated each fourth overflow or underflow event depending on when the repetition counter was written. This will allow us to change the PWM frequency after a certain number of periods. Timer 1 will be selected for this application, because we need the complementary output. This table can be found in the datasheet. Now we're good to start the hands-on exercise. Using the STM32 QYDE, create a new STM32 project. Select the NUCLE H745 board for this exercise. File, New, STM32 Project. Type in STM32 H745, we're going to select this board here, click Next. Type in project name. My project name, I'm going to type in variable frequency PWM underscore demo. Click Finish. Set the H7 core clock to max value. This clock value is chosen arbitrary. Go to clock configuration, make this core 7 clock value to 400 mA. Go back to pen out and configuration tab. Select timers. Select one of the advanced timers. We'll go with time 1, because it can output complementary PWM signal. For runtime context, set it to Cortex M7, since we'll be running our code on the Cortex M7 core. We're going to choose complementary outputs. So go to channel 1. Change channel 1 to PWM generation, channel 1 and channel 1N. Do the same for channel 2 and 3. We will work with an arbitrary clock speed of 480 mHz, so set the pre-scaler to zero, and initialize the ARR register to 30,000. Change the pre-scaler to zero and change the counter period to 30,000. Change counter mode to center aligned mode 1. Because center aligned mode has lower noise and is better suited for motor control and power electronic control, the specific center alignment mode is not important here. So we just go with mode 1. Mode 1 just means capture event CCXIF flag is generated whenever the clock counter matches the capture compare register when it's down counting. Set the repetition counter to arbitrary value of 3 to change the frequency after every second period of current frequency. For channel 1, enter 25% of ARR for the pulse. 25% of 30,000 is 7,500. Leave the PWM mode as mode 1, because we want the output signal high when the timer counter is lower than the cap to compare register. For channel 2, enter 50% of ARR for pulse, so enter 15,000. For channel 3, enter 75% of ARR for pulse, so enter 22,500. As a last step, click on Invict Settings. Enable timer 1 interrupt to generate interrupt after each update event. When the repetition counter reaches 0, we change the frequency in a timer callback function. To make it easier for us to access these GPIO pins on our nuclear board, we're going to remap them into a different location. Hold the left control key and hold the left mouse key on the pin that you want to move. Now drag the same thing with these two pins. After finishing your IOC file configuration, click Device Configuration Tool and Core Generation. In the last step, you need to enable Complementary PWM generation, set up a state machine for changing between frequencies, and set up your interrupt callback function. In the link provided in the description, you'll come across a zip folder called Complementary Variable Frequency PWM, extracted here. Since we are working with the Cortex M7 project, our project will be located in this location. What is the Cortex M7? Core Source. This is the main file that we will compile and upload into our board. Open the file code to be added, and copy the code section to your main code in the Cortex M7 core project. First step, we're going to copy these micro definitions into our main.c. We're going to change the frequency on the fly, so we have to specify the value of the recycle when the ARR content changes. The finding these macros will allow us to easily change the recycle for each frequency. Now we will copy this global flag into our main.c. We define that timer auto-reload register flag, which is used for sequencing between frequencies of 4, 8, and 16 kHz. We use this flag in our callback function state machine. Next, we're going to copy these Hall APIs for starting the PWM generation into our main function in main.c. Main function, we're going to paste it here. First, we call the Hall API Timer IT because we want to receive interrupt after each up-to-event, where the repetition counter reaches zero. This is how we will change the frequency during one time. The rest of the Hall APIs shown here are used to start the PWM for regular channel and the complementary channel of time one. We call Hall PWM start and Hall PWM end start for each channel. Last step, we're going to copy the callback function and its state machine into our main code. In our callback function call, the global variable timer underscore ar underscore value is used as an input to our state machine so we can change between different frequencies. Here we have two Hall macro function used to update the auto-reload register and the capture compare register during one time. Before running our Cortex M7 project, we need to upload the Cortex M4 project image into our board. Else, the project on the Cortex M7 core will get stuck inside a loop. So click on the Cortex M4 core project, compile, make sure no errors or warnings. Okay, this looks fine. Now you can upload the code into the board, upload the image into the board. Okay, so our Cortex M4 image is now uploaded. So now we're ready to upload our Cortex M7 project next. Last step, compile the project and ensure there are no error or warnings. Now debug and flash your image into your nuclear board. Click resume and now your image is executing on your nuclear board. Connecting your pins to a oscilloscope, you should observe the recycle of 25 percent for channel one, 50 percent for channel two, and 75 percent for channel three. You will see frequency varying during one time from 4 kilohertz to 16 kilohertz. Relevant application nodes as well as reference manual and data sheet can be found in the following links. We hope you found this video helpful. Thank you very much for watching.