【STM32】Serial port related configuration registers, library functions (UART general steps)

Publisher:DazzlingSmileLatest update time:2019-03-13 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

STM32F1xx official information:


"STM32 Chinese Reference Manual V10" - Chapter 25 Universal Synchronous Asynchronous Receiver Transmitter (USART)


 


Serial port related configuration registers

Status Register (USART_SR)



The status register is used to detect the current state of the serial port. The states that can be detected include: send register empty bit, send completion bit, read data register non-empty bit, main line idle bit detected, overload error, etc.


Here we mainly focus on two bits: RXNE and TC (the 5th and 6th bits).


RXNE (Read Data Register Not Empty): When this bit is set to 1, it indicates that data has been received and can be read (that is, the data in the RDR shift register is transferred to the USART_DR register). At this time, what needs to be done is to read USART_DR as quickly as possible to clear this bit, or write 0 to this bit to clear it directly.


TC (Transmit Complete): When this bit is set to 1, it indicates that the data in USART_DR has been sent. If the interrupt for this bit is set, an interrupt will be generated. There are also two ways to clear this bit: read USART_SR, write USART_DR; directly write 0 to this bit.


Data Register (USART_DR)



USART_DR actually contains two registers, one is TDR for sending, and the other is RDR for receiving. When sending data, data written to USART_DR will be automatically stored in TDR; when reading data, data read from USART_DR will automatically extract RDR data.


Serial communication is transmitted one bit at a time, so the TDR and RDR registers are between the system bus and the shift register; when sending data, the TDR content is transferred to the transmit shift register, and when receiving data, each received bit is sequentially saved in the receive shift register and then transferred to the RDR.


Baud Rate Register (USART_BRR)



The baud rate register includes two parts: DIV_Mantissa (integer part) and DIV_Fraction (fractional part).


Control Register (USART_CRx)



The control register mainly sets USART enable, check control enable, check selection (odd check or even check), PE interrupt enable, send buffer empty interrupt enable, send completion interrupt enable, receive buffer not empty enable, send enable, receive enable, word length, etc.


 


USART peripheral pin multiplexing

When using USART, GPIO pins need to be multiplexed. The following figure introduces the pin settings of USART:




Baud rate calculation method

Before learning about baud rate, first understand the communication rate. The communication rate is usually expressed in bit rate, which is the number of binary bits transmitted per second, in bits per second (bit/s). The concept that is easily confused with bit rate is "baud rate", which indicates how many code units are transmitted per second.


Code element is the concept of communication signal modulation. A binary number is represented by symbols with the same time interval. Such a signal is called a code element. For example, in common communication transmission: 0V represents the number 0, 5V represents the number 1, then a code element can represent two states 0 and 1, so a code element is equal to a binary bit, and the baud rate is consistent with the bit rate; if 0V, 2V, 4V and 6V represent 00, 01, 10, 11 respectively in the transmission, then each code element can represent four states, two binary bits, so the number of code elements is half of the number of binary bits, and the baud rate is half of the bit rate. Because a code element represents two states in many common communications, people often directly use baud rate to represent bit rate, but there is a difference between the two. 


Since there is no clock signal in asynchronous communication, the two communicating devices need to agree on the baud rate, that is, the length of each code element, in order to decode the signal. Common baud rates are 4800, 9600, and 115200.


 


In the above formula, fpclkx is the clock for the serial port (PCLK1 is used for USART2, 3, 4, 5, PCLK2 is used for USART1); USARTDIV is an unsigned fixed-point number. As long as we get the value of USARTDIV, we can calculate the baud rate.




Serial port operation related library functions


1 initialization function

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);

Function: Used to initialize the configurations of serial port baud rate, data word length, parity check, hardware flow control, and transmit and receive enable.


2 enable functions

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);

Function: The former enables the serial port, and the latter enables the related interrupts of the serial port.


2 data sending and receiving functions

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

Function: The former sends data to the serial port, and the latter receives data from the serial port.


4 status bit functions

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);

void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);

ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

Function: The first two get (or clear) the status flag, and the last two get (or clear) the interrupt status flag.


 


General steps for serial port operation

GPIO clock enable, serial port clock enable. Call function: RCC_APB2PeriphClockCmd() (see: [STM32] STM32 port multiplexing and remapping (AFIO auxiliary function clock));

