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...
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
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Live broadcast data collection | ST home appliance three-phase motor control solution
- New generation of ESD protection devices no longer require VCC connection
- The latest MicroPython official PDF technical documentation (updated to v1.21)
- Technical applications of crystal oscillators and intelligent robots during the epidemic
- EEWORLD University ---- Gizwits ECE Getting Started Tutorial
- Regarding the problem of operating a single bit in a register
- How to choose and use 2.4G antenna applications?
- Automotive Power Electronics and Motor Drives Handbook
- [NXP Rapid IoT Review] + Finally climbed out of the pit (Second week review summary)
- National Undergraduate Electronic Design Competition Module Design Series (II)