cancel
Showing results for 
Search instead for 
Did you mean: 

DMA with UART

Anesh
Associate III

Hello,

I am trying to implement Modbus protocol in an efficient way. Untill now I have implemented everhting with UART interuot based Transmission and recption. Now I would like to implement with DMA to offload controller from much neavy lifting. For your refernce, I somhow managed with the below code t transfer the TX_Array from 0x00 to 0x09. I verified this in oscilloscope. But this aimed frame is appearing only once then only 0x00 is seen infinitely. even DE pin is not driven to low. Which indicateds that ISR is not being called and transfer is not stopped. Or somewhere it make the controoller to hang. Please let me know where I am makeing mistakes.

Please pardon me, I will come back again for RX implementation after fixing this issue. Thank you.

 
#include <stdint.h>
 
#include "stm32f030x8.h"
 
#define Set_USART1_BRR (40000000/9600) // 9600 Baudrate
#define Set_Parity 0x01 // EVen
 
#define Switch_Reset_LED_ON (GPIOB->BSRR = GPIO_BSRR_BS_10) // PB10 (Set pin)
#define Switch_Status_LED_ON (GPIOB->BSRR = GPIO_BSRR_BS_4) // PB4 (Set pin)
#define Switch_RXD_LED_ON (GPIOB->BSRR = GPIO_BSRR_BS_3) // PB3 (Set pin)
#define Switch_TXD_LED_ON (GPIOA->BSRR = GPIO_BSRR_BS_15) // PA15 (Set pin)
 
#define Switch_Reset_LED_OFF (GPIOB->BSRR = GPIO_BSRR_BR_10) // PB10 (Set pin)
#define Switch_Status_LED_OFF (GPIOB->BSRR = GPIO_BSRR_BR_4) // PB4 (Set pin)
#define Switch_RXD_LED_OFF (GPIOB->BSRR = GPIO_BSRR_BR_3) // PB3 (Set pin)
#define Switch_TXD_LED_OFF (GPIOA->BSRR = GPIO_BSRR_BR_15) // PA15 (Set pin)
 
#define CLEAR_DE (GPIOB->ODR &= ~(1 << 5));
#define SET_DE (GPIOB->ODR |= (1 << 5));
 
void Config_System_Clock(void);
void Init_GPIOs(void);
void USART1_Init(void);
void MB_RTU_Transmit(volatile uint8_t *data, uint16_t length);
void Init_Tim14_1ms(void);
void delay_ms(uint32_t ms);
 
volatile uint32_t ms_Ticks;
volatile uint8_t Tick_1ms;
volatile uint8_t TX_Array[10]={0}, RX_Array[10]={0};
 
int main(void)
{
Config_System_Clock();
Init_GPIOs();
USART1_Init();
Init_Tim14_1ms();
 
for (uint8_t i = 0; i < 10; ++i) { TX_Array[i] = i; }
 
while(1)
{
//Switch_Reset_LED_ON; delay_ms(500);
//Switch_Reset_LED_OFF; delay_ms(500);
 
//SET_DE; delay_ms(10);
MB_RTU_Transmit(TX_Array, 10);
//delay_ms(100);
//CLEAR_DE; delay_ms(10);
}
}
 
