# PWM ## PWM Output ![image](https://hackmd.io/_uploads/rkwZBVDTT.png =x160) ### Project Settings 1. In **System Core → RCC**, set **High Speed Clock (HSE)** as **Crystal/Ceramic Resonator** ![image](https://hackmd.io/_uploads/B1h4H4DpT.png =x250) 2. On the Nucleo board, check the frequency written on this metal chip, in this case it is **8.000mHz** ![image](https://hackmd.io/_uploads/SyODHVw66.png =x200) Then, in **Clock Configuration**, set **Input Frequency** as the value on the chip ![image](https://hackmd.io/_uploads/H1cYr4vp6.png =x200) 3. Set **PLL Source Mux** as **HSE**, **System Clock Mux** as **PLLCLK** and **HCLK** value as you wanted, in this case, we use 80 MHz ![image](https://hackmd.io/_uploads/BJFsBNP6T.png) 4. Choose a Timer and a channel and its corresponding pin. In this case, we choose **Timer 1** and **Channel 1** which uses the **PA8** pin ![image](https://hackmd.io/_uploads/ry96rNDTT.png =x200) In **Timers → TIM1** settings, set **Clock Source** as **Internal Clock** ![image](https://hackmd.io/_uploads/BJDk8NPp6.png =x200) In **TIM1** settings, set **Channel1** as **PWM Generation CH1** ![image](https://hackmd.io/_uploads/S1g-LEw6a.png =x200) 5. Look up **Block Diagram** in the [datasheet](https://www.st.com/resource/en/datasheet/stm32f401re.pdf) of your board and check the timer belongs to which peripheral In this case, **Timer 1** is connectec to **APB2** ![image](https://hackmd.io/_uploads/H1jGIEPpa.png =x300) 6. Back to **Clock Settings**, check the timer frequency of the peripheral In this case, the timer frequency of **APB2** is 80 MHz ![image](https://hackmd.io/_uploads/rkVEI4wap.png =x250) 7. Now we need to focus on three important parameters of PWM settings such as **Timer clock**, **PWM frequency**, and **Duty cycle** - **Timer clock** $=\frac{Original\ timer\ clocks}{Prescaler+1}$ - **PWM frequency** $=\frac{Timer\ clock}{Counter\ period+1}$ - **Duty cycle** $=\frac{CCRX}{Counter\ period}\times 100\%$ In our case, we set: - **Timer clock** $=1\ MHz=\frac{80\ MHz}{80}\Rightarrow Prescaler=(80-1)$ - **PWM frequency** $=10 kHz=\frac{1\ MHz}{100}\Rightarrow Counter\ period=(100-1)$ Set the parameters in **TIM1 → Parameters setting** ![image](https://hackmd.io/_uploads/HyVI84Dpa.png =x200) We will control the **Duty cycle** later in the programming part 8. (Optional) Add a new **DMA Request** (Direct Memory Access) and Choose the ![image](https://hackmd.io/_uploads/Hk6D8Nv66.png =x200) And set the **direction** to **Memory to Peripheral** ![image](https://hackmd.io/_uploads/SkrF8NvTT.png =x200) 9. Save and generate the project --- ### Programming In this section, we also use **TIM1 Channel 1** for example 1. To set the **Duty Cycle**, use: ```cpp TIM1->CCR1 = 50 // timer 1, channel 1, duty cycle 50% ``` 2. To start the PWM mode, use: ```cpp HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); ``` (Optional) Use DMA (Direct Memory Access) to start the PWM mode, use the following code instead ```cpp uint16_t pwmData[3]; pwmData[0] = 0; pwmData[1] = 50; pwmData[2] = 100; HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)pwmData, 3); ``` ## PWM Input (Fill this up later) ## Reference - [It takes two minutes to generate PWM signal in STM32](https://www.youtube.com/watch?v=9bpMReVEVzM&ab_channel=SteppeSchool) - [STM32 TIMERS #1. PWM Output || DMA](https://www.youtube.com/watch?v=OwlfFp8fPN0&list=PLfIJKC1ud8gjLZBzjE3kKBMDEH_lUc428) - [STM32 TIMERS #2. PWM Input](https://www.youtube.com/watch?v=P6211ic2N_s&list=PLfIJKC1ud8gjLZBzjE3kKBMDEH_lUc428&index=4&pp=iAQB)