# STM32 & C/C++ 常用程式語法
## C/C++
### 基本符號
- {} 大括號
- () 小括號
- = 等於
- ! 驚嘆號
- & and
- ; 分號
### 變數
- 用來儲存資料的容器
- 有分不同型態
- int 整數 ex. 1, 2, 3...
- float/double 浮點數(小數) ex. 1.2, 1.3, 1.4...
### if/else - 如果... 就... 不然就...
- 布林運算
- && - 且(兩個都是對的才成立)
- || - 或(只要有一個是對的就成立)
- 條件判斷
- == - 等於
- != - 不等於
### 迴圈 - 不斷執行
- while
- while(條件){執行內容}
- for
- for(變數初始化;直到什麼狀況;變數怎麼變){執行內容}
## STM32 基礎程式架構
- 東西放在 Begin - End 中間!!
- 主要程式放在 main 裡
- 大約在 70 行上下
- 要不斷執行的放在 **main** 裡的 while 中 (約在105行上下)
- 中斷那些東西可以放在 USER CODE 4 中
- 約在 360 行上下
## GPIO
::: warning
放在 MX_GPIO_Init(); 後面
:::
### 輸出 高/低 電位
- 三個參數記得改!
- 英文編號, 數字編號, 高 or 低
```Cpp=
HAL_GPIO_WritePin(GPIOx, GPIO_PIN_x, GPIO_PIN_SET/GPIO_PIN_RESET);
```
輸出 上次相反 電位
```Cpp=
HAL_GPIO_TogglePin(GPIOx, GPIO_PIN_x);
```
### 接收輸入電位
- 回傳 高(1) or 低(0)
```Cpp=
HAL_GPIO_ReadPin(GPIOx, GPIO_PIN_x);
```
::: warning
放在 MX_GPIO_Init(); 後面
:::
## EXTI 外部中斷
- 放在 USER CODE 4 中(約在 360 行上下)
```Cpp=
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == GPIO_PIN_x){
// 執行內容
}
}
```
## Timer 中斷
- 頻率公式
$$
f_{out} = \frac{f_{clk}}{(PSC+1)(ARR+1)}
$$
$f_{out}$: PWM 訊號頻率
$f_{clk}$: STM32 晶片時脈信號頻率, 170*1000000 Hz for G431RB
- 放在 USER CODE 2 中(約在 96 行上下)
```Cpp=
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htimx);
/* USER CODE END 2 */
```
- 放在 USER CODE 4 中(約在 360 行上下)
```Cpp=
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if (htim -> Instance == TIMx){
// 執行內容
}
}
/* USER CODE END 4 */
```
## 輸出 PWM 訊號
- 頻率公式
$$
f_{out} = \frac{f_{clk}}{(PSC+1)(ARR+1)}
$$
$f_{out}$: PWM 訊號頻率
$f_{clk}$: STM32 晶片時脈信號頻率, 170*1000000 Hz for G431RB
- 工作週期
$$
Duty\ cycle = \frac{Pulse}{ARR+1} \times 100\%
$$
- 放在 USER CODE 2 中(約在 96 行上下)
```Cpp=
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_x);
/* USER CODE END 2 */
```
- 要改變 Pulse
```Cpp=
__HAL_TIM_SET_COMPARE(&htimx, TIM_CHANNEL_x, Pulse值);
```
- 要改變 ARR
```Cpp=
__HAL_TIM_SET_AUTORELOAD(&htimx, ARR值);
```
## Encoder 編碼器讀取
- 放在 USER CODE 2 中(約在 96 行上下)
```Cpp=
/* USER CODE BEGIN 2 */
// 有用到的 Channel 都要填
HAL_TIM_Encoder_Start(&htimx, TIM_CHANNEL_a);
HAL_TIM_Encoder_Start(&htimx, TIM_CHANNEL_b);
/* USER CODE END 2 */
```
- 讀取 Encoder 值
```Cpp=
__HAL_TIM_GetCounter(&htimx);
```
- 賦予 Encoder 值
```Cpp=
__HAL_TIM_SetCounter(&htimx, 賦予的值);
```
## NUCLEO-G431RB 腳位圖