void Init_GPIOs(void)
{
RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // Enable GPIOA clock
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // Enable GPIOB clock
RCC->AHBENR |= RCC_AHBENR_GPIOCEN; // Enable GPIOC clock
 
/* Settings for ONB_Reset_LED: PB10 */
GPIOB->MODER &= ~GPIO_MODER_MODER10;                // Clear mode for PB10
GPIOB->MODER |= GPIO_MODER_MODER10_0;              // Set as Output (01)
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_10;                // Push-pull (0)
GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEEDR10;          // Clear speed for PB10
GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR10_0;        // Medium speed (01)
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR10;                // No pull-up, no pull-down (00)
 
/* Settings for ONB_Status_LED: PB4 */
GPIOB->MODER &= ~GPIO_MODER_MODER4;                // Clear mode for PB4
GPIOB->MODER |= GPIO_MODER_MODER4_0;              // Set as Output (01)
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_4;                // Push-pull (0)
GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEEDR4;          // Clear speed for PB4
GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR4_0;        // Medium speed (01)
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR4;              // No pull-up, no pull-down (00)
 
/* Settings for ONB_RXD_LED: PB3 */
GPIOB->MODER &= ~GPIO_MODER_MODER3;                // Clear mode for PB3
GPIOB->MODER |= GPIO_MODER_MODER3_0;              // Set as Output (01)
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_3;                // Push-pull (0)
GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEEDR3;          // Clear speed for PB3
GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR3_0;        // Medium speed (01)
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR3;                // No pull-up, no pull-down (00)
 
/* Settings for ONB_TXD_LED: PA15 */
GPIOA->MODER &= ~GPIO_MODER_MODER15;                // Clear mode for PA15
GPIOA->MODER |= GPIO_MODER_MODER15_0;              // Set as Output (01)
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_15;                // Push-pull (0)
GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEEDR15;          // Clear speed for PA15
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR15_0;        // Medium speed (01)
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR15;                // No pull-up, no pull-down (00)
}
 
void USART1_Init(void)
{
    // 1. Enable clocks for GPIOB, USART1, and DMA1
    RCC->AHBENR  |= RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMA1EN;
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
 
    // 2. --- Configure PB5 as DE output ---
    GPIOB->MODER   &= ~(3 << (5 * 2));
    GPIOB->MODER   |=  (1 << (5 * 2));       // Output mode
    GPIOB->OTYPER  &= ~(1 << 5);             // Push-pull
    GPIOB->OSPEEDR |=  (3 << (5 * 2));       // High speed
    GPIOB->PUPDR   &= ~(3 << (5 * 2));       // No pull
    GPIOB->ODR     &= ~(1 << 5);             // Set DE LOW (receive mode)
 
    // 3. --- Configure PB6 as USART1_TX (AF0) ---
    GPIOB->MODER   &= ~(3 << (6 * 2));
    GPIOB->MODER   |=  (2 << (6 * 2));       // Alternate function
    GPIOB->OTYPER  &= ~(1 << 6);             // Push-pull
    GPIOB->OSPEEDR |=  (3 << (6 * 2));       // High speed
    GPIOB->PUPDR   &= ~(3 << (6 * 2));
    GPIOB->PUPDR   |=  (1 << (6 * 2));       // Pull-up
    GPIOB->AFR[0]  &= ~(0xF << (6 * 4));
    GPIOB->AFR[0]  |=  (0x0 << (6 * 4));     // AF0 = USART1
 
    // 4. --- Configure USART1 ---
    USART1->CR1 &= ~USART_CR1_UE;            // Disable USART1
    USART1->BRR  = Set_USART1_BRR;           // Set baud rate
 
    switch (Set_Parity)
    {
        case 0: // 8N2 (No parity)
            USART1->CR1 &= ~USART_CR1_PCE;
            USART1->CR1 &= ~USART_CR1_M;
            USART1->CR2 &= ~USART_CR2_STOP;
            USART1->CR2 |= USART_CR2_STOP_1 | USART_CR2_STOP_0; // 2 stop bits
            break;
        case 1: // 8E1 (Even parity)
            USART1->CR1 |=  USART_CR1_PCE;
            USART1->CR1 &= ~USART_CR1_PS;
            USART1->CR1 |=  USART_CR1_M;
            USART1->CR2 &= ~USART_CR2_STOP;
            break;
        case 2: // 8O1 (Odd parity)
            USART1->CR1 |=  USART_CR1_PCE;
            USART1->CR1 |=  USART_CR1_PS;
            USART1->CR1 |=  USART_CR1_M;
            USART1->CR2 &= ~USART_CR2_STOP;
            break;
    }
 
    USART1->CR3 |= USART_CR3_DMAT;  // Enable DMA TX
 
    USART1->CR1 |= USART_CR1_TE;    // Enable Transmit
    USART1->CR1 |= USART_CR1_UE;    // Enable USART1
 
    // 5. --- Configure DMA1 Channel 2 for USART1_TX ---
 
    DMA1_Channel2->CCR &= ~DMA_CCR_EN;             // Step 0: Disable channel first
 
    DMA1_Channel2->CPAR = (uint32_t)&USART1->TDR;  // Step 1: Peripheral address
 
    // Steps 2 & 3 (CMAR and CNDTR) will be configured during DMA transfer start
 
    DMA1_Channel2->CCR = 0;  // Clear all settings
 
    // Step 4: Configure CCR
    DMA1_Channel2->CCR |= DMA_CCR_MINC      // Increment memory address
                        | DMA_CCR_DIR       // Read from memory to peripheral
                        | DMA_CCR_TCIE      // Transfer complete interrupt
                        | DMA_CCR_PL_1;     // High priority (PL = 2)
 
    NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);   // Step 5: Enable interrupt for DMA
}
 
