Universal Synchronous/Asynchronous Receiver/Transmitter (USART)
The STM32F103xC, STM32F103xD and STM32F103xE enhanced series products have three built-in universal synchronous/asynchronous receivers (USART1, USART2 and USART3), and two universal asynchronous receivers (UART4 and UART5). These five interfaces provide asynchronous communication, support IrDA SIR ENDEC transmission codec, multi-processor communication mode, single-line half-duplex communication mode and LIN master/slave function. The communication rate of the USART1 interface can reach 4.5 Mbit/s, and the communication rate of other interfaces can reach 2.25 Mbit/s. The USART1, USART2 and USART3 interfaces have hardware CTS and RTS signal management, ISO7816 compatible smart card mode and SPI-like communication mode. All other interfaces except UART5 can use DMA operation.
1. Main features of USART
1.1. Full-duplex, asynchronous communication
1.2.NRZ standard format
1.3. Fractional Baud Rate Generator System
1.3.1Programmable baud rate for both sending and receiving, up to 4.5Mbits/s
1.4. Programmable data word length (8 or 9 bits)
1.5. Configurable stop bits - supports 1 or 2 stop bits
1.6. LIN master's ability to send a synchronous break character and LIN slave's ability to detect a break character
1.6.1 When USART hardware is configured as LIN, a 13-bit break character is generated; a 10/11-bit break character is detected
1.7. The sender provides the clock for synchronous transmission
1.8.IRDA SIR Encoder and Decoder
1.8.1. Support 3/16 bit duration in normal mode
1.9. Smart card emulation function
1.9.1. Smart card interface supports asynchronous smart card protocol defined in ISO7816-3 standard
1.9.2. 0.5 and 1.5 stop bits used by smart cards
1.10. Single-line half-duplex communication
1.11. Configurable multi-buffer communication using DMA
1.11.1. Buffering receive/transmit bytes in SRAM using centralized DMA
1.12. Separate Transmitter and Receiver Enable Bits
1.13. Detection flag
1.13.1. Receive buffer full
1.13.2. Transmit Buffer Empty
1.13.3. Transmission end mark
1.14. Verification Control
1.14.1. Sending a check digit
1.14.2. Verify received data
1.15. Four error detection flags
1.15.1. Overflow Error
1.15.2. Noise Error
1.15.3. Frame Error
1.15.4. Verification Error
1.16.10 interrupt sources with flags
1.16.1.CTS Changes
1.16.2.LIN Break Character Detection
1.16.3. Send data register empty
1.16.4. Sending completed
1.16.5. Receive data register full
1.16.6. Bus is detected to be idle
1.16.7. Overflow Error
1.16.8. Frame Error
1.16.9. Noise Error
1.16.10. Verification Error
1.17. Multiprocessor communication -- if address does not match, enter silent mode
1.18. Wake up from silent mode (by idle bus detection or address mark detection)
1.19. Two ways to wake up the receiver: address bit (MSB, bit 9), bus idle
2. USART Function Overview
The interface is connected to other devices through three pins (see the figure below). Any USART bidirectional communication requires at least two pins: receive data input (RX) and transmit data output (TX).
RX: Receive data input. Use oversampling technology to distinguish data from noise and recover data.
TX: Transmit data output. When the transmitter is disabled, the output pin reverts to its I/O port configuration. When the transmitter is enabled and not transmitting data, the TX pin is at a high level. In single-wire and smart card modes, this I/O port is used for both data transmission and reception.
2.1. The bus should be in idle state before sending or receiving
2.2. A start bit
2.3. A data word (8 or 9 bits), least significant bit first
2.4.0.5, 1, 1.5, 2 stop bits, indicating the end of the data frame
2.5. Using the fractional baud rate generator - 12-bit integer and 4-bit decimal representation.
2.6. A status register (USART_SR)
2.7. Data Register (USART_DR)
2.8. A baud rate register (USART_BRR), 12-bit integer and 4 decimal places
2.9. A smart card mode protection time register (USART_GTPR)
The following pins are required in synchronous mode:
CK: Transmitter Clock Output. This pin outputs the clock used to synchronize transmissions (there is no clock pulse on the Start and Stop bits, and software can optionally send a clock pulse on the last data bit). Data can be received synchronously on RX. This can be used to control external devices with shift registers (such as LCD drivers). The clock phase and polarity are software programmable. In smart card mode, CK can provide the clock for the smart card.
The following pins are required in IrDA mode:
IrDA_RDI: data input in IrDA mode;
IrDA_TDO: Data output in IrDA mode.
The following pins are required in hardware flow control mode:
nCTS: Clear to send, if it is high level, it blocks the next data transmission when the current data transmission ends;
nRTS: Send request. If it is low, it indicates that USART is ready to receive data.
Taking STM32F103ZET6 as an example, the following introduces the use of the asynchronous receiver of the universal synchronous asynchronous receiver through library functions combined with register configuration (the project verifies that the operation is stable).
The general (conventional) steps for serial port settings can be summarized as follows:
1) Serial port clock enable, GPIO clock enable;
2) Serial port reset (can be omitted);
3) GPIO port mode setting;
4) Initialize serial port parameters;
5) Enable interrupts and initialize NVIC (this step is required only if interrupts need to be enabled);
6) Enable the serial port;
7) Write an interrupt handling function.
In addition to the conventional configuration method mentioned above, USART can also use DMA for continuous communication. The DMA requests for the Rx buffer and Tx buffer are generated separately.
Send using DMA
Using DMA for transmission can be activated by setting the DMAT bit on the USART_CR3 register. When the TXE bit is set to '1', DMA transfers data from the specified SRAM area to the USART_DR register. The steps to assign a DMA channel for USART transmission are as follows (x represents the channel number):
1. Configure the USART_DR register address as the destination address of DMA transfer in the DMA control register. After each TXE event, the data will be transferred to this address.
2. Configure the memory address as the source address of the DMA transfer in the DMA control register. After each TXE event, the data will be read from this memory area and transferred to the USART_DR register.
3. Configure the total number of bytes to be transferred in the DMA control register.
4. Configure channel priority on DMA registers.
5. Configure the DMA interrupt to be generated when the transfer is halfway or fully completed, as required by the application.
6. Activate the channel on the DMA register.
When the transfer completes the amount of data specified by the DMA controller, the DMA controller generates an interrupt on the interrupt vector of the DMA channel.
In transmit mode, when DMA has transmitted all the data to be transmitted, the DMA controller sets the TCIF flag of the DMA_ISR register; monitoring the TC flag of the USART_SR register can confirm whether the USART communication is over, so as to avoid destroying the last transmitted data before shutting down the USART or entering the stop mode; the software needs to wait for TXE=1 first, and then wait for TC=1.
Receiving using DMA
You can activate DMA reception by setting the DMAR bit in the USART_CR3 register. Each time a byte is received, the DMA controller transfers the data from the USART_DR register to the specified SRAM area (refer to the DMA related instructions). The steps to assign a DMA channel for USART reception are as follows (x represents the channel number):
1. Configure the USART_DR register address as the source address of the transfer through the DMA control register. After each RXNE event, data will be read from this address and transferred to the memory.
2. Configure the memory address as the destination address of the transfer through the DMA control register. After each RXNE event, the data will be transferred from USART_DR to this memory area.
3. Configure the total number of bytes to be transferred in the DMA control register.
4. Configure channel priority on DMA registers.
5. Configure the DMA interrupt to be generated when the transfer is halfway or fully completed, as required by the application.
6. Activate the channel on the DMA control register.
When the reception completes the transfer amount specified by the DMA controller, the DMA controller generates an interrupt on the interrupt vector of the DMA channel.
Error flags and interrupt generation in multi-buffer communications
In case of multi-buffer communication, if any error occurs during communication, the error flag will be set after the current byte is transferred. If the interrupt enable bit is set, an interrupt will be generated. In case of single byte reception, the frame error, overflow error and noise flags that are set together with RXNE have separate error flag interrupt enable bits; if set, an interrupt will be generated after the current byte transfer is completed.
code show as below:
1. Define receive and send data cache variables
#define COMx_RXBUFFER_SIZE 255 //Serial port receive buffer length
typedef struct COMx_RXBUFFER
{
u8 buffer[COMx_RXBUFFER_SIZE]; //Receive buffer
u8 RxFlag; //Receive data flag 1: New data received 0: No new data received
u16 RxLen; //Received data length
}COMx_RXBUFFER;
#define UART1_RX_LEN COMx_RXBUFFER_SIZE //USART1 DMA receive buffer length
uint8_t Uart1_Tx[UART1_TX_LEN] = {0}; //Serial port 1 sends DMA buffer
uint8_t Uart1_Rx[UART1_RX_LEN] = {0}; //Serial port 1 receives DMA buffer
//Serial port 1 receives DMA buffer
COMx_RXBUFFER Uart1_RxBuffer;
2. Configure the serial port
static void BSP_USART1_Init(u32 baud)
{
USART_InitTypeDef bsp_usart_init;
GPIO_InitTypeDef bsp_usartpin_init;
// Enable USART1 clock, enable USART1 pin clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
//Initialize USART1 pin PA9 TX
bsp_usartpin_init.GPIO_Pin = GPIO_Pin_9;
bsp_usartpin_init.GPIO_Speed = GPIO_Speed_50MHz;
bsp_usartpin_init.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &bsp_usartpin_init);
//Initialize USART1 pin PA10 RX
bsp_usartpin_init.GPIO_Pin = GPIO_Pin_10;
bsp_usartpin_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &bsp_usartpin_init);
// Initialize USART1 parameters
bsp_usart_init.USART_BaudRate = baud;
bsp_usart_init.USART_WordLength = USART_WordLength_8b;
bsp_usart_init.USART_StopBits = USART_StopBits_1;
bsp_usart_init.USART_Parity = USART_Parity_No;
bsp_usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
bsp_usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &bsp_usart_init);
// Initialize interrupt
BSP_NVIC_Init(USART1_IRQn, 1, 1);
// Enable USART1 bus idle interrupt
USART_ITConfig(USART1,USART_IT_TC,DISABLE);
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//Serial port receive DMA configuration
BSP_DMAUsar1Rx_Init();
//Serial port sends DMA configuration
BSP_DMAUsar1Tx_Init();
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //Receive using DMA
//Open USART1
USART_Cmd(USART1, ENABLE);
}
Analyze the above code:
1. Enable the serial port clock. The serial port is a peripheral mounted under APB2, so the enable function is:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);
2. Serial port reset. When a peripheral device fails, you can reset it through the reset setting, and then reconfigure the peripheral device to make it work again. Generally, when the system starts to configure the peripheral device, it will first perform the operation of resetting the peripheral device (omitted here);
3.GPIO port mode setting. Configure the pins according to the figure below. USART1 used here corresponds to pins PA9 (TX) and PA10 (RX);
4. Serial port parameter configuration. Custom baud rate, 1 start bit, 1 stop bit, 8 data bits, no parity, no flow control. Enable receiving and sending data functions.
5. Enable the bus idle interrupt and initialize the interrupt. For more information about interrupts, refer to the relevant content
The initialization interrupt code is as follows:
/*
*********************************************************************************************************
* BSP_NVIC_Init()
*
* Description: Interrupt priority initialization function, used to set the priority of the interrupt
*
* Argument(s) : IRQChannel interrupt channel.
* PreemptionPrio interrupt preemption priority
* SubPrio interrupt subpriority
*
* Return(s) : none.
*
* Caller(s) : Application.
*
* Note(s) : none.
*********************************************************************************************************
*/
void BSP_NVIC_Init(u8 IRQChannel, u8 PreemptionPrio, u8 SubPrio)
{
NVIC_InitTypeDef bsp_nvic_init;
bsp_nvic_init.NVIC_IRQChannel = IRQChannel;
bsp_nvic_init.NVIC_IRQChannelPreemptionPriority = PreemptionPrio;
bsp_nvic_init.NVIC_IRQChannelSubPriority = SubPrio;
bsp_nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&bsp_nvic_init);
}
6. Configure DMA mode to receive serial port data. For more information about DMA, see the DMA controller introduction.
code show as below:
//USART1 receive DMA configuration
static void BSP_DMAUsar1Rx_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //Start DMA clock
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); //Peripheral address
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart1_Rx; //Memory address
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //dma transmission direction is unidirectional
DMA_InitStructure.DMA_BufferSize = UART1_RX_LEN; //Set the length of the DMA buffer during transmission
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Disable DMA peripheral increment mode, a peripheral
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Set DMA memory increment mode
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //Peripheral data word length
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //Memory data word length
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //Set DMA transfer mode
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //Set the DMA priority level
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Disable the variables in the two DMA memories from accessing each other
DMA_Init(DMA1_Channel5,&DMA_InitStructure);
DMA_Cmd(DMA1_Channel5,ENABLE); //Enable channel 5
}
7. Configure DMA mode to send serial port data. The code is as follows:
//USART1 sends DMA configuration
static void BSP_DMAUsar1Tx_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //Start DMA clock
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); //DMA peripheral base address
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart1_Tx; //DMA memory base address
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //Data transmission direction, read from memory and send to peripherals
DMA_InitStructure.DMA_BufferSize = UART1_TX_LEN; //DMA channel DMA buffer size
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Peripheral address register remains unchanged
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Memory address register increment
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //Data width is 8 bits
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //Data width is 8 bits
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //Work in normal mode
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA channel x has medium priority
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA channel x is not set for memory to memory transfer
DMA_Init(DMA1_Channel4, &DMA_InitStructure); //Initialize the registers identified by the DMA channel USART1_Tx_DMA_Channel according to the parameters specified in DMA_InitStruct
}
8. Enable DMA mode to receive data and turn on the serial port function.
9. The interrupt processing function is as follows:
//USART1 interrupt function.
void USART1_IRQHandler(void)
{
uint16_t i = 0;
OSIntEnter();
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{
//1. Clear USART1 receive completion interrupt
//USART_ClearFlag(USART1,USART_IT_IDLE);
USART1->SR;
USART1->DR; //Clear USART_IT_IDLE flag
//2. Store the received data content, length, and flag bit
DMA_Cmd(DMA1_Channel5,DISABLE); //Disable DMA
if(!Uart1_RxBuffer.RxFlag) //Determine whether there is a data packet being processed
{
Uart1_RxBuffer.RxLen = UART1_RX_LEN -
DMA_GetCurrDataCounter(DMA1_Channel5); //Calculate the length of the received data packet
for (i = 0;i < Uart1_RxBuffer.RxLen;i++) // Cache the received data packet
{
Uart1_RxBuffer.buffer[i] = Uart1_Rx[i];
}
Uart1_RxBuffer.RxFlag = 1; //Set the receiving status flag
}
DMA_SetCurrDataCounter(DMA1_Channel5,UART1_RX_LEN); //Set the transmission data length
DMA_Cmd(DMA1_Channel5,ENABLE); //Open DMA
}
// 3. Send message to task_command_process
OSMboxPost(MboxCmdSet, &Uart1_RxBuffer.buffer[0]); // Inform App_TaskCommandProcess() that one command has arrived.
OSIntExit();
}
Because the project is developed based on the ucos-ii system, the interrupt function contains ucos-ii system related functions. The interrupt processing steps are as follows:
9.1. Determine whether the interrupt type is a bus idle interrupt. If not, exit the interrupt without any processing; if yes, continue processing;
9.2. Clear the interrupt flag;
9.3. Turn off the DMA receiving function and obtain the length of the received data;
9.4. Extract the received data from the DMA receive buffer according to the received data length;
9.5. Reset DMA transfer data length and enable DMA receiving function;
9.6. Exit the interrupt handling function.
Since the time when the serial port receives data is unknown, interrupts are used to process the received data. However, it is obviously not enough to only receive data without interruption. The following is an introduction to the data sending function. The code is as follows:
//USART1 DMA sends data of specified length
//str: the first address of the data to be sent
//cndtr: data transmission volume
void BSP_DMAUsart1Puts(unsigned char *str,u8 cndtr)
{
memcpy(Uart1_Tx, str, cndtr);
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //Enable DMA transmission of serial port 1
DMA_Cmd(DMA1_Channel4, DISABLE ); //Disable the channel indicated by USART1 TX DMA1
DMA_SetCurrDataCounter(DMA1_Channel4,cndtr); //DMA channel DMA buffer size
DMA_Cmd(DMA1_Channel4, ENABLE); //Enable the channel indicated by USART1 TX DMA1
}
The time to send data through the serial port is predictable, so the normal way to send serial port data can be used. The steps are as follows:
1. Transfer the data to be sent to the DMA send buffer;
2. Turn off the DMA serial port data sending function;
3. Set the size of the data to be sent;
4. Enable the DMA serial port sending function to send the data out.
This concludes the introduction to serial communication. To get the received data, just check the data in the variable Uart1_RxBuffer.buffer[]. To send data, call the following function.
void BSP_DMAUsart1Puts(unsigned char *str,u8 cndtr);
Previous article:STM32F103 USART serial port simple implementation
Next article:STM32 serial communication USART program example
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
- [Xianji HPM6750 Review] + Environment Setup Test
- EEWORLD University ---- Webinar: Thermal Monitoring and Protection
- How to solve the power supply ripple
- 【AT-START-F425 Review】No.06 Driving Segment LCD
- Today at 10:00 AM Award-winning live broadcast: STMicroelectronics SiC products and industrial application guide
- Gossip negative feedback
- Do you think domestic regulators will prevent Nvidia from acquiring ARM?
- [Qinheng RISC-V core CH582] Application of ADC and general controller
- PFC switching power supply has these performance characteristics, do you know?
- Problems with encrypted transmission of STC microcontroller programs