Overview
The STM32F103R6 has up to two USART(Universal Synchronous/Asynchronous Receiver/Transmitter) communication modules, USART1 and USART2. These communication interfaces could be configured as synchronous or asynchronous transmission. Synchronous transmission uses a share clock line that synchronize with data.
A serial communication between two devices using a shared clock source
|
The timing diagram of a serial communication without a dedicated clock line
|
The signaling difference between a USART and a UART
|
UART is more convenient than USART because it does not require clock line over the communication interface. In some case it requires more control lines. For electronic hobbyists it is widely used with some device such as,
- the Bluetooth module,
- the Arduino serial interface that use as program uploading and serial data transmission,
- the ESP8266 WiFi module,
- the Nextion HMI (Human Machine Interface)
- the GSM module.
The Baud Rate (bits per second) is the numbers of data bits transferred per second. The STM32F1xx has the following Baud Rate.
stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx- standard Baud Rate |
Using the STM32CubeIDE and its CubeHal, the programmer doesn't need to calculate and configure its internal register as the IDE has a code configuring tool.
UART Programming In STM32CubeIDE Example
There are a lot of library functions in the STM32CubeIDE especially the HAL(Hardware Abstraction Layer) libraries. We still able use ARM Cortex-M3 legacy libraries in this IDE. The following APIs are belong to the IO operation functions group,
- HAL_UART_Transmit()- HAL_UART_Receive()
- HAL_UART_Transmit_IT()
- HAL_UART_Receive_IT()
- HAL_UART_Transmit_DMA()
- HAL_UART_Receive_DMA()
- HAL_UART_DMAPause()
- HAL_UART_DMAResume()
- HAL_UART_DMAStop()
- HAL_UARTEx_ReceiveToIdle()
- HAL_UARTEx_ReceiveToIdle_IT()
- HAL_UARTEx_ReceiveToIdle_DMA()
- HAL_UARTEx_GetRxEventType()
- HAL_UART_Abort()
- HAL_UART_AbortTransmit()
- HAL_UART_AbortReceive()
- HAL_UART_Abort_IT()
However there are additional function such as, Peripheral Control function, Peripheral State and Errors functions group.
In this example I will use a few functions,
- HAL_UART_Init (UART_HandleTypeDef * huart)
For example HAL_UART_Init (&huart1) , or HAL_UART_Init (&huart2)
- HAL_UART_Transmit (UART_HandleTypeDef * huart, const uint8_t * pData, uint16_t
Size, uint32_t Timeout)
For example HAL_UART_Transmit(&huart1,"Hello",5,1000)
- HAL_UART_Receive (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size,
uint32_t Timeout)
For example HAL_UART_Receive(&huart1,myData,1,1000)
I will show a simple programming using CubeHAL. The firmware will be use with Proteus Simulator.
Simulating Program - Virtual Terminal Acts As UART Receiver/Transmitter. |
- 1 LED1 ON
- 2 LED1 OFF
- 3 LED2 ON
- 4 LED2 OFF
Now we will start writing the program for this example by creating a new STM32 project. Click on the USART1 in device configuration tool and select Asynchronous in Mode combo box.
USART1 Configuration |
GPIO Setting |
After the code generation is created we will need to add some user codes in the main.c file.
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2023 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private variables ---------------------------------------------------------*/ UART_HandleTypeDef huart1; /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); /* USER CODE BEGIN PFP */ /** * @brief The application entry point. * @retval int */ int main(void) { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); HAL_UART_Transmit(&huart1,"STM32F103 UART1 Example #3\r\n",32,1000); uint8_t myData=0; /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_UART_Receive(&huart1,&myData,1,1000); switch(myData){ case '1': HAL_GPIO_WritePin(GPIOC,LED1_Pin,GPIO_PIN_SET); HAL_UART_Transmit(&huart1,&myData,1,1000); HAL_UART_Transmit(&huart1," LED1 ON\r\n",12,1000); myData=0; break; case '2': HAL_GPIO_WritePin(GPIOC,LED1_Pin,GPIO_PIN_RESET); HAL_UART_Transmit(&huart1,&myData,1,1000); HAL_UART_Transmit(&huart1," LED1 OFF\r\n",12,1000); myData=0; break; case '3': HAL_GPIO_WritePin(GPIOC,LED2_Pin,GPIO_PIN_SET); HAL_UART_Transmit(&huart1,&myData,1,1000); HAL_UART_Transmit(&huart1," LED2 ON\r\n",12,1000); myData=0; break; case '4': HAL_GPIO_WritePin(GPIOC,LED2_Pin,GPIO_PIN_RESET); HAL_UART_Transmit(&huart1,&myData,1,1000); HAL_UART_Transmit(&huart1," LED2 OFF\r\n",12,1000); myData=0; break; } } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {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_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != 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 = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART1_Init 2 */ /* USER CODE END USART1_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, LED1_Pin|LED2_Pin, GPIO_PIN_RESET); /*Configure GPIO pins : LED1_Pin LED2_Pin */ GPIO_InitStruct.Pin = LED1_Pin|LED2_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); } /* 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 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
It requires 6.24KB of Flash and 1.62KB of RAM. Click here to download its source file.