---
# System prepended metadata

title: STM32F429 Discovery kit
tags: [STM32f429 Discovery kit, UART, USART, Micro controller unit, MCU, firmware]

---

# STM32F429 Discovery kit 
## Final Project Report


[TOC]

:::danger
**Misson :** Simulate board communication using UART and CAN BUS
:::

**本範例使用環境：**
* OS : Windows 10 
* IDE: eclipse(luna版本)
* 燒錄軟體: 內建ST-Link
* Terminal: hercules_3-2-8.exe
* 開發板：stm32f429 Discovery kit



## 成果截圖：
![](https://i.imgur.com/FSF9fuF.png)


## 1. OBC (on board computer)衛星電腦
1. 負責接收使用者**命令輸入** (UART)
2. 根據命令，傳送指令給EUCC (CAN)
3. 從EUCC接收其傳回之資料內容 (CAN)
4. 將收到之CAN資料即其他資訊印在Terminal上 (UART)

以下將依此四個步驟說明需要撰寫的程式碼：
### (1) Receive user command using **UART RX_interrupt**
在`main.c`：
   
``` C=
while(1){
	/////////// 1.Uart (Receive user command using interrupt)
	if(HAL_UART_Receive_IT(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK){
			//BSP_LED_On(LED3);
	}	
```
    
要注意的是：根據`RXBUFFERSIZE`決定**輸入資料長度**，若長度**小於**Size，則視為失敗，很可能會return `HAL_Timeout`
因此在一開始有規定使用者輸入的命令格式：
``` C=
  print_string("Command format: \"To x mode\" Type what mode(x) you want EUCC to transit to.\r\n");
```
在此專案長度為 **9 bytes**。
在`HAL_UART_OUT.h`中：
```c=
#define TXBUFFERSIZE              (9)//Unit:byte
```

### (2) Send data to EUCC using **RxCallback** 
(also print messages on terminal to inform user.)
:::info
在`HAL_UART_OUT.c`的`HAL_UART_RxCpltCallback`中：將extern的UART_send_flag設成1，回到main.c中CPU會進入以下function去執行**用CAN BUS傳送資料給EUCC**的任務。
:::
* Steps:
1. 在`HAL_UART_OUT.c`中：
```c=
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	/* Set transmission flag: transfer complete*/
	UART_send_flag = 1;
	//UsartReady_0 = SET;
	UsartReady_Rx = SET;
	/* Turn LED4 on: Transfer in reception process is correct */
	BSP_LED_On(LED3);

}
```

2. 在`main.c`的`STM32f4_UART_Init()`內補上：

``` C=
	  /////////// 2. Send data to EUCC using RxCallback(also print msg on terminal to inform user.)
	  if(UART_send_flag == 1){

		  //Switch case: aRxBuffer.
		  // Command format: To _ Mode (9 bytes)
		  /*
		  print_u8x(aRxBuffer[0]);
		  print_u8x(aRxBuffer[1]);
		  print_u8x(aRxBuffer[2]);
		  print_u8x(aRxBuffer[3]);
		  */

		  switch(aRxBuffer[3]){
		  case (uint8_t)0x32:
			  data = 0x02;
		  	  num = "2";
		  break;
		  case (uint8_t)0x33:
			  data = 0x03;
		  	  num = "3";
		  break;
		  case (uint8_t)0x34:
			  data = 0x04;
		  	  num = "4";
		  break;
		  case (uint8_t)0x35:
			  data = 0x05;
		  	  num = "5";
		  break;
		  case (uint8_t)0x36:
			  data = 0x06;
		  	  num = "6";
		  break;
		  case (uint8_t)0x31:
			  data = 0x01;
		  	  num = "1";
		  break;
		  default:
			  data = 0x02;
			  num = 2;
		  break;
		  }

		  print_string("\r\nOBC should send to EUCC by CAN:");
		  print_u8x(data);
		  print_string("EUCC should transfer to mode ");
		  print_string(num);
		  print_string("\r\n\n");
		  print_string("CAN sending...\r\n\n");
		  CanHandle.pTxMsg->Data[0] = data;// Data we wand to send to EUCC (opcode(4bits)+value(4bis))
			// Ex :0000 0010(Tell EUCC transition to Mode 2)
		  CanHandle.pTxMsg->StdId = 0x001;	// OBC -> EUCC : 0x0 01
		  CanHandle.pTxMsg->IDE = CAN_ID_STD;
		  CanHandle.pTxMsg->DLC = 1;		// Data length : only one byte.
		  // Send CAN.
		  if(HAL_CAN_Transmit(&CanHandle,0) != HAL_OK)
		  {
		  }
		  HAL_Delay(500);
//		  print_string("Turn off LED3\r\n");
		  BSP_LED_Off(LED3);
		  UART_send_flag = 0; // reset UART_send_flag.
	  }
```

### (3) CAN Receive data from EUCC Using **CAN1_RX0_IRQHandler** in `stm32f4xx_it.c`
Step1. In `main.c`，enable HAL_CAN_Receive_IT 
```c=
/////////// 3. CAN  Receive data from EUCC Using CAN1_RX0_IRQHandler in stm32f4xx_it.c
	if(HAL_CAN_Receive_IT(&CanHandle, CAN_FIFO0) != HAL_OK)
	{
		  /* Reception Error */
//		  Error_Handler();
	}
```
Step2. In `stm32f4xx_it.c`：

```c=
void CAN1_RX0_IRQHandler(void)
{
	// Get data from CAN
	if(CanHandle.pRxMsg->StdId == 0x101){	
        // Receive this data from EUCC.
		CAN_recieve_flag = 1;
	}
	HAL_CAN_IRQHandler(&CanHandle);
}
```
* 記得放在while(1){}內才可以一直從CAN取得資料喔~
* 不要放會無窮迴圈卡住的ERROR_HANDLER在裡面

### (4) UART **TX data to pc** using `print_string("str")`
```c=
/////////// 4. UART TX data to pc using print_string!!("....")
    if(CAN_recieve_flag == 1){
    	print_string("OBC received CAN from EUCC: ");
    	print_u8x(CanHandle.pRxMsg->Data[0]);
    	Opcode = CanHandle.pRxMsg->Data[0]>>4 & (uint8_t)0xF ;
    	value = CanHandle.pRxMsg->Data[0]  & (uint8_t)0x0F;
    	switch(value){
    		case 0x01:
    			print_string("EUCC ack! Mode transition done.");
			break;
    		case 0x00:
    			print_string("EUCC error... Mode transition failed.");
			break;
    		default:
    			print_string("Other messages(may because of loop_back mode: for practice only. Ack!");
    	    break;
    	}
    	CAN_recieve_flag = 0;	// Reset CAN_recieve flag.
    }
```
完整的`main.c`檔案：
(重點放在`while(1){...}`內部的code就可)

```C=
/**
  ******************************************************************************
  * @file    UART/UART_TwoBoards_ComPolling/Src/main.c 
  * @author  MCD Application Team
  * @version V1.2.5
  * @date    29-January-2016 
  * @brief   This sample code shows how to use STM32F4xx UART HAL API to transmit 
  *          and receive a data buffer with a communication process based on
  *          polling transfer. 
  *          The communication is done using 2 Boards.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "HAL_UART_out.h"
#include <stm32f4xx.h>
#include <stm32f4xx_hal_gpio.h>
#include <stm32f4xx_hal_rcc.h>

/** @addtogroup STM32F4xx_HAL_Examples
  * @{
  */

/** @addtogroup UART_TwoBoards_ComPolling
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//#define TRANSMITTER_BOARD 

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* UART handler declaration */
UART_HandleTypeDef UartHandle;

/* Buffer used for transmission */
uint8_t aTxBuffer[] = " **** UART_TwoBoards_ComPolling ****  **** UART_TwoBoards_ComPolling ****  **** UART_TwoBoards_ComPolling **** ";

/* Buffer used for reception */
uint8_t aRxBuffer[RXBUFFERSIZE];

/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void Error_Handler(void);
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval None
  */

// OBC :
////// UART //////
// PC-> OBC (Using Rx Interrupt)
// OBC-> PC (Using Tx Interrupt)

////// CAN //////	CAN_id.(Priority + toWho)
// 1. OBC ->EUCC	001
// 2. EUCC -> OBC	101

// EUCC :
////// CAN //////	CAN_id.
// 1. EUCC -> OBC	101	(1; to 01OBC)
// 2. EUCC -> XXX	2 _ _ (to who(id 2bits)
// 3. XXX -> EUCC	3 _ _ (to who(id 2bits)

// Other components.
////// CAN //////   CAN_id.
// 1. EUCC -> XXX
// 2. XXX -> EUCC

// 3. EUCC -> xTx  702 (7: Priority最低 | 02:xTx)



// TODO:
// 1.add CAN into UART projects!
// 2. Function1 : Send data (Send to Who, and send What)
// 3. Function2 : Receive data (Whether to receive this data)


// Mission : Mode transition.
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define KEY_PRESSED     0x01
#define KEY_NOT_PRESSED 0x00

__IO ITStatus UartReady = RESET;



/////// Define FSM states(of EUCC)
#define Mode1 0x01
#define Mode2 0x02
#define Mode3 0x03
#define Mode4 0x04
#define Mode5_1 0x05
#define Mode5_2 0x07
#define Mode6 0x06



/////////// OBC :
// UART -> RX from PC(user commands):
// CAN -> Send data to EUCC
// CAN -> Receive data from EUCC
// UART -> TX send received data to terminal(print to terminal).
volatile int CAN_recieve_flag = 0;
volatile int UART_send_flag = 0;
uint8_t data;
uint8_t Opcode;
uint8_t value;




int main(void)
{

  /* STM32F4xx HAL library initialization:
       - Configure the Flash prefetch, instruction and Data caches
       - Configure the Systick to generate an interrupt each 1 msec
       - Set NVIC Group Priority to 4
       - Global MSP (MCU Support Package) initialization
     */
  HAL_Init();
  
  /* Configure LED3 and LED4 */
  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);

  /* Configure the system clock to 180 MHz */
  SystemClock_Config();
//  init_GPIO();
  STM32f4_UART_Init(&UartHandle);
  print_string("UART init done.\r\n");
  print_string("Command format: \"To x mode\" Type what mode(x) you want EUCC to transit to.\r\n");
  //print_string("Test HAL_UART_Init == HAL_OK \r\n");

//  UART recieve: 3 inputs : 存放的Buffer指標  接收長度  和Timeout時


#ifdef TRANSMITTER_BOARD

  /* Configure USER Button */
  BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO);
  /* Wait for USER Button press before starting the Communication */
  while (BSP_PB_GetState(BUTTON_KEY) == RESET)
  {
  }
  
  /* The board sends the message and expects to receive it back */
  
  /*##-2- Start the transmission process #####################################*/  
  /* While the UART in reception process, user can transmit data through 
     "aTxBuffer" buffer */
  if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000)!= HAL_OK)
  {
    Error_Handler();   
  }
  
  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
  BSP_LED_On(LED3);
  HAL_Delay(200);
  BSP_LED_Off(LED3);
  
  /*##-3- Put UART peripheral in reception process ###########################*/  
  if(HAL_UART_Receive(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 5000) != HAL_OK)
  {
    Error_Handler();  
  }
    
  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
  BSP_LED_On(LED3);
  HAL_Delay(200);
  BSP_LED_Off(LED3);
  
#else
  


  ///////////// CAN initializations //////////////

  /**
    * @brief  Main program
    * @param  None
    * @retval None
    */


    /* STM32F4xx HAL library initialization:
         - Configure the Flash prefetch, instruction and Data caches
         - Configure the Systick to generate an interrupt each 1 msec
         - Set NVIC Group Priority to 4
         - Global MSP (MCU Support Package) initialization
       */
    /*__attribute__ ((aligned (8))) */uint32_t txbox_num;
    ubKeyNumber = 0x0;
    RxMessagePending_flag = 0;
    totle_track_num = 0;

    uint8_t press_cnt = 0;

    /*STM32f4_UART_DMA_Init(&UartHandle);*/


    /* Configure Key Button */
    BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO);
    /*##-1- Configure the CAN peripheral #######################################*/
//    STM32f4_UART_DMA_Init(&UartHandle);

    //CAN_Config();
    STM32f4_CAN_Init(&CanHandle, &sFilterConfig, &TxMessage, &RxMessage);

    /*print_string_DMA("\r\n(1)\r\n");
    print_string_DMA("TX mailbox identifier register:");
    print_u32x_DMA(CanHandle.Instance->sTxMailBox[0].TIR);
    print_string_DMA("InterruptEnableReg:");
    print_u32x_DMA(CanHandle.Instance->IER);*/



    /*##-2- Start the Reception process and enable reception interrupt #########*/

    /* Infinite loop */
    /*print_string_DMA("(2)\r\n");
    print_string_DMA("ErrStateReg:");
    print_u32x_DMA(CanHandle.Instance->ESR);
    print_string_DMA("InterruptEnableReg:");
    print_u32x_DMA(CanHandle.Instance->IER);
    print_string_DMA("BUTTON State:");
    print_u32x_DMA(BSP_PB_GetState(BUTTON_KEY));

    print_string_DMA("(3)\r\n");*/


  	  /*!< Pointer to transmit structure */
  //	  while(BSP_PB_GetState(BUTTON_KEY) == KEY_PRESSED)
  //	  {
//  		  press_cnt = 0;
//  		  CanHandle.pTxMsg->StdId = 0x001;	// OBC -> EUCC : 0x0 01
//  		  CanHandle.pTxMsg->IDE = CAN_ID_STD;
//  		  CanHandle.pTxMsg->DLC = 1;		// Data length : only one byte.
//  		  CanHandle.pTxMsg->Data[0] = 0x02; // Data we wand to send to EUCC (opcode(4bits)+value(4bis))
//  		  // Ex :0000 0010(Tell EUCC transition to Mode 2)
//  		  // Send message.
//  		  if(HAL_CAN_Transmit(&CanHandle,10) != HAL_OK)
//  		  {
//
//  		  }
//  		  HAL_Delay(500);
  		  // delay 0.5sec ///

  ///////////////////////////////////////////////
	 while(1){
		/////////// 1.Uart (Receive user command using interrupt)
		 if(HAL_UART_Receive_IT(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK){
			 	 //BSP_LED_On(LED3);
		 }

	  // Receive data from User.

	  char* num;
	  HAL_Delay(500);
	  /////////// 2. Send data to EUCC using RxCallback(also print msg on terminal to inform user.)
	  if(UART_send_flag == 1){

		  //Switch case: aRxBuffer.
		  // Command format: To _ Mode (9 bytes)
		  /*
		  print_u8x(aRxBuffer[0]);
		  print_u8x(aRxBuffer[1]);
		  print_u8x(aRxBuffer[2]);
		  print_u8x(aRxBuffer[3]);
		  */

		  switch(aRxBuffer[3]){
		  case (uint8_t)0x32:
			  data = 0x02;
		  	  num = "2";
		  break;
		  case (uint8_t)0x33:
			  data = 0x03;
		  	  num = "3";
		  break;
		  case (uint8_t)0x34:
			  data = 0x04;
		  	  num = "4";
		  break;
		  case (uint8_t)0x35:
			  data = 0x05;
		  	  num = "5";
		  break;
		  case (uint8_t)0x36:
			  data = 0x06;
		  	  num = "6";
		  break;
		  case (uint8_t)0x31:
			  data = 0x01;
		  	  num = "1";
		  break;
		  default:
			  data = 0x02;
			  num = 2;
		  break;
		  }

		  print_string("\r\nOBC should send to EUCC by CAN:");
		  print_u8x(data);
		  print_string("EUCC should transfer to mode ");
		  print_string(num);
		  print_string("\r\n\n");
		  print_string("CAN sending...\r\n\n");
		  CanHandle.pTxMsg->Data[0] = data;// Data we wand to send to EUCC (opcode(4bits)+value(4bis))
			// Ex :0000 0010(Tell EUCC transition to Mode 2)
		  CanHandle.pTxMsg->StdId = 0x001;	// OBC -> EUCC : 0x0 01
		  CanHandle.pTxMsg->IDE = CAN_ID_STD;
		  CanHandle.pTxMsg->DLC = 1;		// Data length : only one byte.
		  // Send CAN.
		  if(HAL_CAN_Transmit(&CanHandle,0) != HAL_OK)
		  {
		  }
		  HAL_Delay(500);
//		  print_string("Turn off LED3\r\n");
		  BSP_LED_Off(LED3);
		  UART_send_flag = 0; // reset UART_send_flag.
	  }
	  /////////// 3. CAN  Receive data from EUCC Using CAN1_RX0_IRQHandler in stm32f4xx_it.c
		if(HAL_CAN_Receive_IT(&CanHandle, CAN_FIFO0) != HAL_OK)
		{
		  /* Reception Error */
//		  Error_Handler();
		}
	/////////// 4. UART TX data to pc using print_string!!("....")
    if(CAN_recieve_flag == 1){
    	print_string("OBC received CAN from EUCC: ");
    	print_u8x(CanHandle.pRxMsg->Data[0]);
    	Opcode = CanHandle.pRxMsg->Data[0]>>4 & (uint8_t)0xF ;
    	value = CanHandle.pRxMsg->Data[0]  & (uint8_t)0x0F;
    	switch(value){
    		case 0x01:
    			print_string("EUCC ack! Mode transition done.");
			break;
    		case 0x00:
    			print_string("EUCC error... Mode transition failed.");
			break;
    		default:
    			print_string("Other messages(may because of loop_back mode: for practice only. Ack!");
    	    break;
    	}
    	CAN_recieve_flag = 0;	// Reset CAN_recieve flag.
    }


}// end while()



	 /////////// TODOs:
	 // 1. Change HAL_CAN_INIT.c to ... mode
	 // 2. In CAN1_RX0_IRQ : set ' if(.. .stdID==0x101) from EUCC->OBC
	 // 3.




  /* The board receives the message and sends it back */



  //print_string("HAL_UART_Receive(&UartHandle, ...) Done.\r\n");
  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
//  HAL_Delay(200);
//  BSP_LED_Off(LED3);
//  HAL_Delay(200);
//  print_string("Toggled LED3.\r\n");
  /*##-3- Start the transmission process #####################################*/  
  /* While the UART in reception process, user can transmit data through 
     "aTxBuffer" buffer */



  if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000)!= HAL_OK)
  {
    Error_Handler();
  }

  print_string("HAL_UART_Transmit.. Done.\r\n");
  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
  BSP_LED_On(LED3);
  HAL_Delay(200);
  BSP_LED_Off(LED3);
  
#endif /* TRANSMITTER_BOARD */
  



  /*##-4- Compare the sent and received buffers ##############################*/
  // If aTxBuffer != aRxBuffer in content, go to Error_Handler().
  if(Buffercmp((uint8_t*)aTxBuffer,(uint8_t*)aRxBuffer,RXBUFFERSIZE))
  {
    Error_Handler();  
  }
  
}	//end main()







/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 180000000
  *            HCLK(Hz)                       = 180000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 4
  *            APB2 Prescaler                 = 2
  *            HSE Frequency(Hz)              = 8000000
  *            PLL_M                          = 8
  *            PLL_N                          = 360
  *            PLL_P                          = 2
  *            PLL_Q                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale1 mode
  *            Flash Latency(WS)              = 5
  * @param  None
  * @retval None
  */


void init_GPIO()
{
	GPIO_InitTypeDef GPIO_InitStruct = {
		.Pin = GPIO_PIN_13| GPIO_PIN_14,
		.Mode = GPIO_MODE_OUTPUT_PP,
		.Speed = GPIO_SPEED_FREQ_VERY_HIGH,
		.Pull =GPIO_PULLDOWN
	};
	__HAL_RCC_GPIOG_CLK_ENABLE();
//	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);

	HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
}






static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /* The voltage scaling allows optimizing the power consumption when the device is 
     clocked below the maximum system frequency, to update the voltage scaling value 
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  
  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 360;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /* Activate the Over-Drive mode */
  HAL_PWREx_EnableOverDrive();
 
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief  UART error callbacks
  * @param  UartHandle: UART handle
  * @note   This example shows a simple way to report transfer error, and you can
  *         add your own implementation.
  * @retval None
  */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
{
  /* Turn LED4 on: Transfer error in reception/transmission process */
  BSP_LED_On(LED4); 
}

/**
  * @brief  Compares two buffers.
  * @param  pBuffer1, pBuffer2: buffers to be compared.
  * @param  BufferLength: buffer's length
  * @retval 0  : pBuffer1 identical to pBuffer2
  *         >0 : pBuffer1 differs from pBuffer2
  */
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
  while (BufferLength--)
  {
    if ((*pBuffer1) != *pBuffer2)
    {
      return BufferLength;
    }
    pBuffer1++;
    pBuffer2++;
  }

  return 0;
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* Turn LED4 on */

//  BSP_LED_On(LED4);
  while(1)
  {
	  HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_14);
	  HAL_Delay(500);
  }
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


```

## 2. 其他初始化或細節注意

:::warning
**提醒**：在使用模擬的Terminal console時，要記得：
1.baurate    (此範例為9600)
2.STOP bit(此範例為1)
3.Parity bit(此範例為None)
等設定要跟你`UART_Init()`內的設定一樣才能有效傳輸喔!
:::

1. 自己測自己時(`silent_loopback_mode`)記得CAN的IRQ判斷CAN_ID要註解掉
2. 辛苦了，想到再補上QQ

## 3. 週三實測報告
星期三晚上我們進行板子對接實際測試
因為tranceiver數量不夠，最多只能一次接上三塊版子
我們實驗：OBC - EUCC - FPA

有些地方要改：
:::success
1. CAN 模式改成： **Normal mode.** (原Loopback mode)
2. CAN1_Rx0_IRQ() 內要設if(CanHandle.pRxMsg->StdId == 0x101)來阻擋不該收的CAN資料
3. 把原本while內的CAN_Transmit改成放在Can_RxCallback才開啟，才不會一直把interrupt打開，(已經打開了!)再開會當掉。
:::

後來嘗試：最多成功(穩定的)是單向的傳輸(從OBC->EUCC->FPA)
我們有用VarViewr看，有時候OBC居然會吃到EUCC要傳給FPA的CAN資料
實在不合常理(因為有設阻擋)
最後猜測是UART跟CAN寫在一起時有些沒考慮到的問題沒解決。

###### tags: `STM32f429 Discovery kit` `UART` `USART` `Micro controller unit` `MCU` `firmware`