I have read a lot of STM32 USART coding, but I think that although they all say the middle point, they are not written very well! As a rookie who has just learned STM, I have read a lot of information and written the knowledge of serial communication that I think is quite satisfactory.
Of course, I have learned a lot from the efforts of my predecessors and the official library function templates of STM. This is also my first time to write a blog on csdn!
In the STM32 reference manual, the serial port is described as a universal synchronous asynchronous receiver and transmitter (USART), which provides a flexible method for full-duplex data exchange with external devices using the industry standard NRZ asynchronous serial data format. USART uses a fractional baud rate generator to provide a wide range of baud rate selection. It supports synchronous unidirectional communication and half-duplex single-line communication, as well as LIN (local Internet), smart card protocol and IrDA (infrared data organization) SIR ENDEC specification, and modem (CTS/RTS) operation. It also allows multi-processor communication. DMA can also be used to achieve high-speed data communication.
USART is connected to other devices through 3 pins. Any USART bidirectional communication requires at least 2 pins: receive data input (RX) and transmit data output (TX).
RX: Receives data serial input. Uses 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. How does the serial port work?
There are generally two ways: query and interrupt.
(1) Query: The serial port program continuously queries in a loop to see if there is any data to be transmitted. If there is, it helps to transmit it (from PC to STM32 board, or from STM32 board to PC).
(2) Interrupt: Normally, the serial port only needs to enable interrupts. If an interrupt is found, it means that it needs to help transmit data - it will immediately transmit the data. Similarly, it can be from PC to STM3 board, and from STM32 board to PC.
3. Serial port hardware connection
The STM32 V3 development board I use has two RS-232 interfaces. The CPU's PA9-US1-TX (P68), PA10-US1-RX (P69), PA9-US2-TX (P25), and PA10-US2-RX (P26) use MAX3232 to implement two RS-232 interfaces, which are connected to the XS5 and XS17 interfaces respectively. In the system storage area startup mode, USART1 will use this port to perform ISP on the CPU on the board through the PC. This port can also be used as a normal serial port. If the short-circuit caps of JP3 and JP4 are removed, the second RS232 communication will be disconnected and it will only be used as a TTL communication channel.
4. Programming Examples
To operate the serial port, we must first connect the STM32 serial port to the CPU. In the Windows operating system, there is a built-in system software called "HyperTerminal". This software is removed from VISTA and above operating systems, but in the XP system, you can copy "hypertrm.dll" and "hypertrm.exe" to the "windows/system32" folder, and then double-click to run hypertrm.exe, and you can see the running interface of the HyperTerminal.
After running the HyperTerminal, the "Connection Description" will pop up. Enter a name and select an icon. You can write any name here. Then the "Connect to" setting will pop up. In "Use when connecting", select COMx that connects your PC and STM32. If you don't know which COM port it is, you can find it in the device manager of the PC. After selecting the COM port, a "Properties" dialog box will pop up. In "Bits/Second", select the same baud rate as set in your STM32. The data bit is also selected according to the STM32 settings. Select None for parity, 1 for stop bit, and None for data flow control. Note that the above options must match the serial port settings in the STM32, otherwise some unknown errors may occur.
After configuring the HyperTerminal, we can start programming the STM32. Programming generally follows the following steps:
(1) RCC configuration;
(2) GPIO configuration;
(3) USART configuration;
(4) NVIC configuration;
(5) Send/receive data.
In the RCC configuration, in addition to the regular clock settings, we must remember to turn on the IO port clock corresponding to the USART, the USART clock, and the pin function multiplexing clock.
In the GPIO configuration, configure the pins on the transmitting end as multiplexed push-pull outputs and the pins on the receiving end as floating inputs.
In the USART configuration, initialize the USART through the USART_InitTypeDef structure and configure it according to the functions you need. Note that the settings in the hyperterminal need to correspond to the configuration in this structure. Since I use the interrupt to receive data, remember to open the serial port interrupt in the USART configuration, and finally open the serial port.
In the configuration of NVIC, the main thing is the configuration of USART1_IRQChannel, which is similar to the interrupt configuration described in the previous notes. If you don’t know how to configure it, you can refer to the previous notes.
After all configurations are done, you can start sending/receiving data. Use USART_SendData() function to send data and USART_ReceiveData() function to receive data. For specific function functions, please refer to the reference file of the firmware library. According to the configuration of USART, 8 bits are used for one frame when sending and receiving. Therefore, when sending, a buffer area is first opened, the data to be sent is sent into the buffer area, and then the data in the buffer area is sent out. When receiving, it is also received into the buffer area first, and then the corresponding operation is performed.
Note that when sending or receiving data, you need to check the status of USART. Only after the data is sent or received can the next frame of data be sent or received. Use USART_GetFlagStatus() function.
At the same time, it should be noted that at the beginning of sending data, the USART flag bit needs to be cleared, otherwise, the first bit of data will be lost. Because after the hardware reset, the USART status bit TC is set. When a frame containing data is sent, the hardware sets this bit. As long as the USART status bit TC is set, data can be sent. Then the TC bit is cleared by the software sequence. The specific steps are "read USART_SR first, then write USART_DR". Only in this way can the flag bit TC be cleared, but when sending the first frame of data, the USART_SR is not read, but the write operation is performed directly, so the TC flag bit is not cleared. Then, when sending the first frame of data, and then using USART_GetFlagStatus() to check the status, it returns that it has been sent (because the TC bit is set to 1), so the program will immediately send the next frame of data, so the first frame of data is overwritten by the second frame of data, so the first frame of data cannot be seen.
After programming according to the above method, we can view the specific status of serial port communication on the hyperterminal. In my example, after the hardware is reset, you can immediately see the "Welcome>
RCC_cfg();
GPIO_cfg();
NVIC_cfg();
USART_cfg();
// Clear the flag, otherwise the first bit of data will be lost
USART_ClearFlag(USART1,USART_FLAG_TC);
//send data
//PB5 is used to show that data is being sent
//When data is being sent, PB5 will light up
for(>
{
USART_SendData(USART1,TxBuf1[i]);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
//Wait for data to be sent
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
while(1);
}
//RCC clock configuration
void RCC_cfg()
{
//Define error status variable
ErrorStatus HSEStartUpStatus;
//Reset the RCC register to the default value
RCC_DeInit();
// Turn on the external high-speed clock crystal
RCC_HSEConfig(RCC_HSE_ON);
//Wait for the external high-speed clock crystal to work
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
//Set AHB clock (HCLK) as system clock
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//Set the high-speed AHB clock (APB2) to HCLK clock
RCC_PCLK2Config(RCC_HCLK_Div1);
//Set the low-speed AHB clock (APB1) to 2 times the frequency of HCLK
RCC_PCLK1Config(RCC_HCLK_Div2);
//Set FLASH code delay
FLASH_SetLatency(FLASH_Latency_2);
// Enable prefetch cache
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//Set the PLL clock to 9 times the HSE frequency 8MHz * 9 = 72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
// Enable PLL
RCC_PLLCmd(ENABLE);
//Wait for PLL to be ready
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//Set PLL as system clock source
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//Judge whether PLL is the system clock
while(RCC_GetSYSCLKSource() != 0x08);
}
//Turn on the GPIO clock, multiplexing function, the clock of serial port 1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA>
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA , &GPIO_InitStructure);
//PA10 is the RX end of US1, responsible for receiving data
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//LED shows that the serial port is sending/receiving data
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//Serial port initialization
void USART_cfg()
{
USART_InitTypeDef USART_InitStructure;
//Set the structure to the default state
USART_StructInit(&USART_InitStructure);
//Set the baud rate to 115200
USART_InitStructure.USART_BaudRate = 115200;
//The width of a frame of data is set to 8 bits
USART_InitStructure.USART_WordLength =USART_WordLength_8b;
//Transmit 1 stop bit at the end of the frame
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//Parity disabled mode, no parity check
USART_InitStructure.USART_Parity = USART_Parity_No;
//Send/receive enable
USART_InitStructure.USART_Mode = USART_Mode_Rx>
//Set serial port 1
USART_Init(USART1,&USART_InitStructure);
//Open the interrupt response function of serial port 1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//Open serial port 1
USART_Cmd(USART1, ENABLE);
}
//Abort placement
void NVIC_cfg()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //Select interrupt group 2
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQChannel; //Select serial port 1 interrupt
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //Set the preemptive interrupt priority to 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; //Set the responsive interrupt priority to 0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //Enable interrupt
NVIC_Init(&NVIC_InitStructure);
}
Then find the corresponding interrupt handling function in the stm32f10x_it.c file and fill in the following content. Note that in stm32f10x_it.c, you need to declare the external variable RX_status
extern FlagStatus RX_status;
void USART1_IRQHandler(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_5);
//Confirm whether data is received
RX_status = USART_GetFlagStatus(USART1,USART_FLAG_RXNE);
//Receive data
if(RX_status == SET)
{
//Send data back to the HyperTerminal
USART_SendData(USART1, USART_ReceiveData(USART1));
//Wait for data to be sent
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) ==RESET);
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
}
}
Previous article:Detailed explanation of baud rate calculation under STM32
Next article:stm32 USART serial communication operation register + library function
Recommended ReadingLatest update time:2024-11-15 13:22
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Three steps to govern hybrid multicloud environments
- Three steps to govern hybrid multicloud environments
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- I encountered several problems in the multisim simulation of the bandpass filter circuit, as shown in the figure. Which forum friend can give me some advice?
- I would like to ask for some knowledge about voltage regulator diodes
- Android BLE low-power Bluetooth slave device application
- Intel FPGA Authoritative Design Guide
- How to download routines to TMS320F28377S in ccs7.4? I hope there are detailed steps
- DWIN 86 box hardware development information sharing
- Msp430F5438A interrupt initial
- EEWORLD University - Teach you how to use emWin graphical interface
- Chuanglong TMS320C6748 development board——timer/counter learning
- The Android software has been unable to successfully upload the example to the board. Is this a bug?