Reset the serial port (this step is not necessary). Call function: USART_DeInit();

Port mode setting under GPIO peripheral function. Calling function: GPIO_Init();

Initialize serial port parameters. Call function: USART_Init();

Enable interrupts and initialize NVIC (this step is required only if interrupts need to be enabled). Call function: NVIC_Init(); USART_ITConfig();

Enable the serial port. Call function: USART_Cmd();

Write an interrupt handling function. Call function: USARTx_IRQHandler();

Serial port data sending and receiving. Calling function: USART_SendData(); USART_ReceiveData();

Get the serial port transmission status. Call function: USART_GetFlagStatus(); USART_ClearITPendingBit();

Follow these general steps to create a simple serial port program:


void My_USART1_Init(void)

{

GPIO_InitTypeDef GPIO_InitStrue;

USART_InitTypeDef USART_InitStrue;

NVIC_InitTypeDef NVIC_InitStrue;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //GPIO port enable

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //Serial port enable


GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;

GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;

GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;

GPIO_Init(GPIOA,&GPIO_InitStrue);


GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;

GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;

GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;

GPIO_Init(GPIOA,&GPIO_InitStrue);


USART_InitStrue.USART_BaudRate=115200;

USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;

USART_InitStrue.USART_Parity=USART_Parity_No;

USART_InitStrue.USART_StopBits=USART_StopBits_1;

USART_InitStrue.USART_WordLength=USART_WordLength_8b;


USART_Init(USART1,&USART_InitStrue);//


USART_Cmd(USART1,ENABLE); //Enable serial port 1


USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //Enable receive interrupt


NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;

NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;

NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;

NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;

NVIC_Init(&NVIC_InitStrue);


}

 

void USART1_IRQHandler(void)

{

u8 res;

if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)

 {

     res= USART_ReceiveData(USART1); 

     USART_SendData(USART1,res);   

  }

}

 

 int main(void)

 {

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

My_USART1_Init();

while(1);

 

 }

usrt_init function


The GPIO port mode setting here is the port mode setting under port multiplexing. As for how to set the GPIO mode under the multiplexing function, you can refer to the manual "STM32 Chinese Reference Manual" p110;

The baud rate setting of USART_BaudRate is written directly, and MDK5 does not have a preset macro definition to select;

USART_Mode mode selection uses USART_Mode_Tx|USART_Mode_Rx to indicate transmit enable and receive enable;

NVIC_IRQChannel interrupt channel, which is the macro definition ending with IRQn at the beginning of stm32f10x.h.

USART1_IRQHandlar function


The USART1_IRQHandlar function is an interrupt handling function and cannot be defined arbitrarily. It needs to follow the definition of MDK. The declaration of these functions is in the startup file startup_stm32f10x_hd.s, where the name of the interrupt handling function can be found.

It is very necessary to first check the status bit in the interrupt processing function. This is because we may have set more than one interrupt in the interrupt setting of the serial port, but the interrupt processing function entered by each interrupt is the same, which requires us to judge the status bit in the interrupt processing function before performing the next operation.

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 

Here, this judgment is used to determine whether to receive an interrupt. The return value of this function is of type ITStatus, which is defined as:


typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;

SET represents 1 (interrupt received), and RESET represents 0 (interrupt not received).


In addition to the ITStatus of the interrupt processing function, it is usually necessary to judge after sending and receiving data. For example, the following program:

USART_SendData(USART1, USART_RX_BUF[t]); //Send data to serial port 1

while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//Wait for sending to end

That is, use the while loop to send data to the serial port and wait for the sending to end through judgment.


There is another problem in this program that has troubled me for a long time and I have not figured it out clearly:


In the interrupt processing function, use the following procedure to receive data:


u8 res;

     res= USART_ReceiveData(USART1); 

Since res is a u8 type number, if a lot of data is sent to the serial port at one time, when the serial port uses this program to receive, a u8 cannot hold a lot of data. This function uses if judgment. If it cannot be loaded at one time, the if judgment program will run once. How can all the data be received?


Answer: Actually, let's look at the interrupt caused by the RXNE flag. When the data in the RDR shift register is transferred to the USART_DR register, that is, when there is data to be received, this bit is set to 1, causing an interrupt and entering the interrupt processing function. However, in this interrupt processing function, we did not clear the interrupt bit like other interrupts, which caused the bit to be 1 all the time and continuously enter the interrupt. So when does it stop? When the data is received, the bit is cleared to 0.


 