void MB_RTU_Transmit(volatile uint8_t *data, uint16_t length)
{
    SET_DE;
DMA1_Channel2->CCR &= ~DMA_CCR_EN;         // Step 0: Disable
 
    DMA1_Channel2->CMAR  = (uint32_t)data;     // Step 2: Memory address
    DMA1_Channel2->CNDTR = length;             // Step 3: Data length
 
    DMA1_Channel2->CCR |= DMA_CCR_EN;          // Step 5: Enable DMA channel
}
 
void DMA1_Channel2_3_IRQHandler(void)
{
    if (DMA1->ISR & DMA_ISR_TCIF2)              // Check if transfer is complete
    {
        DMA1->IFCR |= DMA_IFCR_CTCIF2;         // Clear Transfer Complete flag
 
        DMA1_Channel2->CCR &= ~DMA_CCR_EN;     // Disable DMA after transmission
 
        CLEAR_DE;  // Optionally reset DE pin (back to receive mode)
    }
}
 
void Init_Tim14_1ms(void)
{
    RCC->APB1ENR |= RCC_APB1ENR_TIM14EN;
 
    TIM14->PSC = 39;
    TIM14->ARR = 999;
    TIM14->CNT = 0;
 
    TIM14->SR &= ~TIM_SR_UIF;           // Clear any pending flag
    TIM14->DIER |= TIM_DIER_UIE;        // Update interrupt enable
    TIM14->CR1 |= TIM_CR1_CEN;          // Counter enable
 
    NVIC_EnableIRQ(TIM14_IRQn);         // Enable IRQ in NVIC
}
 
 
void TIM14_IRQHandler(void)
{
    if (TIM14->SR & TIM_SR_UIF)
    {
    //Switch_Status_LED_ON;
    TIM14->SR &= ~TIM_SR_UIF;
        ms_Ticks++;
        Tick_1ms=1;
        //Switch_Status_LED_OFF;
    }
}
 
void delay_ms(uint32_t ms)
{
    uint32_t start = ms_Ticks;
    while ((ms_Ticks - start) < ms);
}
 
void Config_System_Clock(void)
{
    // 1. Enable HSE (High Speed External oscillator)
    RCC->CR |= RCC_CR_HSEON;
    while ((RCC->CR & RCC_CR_HSERDY) == 0); // Wait for HSE ready
 
    // 2. Configure PLL
    // PLL source = HSE, PLL multiplier = 5
    RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL); // Clear PLL config
    RCC->CFGR |= RCC_CFGR_PLLSRC_HSE_PREDIV | RCC_CFGR_PLLMUL5; // HSE / 1 * 5
 
    // 3. Enable PLL
    RCC->CR |= RCC_CR_PLLON;
    while ((RCC->CR & RCC_CR_PLLRDY) == 0); // Wait for PLL ready
 
    // 4. Select PLL as system clock
    RCC->CFGR &= ~RCC_CFGR_SW;
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait until PLL used as system clock
}

 

16 REPLIES 16
Carl_G
Senior II

Oh, so you are expecting the one good transmit then it should stop? But it keeps going with bad data?

Anesh
Associate III

