---
# System prepended metadata

title: '(志航)[STM32]序列埠通訊、外部中斷、窗口看門狗(WWDG)'

---

# (志航)  [STM32]序列埠通訊、外部中斷、窗口看門狗(WWDG)



## 實驗九-序列埠通訊 | 實驗十-外部中斷 | 實驗十二-窗口看門狗(WWDG)

### 序列埠通訊
:::success
USART（Universal Synchronous Asynchronous Receiver Transmitter，通用同步/異步收發器） 是嵌入式系統中兩種常見的通訊方式。
我們這邊使用的是Asynchronous（非同步模式）:發送端和接收端需要事先協商好一個固定的波特率來同步通信。
:::
***
#### 硬體設置
![螢幕擷取畫面 2024-10-14 154219](https://hackmd.io/_uploads/rJdasS5y1g.png)
![螢幕擷取畫面 2024-10-14 154057](https://hackmd.io/_uploads/rkk7hBqJye.png)
![S__241467397](https://hackmd.io/_uploads/rJUM6B9y1x.jpg)
PIN腳的TX,RX與GND分別接到USB轉TTL的RXD、TXD、GND
___
#### 主要程式碼

``` c= 
#include "string.h"
uint8_t Rxbuf[3];
uint16_t L[4]= {LD4_Pin, LD3_Pin, LD5_Pin, LD6_Pin};
int main(void)
{
    //啟動 UART DMA 接收
  HAL_UART_Receive_DMA(&huart1, Rxbuf, sizeof(Rxbuf));

  while (1)
  {

    if (strcmp((char *)Rxbuf, "FWD") == 0)  // 接收到 'FWD'，開啟正轉
            {
            	for (int i = 0; i < 4; i++) {

            			   HAL_GPIO_WritePin(GPIOD, L[i] , GPIO_PIN_SET);

            			   for (int j = 0; j < 4; j++) {
            				   if (i != j ) {
            					   HAL_GPIO_WritePin(GPIOD, L[j], GPIO_PIN_RESET);

            				   }
            			   }
            			   HAL_Delay(300); 

            			   HAL_GPIO_WritePin(GPIOD, L[i] , GPIO_PIN_RESET);
            			   HAL_Delay(300 );
            	           }
            }
            else if (strcmp((char *)Rxbuf, "REV") == 0)  // // 接收到 'REV'，開啟逆轉
            {
            	for (int i = 3; i >= 0; i--) {

            			   HAL_GPIO_WritePin(GPIOD, L[i] , GPIO_PIN_SET);


            			   for (int j = 0; j < 4; j++) {
            				   if (i != j ) {
            					   HAL_GPIO_WritePin(GPIOD, L[j], GPIO_PIN_RESET);

            				   }
            			   }
            			   HAL_Delay(300); 

            			   HAL_GPIO_WritePin(GPIOD, L[i] , GPIO_PIN_RESET);
            			   HAL_Delay(300 );
            	           }
            }
  }
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
    if (UartHandle->Instance == USART1)
    {
        // 顯示接收到的字元
    	printf("Input: %s\r\n", Rxbuf);

        // 重新啟動 UART 接收，以便繼續接收下一筆資料
        HAL_UART_Receive_DMA(&huart1, Rxbuf, sizeof(Rxbuf));
    }
}

```

#### 成果
{%youtube  p0gpIsDbMKI%}

---
### 外部中斷
:::success
外部中斷（External Interrupt）：通過外部硬件引腳觸發中斷。當指定的GPIO引腳發生邊沿變化，就會觸發中斷，MCU會暫停當前的任務，進入中斷服務程序
:::
___
#### 硬體設置

![螢幕擷取畫面 2024-10-14 161716](https://hackmd.io/_uploads/rJ3Vjv5JJg.png)
![螢幕擷取畫面 2024-10-18 140633](https://hackmd.io/_uploads/rJy42ukgkx.png)
![螢幕擷取畫面 2024-10-14 180421](https://hackmd.io/_uploads/SyCJpwqkJx.png)
___
#### 主要程式碼

打開stm32f4xx_it.c![螢幕擷取畫面 2024-10-14 174419](https://hackmd.io/_uploads/r1i_uD51Jg.png)

:::success
 ==HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)== 此回調函數可從下列路徑查詢使用
![螢幕擷取畫面 2024-10-14 174502](https://hackmd.io/_uploads/BkIWtv9kJe.png)
:::

``` c=
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == PB3_Pin)  // 確認是PB3引腳觸發的中斷
    {

        if (HAL_GPIO_ReadPin(GPIOB, PB3_Pin) == GPIO_PIN_SET)  // 如果PB3為高電平
        {
            for (int i = 0; i < 4; i++)
            {
                HAL_GPIO_WritePin(GPIOB, LD10_Pin, GPIO_PIN_SET);
                HAL_Delay(200);

                HAL_GPIO_WritePin(GPIOB, LD10_Pin, GPIO_PIN_RESET);
                HAL_Delay(200);
            }
        }

    }
}
```
main.c
``` c= 
int main(void)
{
  uint16_t L[4]= {LD4_Pin, LD3_Pin, LD5_Pin, LD6_Pin};
   while(1) {

    /* USER CODE END WHILE */
    MX_USB_HOST_Process();

    /* USER CODE BEGIN 3 */

	   for (int i = 0; i < 4; i++) {
		   if(HAL_GPIO_ReadPin(GPIOD, SW1_Pin) == 1){
		   HAL_GPIO_WritePin(GPIOD, L[i], GPIO_PIN_SET);
		   }
		   for (int j = 0; j < 4; j++) {
			   if (i != j && HAL_GPIO_ReadPin(GPIOD, SW1_Pin) == 1) {
				   HAL_GPIO_WritePin(GPIOD, L[j], GPIO_PIN_RESET);
			   }
		   }
		   HAL_Delay(200);
		   HAL_GPIO_WritePin(GPIOD, L[i], GPIO_PIN_RESET);
		   HAL_Delay(200);
           }
   }
}
```
___
#### 成果
{%youtube  DyOgAX2GwpQ%}

---
### 窗口看門狗(WWDG)
:::success
窗口看門狗定時器（WWDG）監控系統運行，必須在特定時間窗口內重置，否則將觸發復位。它提高系統穩定性，防止死循環或故障，廣泛應用於嵌入式系統和工業控制等領域。
:::
___
#### 硬體設置
![螢幕擷取畫面 2024-10-14 201033](https://hackmd.io/_uploads/HJA5oK91Je.png)
![螢幕擷取畫面 2024-10-14 204806](https://hackmd.io/_uploads/ByerXc9y1x.png)


![WWDG-TIME1](https://hackmd.io/_uploads/S18azGqykl.png)
![WWDG-TIME](https://hackmd.io/_uploads/r19MZItJ1g.png)
:::success
127(0x7F)：當 WWDG 開始工作時，計數器值通常被設置為 0x7F（127），這代表計數器的起始值。
63(0x3F)：當計數器倒數到 0x3F（63）時，如果程序沒有在窗口期內（即計數器值介於窗口值和 0x3F 之間）重置計數器，系統將觸發重啟。
:::
只有在Refresh allowed區間Refresh WWDG才不會系統重啟。 時間計算
#### 主要程式碼
``` c=
int main(void)
{
  HAL_GPIO_TogglePin(GPIOD, LD3_Pin);
while (1)
  {
    /* USER CODE END WHILE */
    MX_USB_HOST_Process();

    /* USER CODE BEGIN 3 */
    //(1/36000000)*4096*2^3*(127-80) ~ 44 ms Disable reloadin
    //(1/36000000)*4096*2^3*(80-63+1 ) ~ 16 ms
    //(1/36000000)*4096*2^3*(127-63+1) ~ 59 ms 44~59 ms Refresh WWDG
    //HAL_Delay(40);  //   Disable reloading
    HAL_Delay(50);    //   Normal, safe
    //HAL_Delay(65);  //   timeout, system reset
    HAL_WWDG_Refresh(&hwwdg);
    HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
  }
}
```
EarlyWakeupCallback : WWDG早期喚醒中斷回調函數
```c=
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg) {
    HAL_GPIO_TogglePin(LD6_GPIO_Port, LD6_Pin);
}
```
___
#### 成果
{%youtube  vgjF_HG_FRA%}
{%youtube  b0LyNaG5tO8%}
___

## **實驗進度**
- [x] 6-跑馬燈實驗
- [x] 7-蜂鳴器實驗
- [x] 8-按鈕輸入實驗
- [x] 9-序列埠通訊實驗
- [x] 10-外部中斷實驗
- [x] 12-窗口門狗(WWDG)實驗
- [ ] 13-定時器中斷實驗
- [ ] 14-PWN輸出實驗
- [ ] 16-電容觸摸按鍵實驗
- [ ] 18-TFTLCD顯示實驗
- [ ] 19-USMART調試組件實驗
- [ ] 20-RTC即時時鐘實驗
- [ ] 23-ADC實驗
- [ ] 29-IIC實驗
- [ ] 30-SPI實驗
- [ ] 36-DHT11數位溫濕度感測器實驗