printf Function

The code supporting the printf function is defined in the usart.c file in the SYSTEM folder. By adding the following code, you can send the required content to the serial port through the printf function. This code does not need to be modified, just import it into usart.h and it can be used.


#if 1

#pragma import(__use_no_semihosting)             

//Support functions required by the standard library                 

struct __FILE 

int handle; 

 

}; 

 

FILE __stdout;       

// define _sys_exit() to avoid using semihost mode    

_sys_exit(int x) 

x = x; 

//Redefine fputc function 

int fputc(int ch, FILE *f)

{      

while((USART1->SR&0X40)==0);//Send in a loop until the sending is completed   

    USART1->DR = (u8) ch;      

return ch;

}

#endif 

The whole code block is quite strange. After redefining the fputc function, there is no display declaration of the printf function, so that the content can be sent to the serial port. I looked at it for a long time, but I still couldn't understand what was going on...

Keywords:STM32 Reference address:【STM32】Serial port related configuration registers, library functions (UART general steps)

Previous article:【STM32】STM32 firmware library (standard peripheral library)
Next article:【STM32】Basic principles of serial communication (super basic, detailed version)

Recommended ReadingLatest update time:2024-11-16 12:58

STM32 study notes---counter timing interrupt (1s)
  #include "tim_driver.h"     //tim2³õʼ»¯:1ÃëÖÓ¸üÐÂÊý¾Ý void tim2_init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; //ʹÄÜʱÖÓ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode   = TIM_CounterMode_
[Microcontroller]
STM32 study notes---counter timing interrupt (1s)
STM32 Development Board - I2C--24Cxx
The 24Cxx series we use for demonstration is the most commonly used EEPROM chip. As mentioned above, the address code of 24Cxx is fixed, and the 8 bits are as follows: 1   0   1   0   A2 A1 A0   0 A2 A1 A0 are the levels of its three pins respectively. There is something special about 24Cxx. 24Cxx includes four
[Microcontroller]
STM32 TFT learning notes - brush characters
Host environment: Windows 7 SP1 Development environment: MDK5.14 Target board: ST NUCLEO-F303RE TFT model: 2.4 inches, with touch, SD card, 240*320 resolution, 260,000 colors Driver IC:ILI9325 ST library version: STM32Cube_FW_F3_V1.1.0 After brushing the picture, it is natural to want to brush the character experime
[Microcontroller]
【STM32】Basic principles of serial communication (super basic, detailed version)
STM32F1xx official information: "STM32 Chinese Reference Manual V10" - Chapter 25 Universal Synchronous Asynchronous Receiver Transmitter (USART)   Communication interface background knowledge How devices communicate with each other Generally speaking, the communication between devices can be divided into two ty
[Microcontroller]
【STM32】Basic principles of serial communication (super basic, detailed version)
STM32 collects multi-channel AD through DMA
environment: Host: XP Development environment: MDK4.23 MCU:STM32F103CBT6 illustrate: Collect AD through pins PA1 and PA2. Collect AD 10 times for each channel. #include "ad_driver.h"      //Global variables   //AD sampling storage space   __IO uint16_t ADCConvertedValue ;      //function   //Initialize AD   void ini
[Microcontroller]
[STM32] BUG and precautions about USART receive interrupt
Today, I encountered some problems when using the USART module and solved them, so I posted them to share. Problem description: When using USART for serial communication, I only turned on the receive interrupt and set the preemption priority to the lowest level. The previous priority of the receive interrupt handle
[Microcontroller]
STM32 drives LCD12864
#include "led.h" #undef APP_DE #include "hawk.h" LCD uses JLX19264G-260 from Jinglianxun Electronics #define FEEDDOG() GPIOC- ODR^= GPIO_Pin_0 //LCD IO initialization void LCD_Init(void) {    GPIO_InitTypeDef GPIO_InitStructure;    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIO
[Microcontroller]
USB design based on STM32--MCU program
First, let's take a look at the working process of USB. When a USB device is connected to the host, the host begins to enumerate the USB device and sends a command to the USB device to obtain the relevant description information of the USB device, including device description (device descriptor), conf
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号