Yes, I expect one com[plete frame (mentioned by the length) must be transmitted and then stopped.

I modified the code and call initiate the transmission inside while (1) loop once in 25 nilli seconds. 

As per my understanding and oscilloscope plots. It stops after 10 elements. when I just restart the micro controller. Later, no more tranmissions.

	while(1)
	{
		//for (uint16_t temp = 0; temp < 1000; ++temp);

		MB_RTU_Transmit(TX_Array, 10);
		delay_ms(25);
	}
}

 

Buit it is not restarting. Also I think it does not reach the ISR. Because I make teh DE pin to go Low there. Also I make an Reset LED to turn on for checking. But these commands are not excecuted.

void DMA1_Channel2_3_IRQHandler(void)
{
    if (DMA1->ISR & DMA_ISR_TCIF2)              // Check if transfer is complete
    {
        DMA1->IFCR |= DMA_IFCR_CTCIF2;         // Clear Transfer Complete flag

        //DMA1_Channel2->CCR &= ~DMA_CCR_EN;     // Disable DMA after transmission

        CLEAR_DE;  // Optionally reset DE pin (back to receive mode)

        Switch_Reset_LED_ON;
    }
}

 

I have the plot too.

 

For more info I share you my init function

void USART1_Init(void)
{
    // 1. Enable clocks for GPIOB, USART1, and DMA1
    RCC->AHBENR  |= RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMA1EN;
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

    // 2. --- Configure PB5 as DE output ---
    GPIOB->MODER   &= ~(3 << (5 * 2));
    GPIOB->MODER   |=  (1 << (5 * 2));       // Output mode
    GPIOB->OTYPER  &= ~(1 << 5);             // Push-pull
    GPIOB->OSPEEDR |=  (3 << (5 * 2));       // High speed
    GPIOB->PUPDR   &= ~(3 << (5 * 2));       // No pull
    GPIOB->ODR     &= ~(1 << 5);             // Set DE LOW (receive mode)

    // 3. --- Configure PB6 as USART1_TX (AF0) ---
    GPIOB->MODER   &= ~(3 << (6 * 2));
    GPIOB->MODER   |=  (2 << (6 * 2));       // Alternate function
    GPIOB->OTYPER  &= ~(1 << 6);             // Push-pull
    GPIOB->OSPEEDR |=  (3 << (6 * 2));       // High speed
    GPIOB->PUPDR   &= ~(3 << (6 * 2));
    GPIOB->PUPDR   |=  (1 << (6 * 2));       // Pull-up
    GPIOB->AFR[0]  &= ~(0xF << (6 * 4));
    GPIOB->AFR[0]  |=  (0x0 << (6 * 4));     // AF0 = USART1

    // 4. --- Configure USART1 ---
    USART1->CR1 &= ~USART_CR1_UE;            // Disable USART1
    USART1->BRR  = Set_USART1_BRR;           // Set baud rate

    switch (Set_Parity)
    {
        case 0: // 8N2 (No parity)
            USART1->CR1 &= ~USART_CR1_PCE;
            USART1->CR1 &= ~USART_CR1_M;
            USART1->CR2 &= ~USART_CR2_STOP;
            USART1->CR2 |= USART_CR2_STOP_1 | USART_CR2_STOP_0; // 2 stop bits
            break;
        case 1: // 8E1 (Even parity)
            USART1->CR1 |=  USART_CR1_PCE;
            USART1->CR1 &= ~USART_CR1_PS;
            USART1->CR1 |=  USART_CR1_M;
            USART1->CR2 &= ~USART_CR2_STOP;
            break;
        case 2: // 8O1 (Odd parity)
            USART1->CR1 |=  USART_CR1_PCE;
            USART1->CR1 |=  USART_CR1_PS;
            USART1->CR1 |=  USART_CR1_M;
            USART1->CR2 &= ~USART_CR2_STOP;
            break;
    }

    USART1->CR3 |= USART_CR3_DMAT;  // Enable DMA TX

    USART1->CR1 |= USART_CR1_TE;    // Enable Transmit
    USART1->CR1 |= USART_CR1_UE;    // Enable USART1

    // 5. --- Configure DMA1 Channel 2 for USART1_TX ---

    DMA1_Channel2->CCR &= ~DMA_CCR_EN;             // Step 0: Disable channel first

    DMA1_Channel2->CPAR = (uint32_t)&USART1->TDR;  // Step 1: Peripheral address

    // Steps 2 & 3 (CMAR and CNDTR) will be configured during DMA transfer start

    DMA1_Channel2->CCR = 0;  // Clear all settings

    // Step 4: Configure CCR
    DMA1_Channel2->CCR |= DMA_CCR_MINC      // Increment memory address
                        | DMA_CCR_DIR       // Read from memory to peripheral
                        | DMA_CCR_TCIE      // Transfer complete interrupt
                        | DMA_CCR_PL_1;     // High priority (PL = 2)

    NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);   // Step 5: Enable interrupt for DMA
}

 

