# PWM
## PWM Output

### Project Settings
1. In **System Core → RCC**, set **High Speed Clock (HSE)** as **Crystal/Ceramic Resonator**

2. On the Nucleo board, check the frequency written on this metal chip, in this case it is **8.000mHz**

Then, in **Clock Configuration**, set **Input Frequency** as the value on the chip

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

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

In **Timers → TIM1** settings, set **Clock Source** as **Internal Clock**

In **TIM1** settings, set **Channel1** as **PWM Generation CH1**

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**

6. Back to **Clock Settings**, check the timer frequency of the peripheral
In this case, the timer frequency of **APB2** is 80 MHz

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**

We will control the **Duty cycle** later in the programming part
8. (Optional) Add a new **DMA Request** (Direct Memory Access) and Choose the

And set the **direction** to **Memory to Peripheral**

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)