And the function I call to transfer the data

void MB_RTU_Transmit(volatile uint8_t *data, uint16_t length)
{
    SET_DE;

    DMA1_Channel2->CCR &= ~DMA_CCR_EN;          // Step 0: Disable DMA
    DMA1->IFCR |= DMA_IFCR_CTCIF2;              // Step 1: Clear any pending interrupt flag
    DMA1_Channel2->CMAR  = (uint32_t)data;      // Step 2: Set memory address
    DMA1_Channel2->CNDTR = length;              // Step 3: Set data length
    // Step 4 is implicit if DMA config is done in init
    DMA1_Channel2->CCR |= DMA_CCR_EN;           // Step 5: Enable DMA to start transfer
}

 

Carl_G
Senior II

Don't just call MB_RTU_Transmit in a loop like that. It may be in the middle of transmitting when you call again and mess it up. First I think you need to get the IRQ going then you can try multiple transmits. You should disable the DMA in the IRQ. Then you can wrap the transmit function in a check to make sure the DMA is disabled. Then you know it wont be stepping on an active transmission.

e.g

	while(1)
	{
		//for (uint16_t temp = 0; temp < 1000; ++temp);
                if(!(DMA1_Channel2->CCR & DMA_CCR_EN))
                {
                     MB_RTU_Transmit(TX_Array, 10);
                }
		delay_ms(25);
	}

 

 

But you need to get your IRQ going.

Also I suspect you should be using the USART IRQ Handler

void USART1_IRQHandler(void)
{

}

 

Does your DMA have a global interrupt flag? If so can you be sure to clear it at the start? For me it is in ISR register and can be cleared with IFCR register.

I tried this also 

	while(1)
	{
		//for (uint16_t temp = 0; temp < 1000; ++temp);
                if(!(DMA1_Channel2->CCR & DMA_CCR_EN))
                {
                     MB_RTU_Transmit(TX_Array, 10);
                }
		delay_ms(25);
	}

The code runs only once just after reset. During that time too ISR is not called. I confirm this by LED not glowing.

I think UASRT1_IRQHandleer is not useable with DMA.

void USART1_IRQHandler(void)

If you have test setup, I request you to test and give me ideas. I am really wondering why I am not able to fix this issue. I thought DMA as simple and straing forward.

Have you tried using the HAL? With STM32CubeMX? I use it with the HAL and I have USART working just as you want it to work. Every so often I dump a bunch of data at it using DFA. The HAL uses both DFA and USART interrupt. Once the HAL is working then you can start stripping things out. Thats my planned strategy since the HAL is kindof heavy for this simple task. 

Anesh
Associate III

Yes, just now I tried with HAL. I checked TX part alone. It works perfectly. I hope RX part will also work. I am trying to analyze the HAL functions, nested, some non understable syntax..... its really hard for me since I am not from Software background. I could see the frames repeated perfectly once in 100ms.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  uint8_t Frame[10] = {0,1,2,3,4,5,6,7,8,9};
  //uint16_t Count=0;

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	  HAL_UART_Transmit_DMA(&huart1, Frame, 10);
	  HAL_Delay(100);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART1 Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_9B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_EVEN;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel2_3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  /* USER CODE BEGIN MX_GPIO_Init_1 */

  /* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /* USER CODE BEGIN MX_GPIO_Init_2 */

  /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#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 CODE BEGIN 6 */
  /* 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) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */