I used to adjust the serial port of STM8L, which had simple logic and clear interrupts. After changing to STM8S105K4, although the STD library is also used, in addition to the differences in language levels such as function names and macro names, there are also some differences in interrupt handling, which I would like to note.
The structure is the same as this article [Using STM8L USART serial port], which is also an interrupt asynchronous mode, but for the convenience of calling, it is changed to synchronous at the calling level.
(For STM8S105K MCU, RX is PD6 and RX is PD5.)
In terms of usage, the main problem is that the interrupt name, usage occasions and timing are not clear, which is not as clear as the definition of STM8L.
For example, use UART2_IT_RXNE_OR to switch interrupts, and use UART2_IT_RXNE to clear interrupts. You cannot use UART2_IT_RXNE to switch, nor can you use UART2_IT_RXNE_OR to clear interrupts, otherwise the STD library will assert that the parameters are legal, and the program will hang in minutes.
For reference.
The following is the sample code. In order to better separate from the application layer and generalize the code, an independent UART read and write buffer is set. If the buffer is large, please use @near to initialize it in the separated data area.
In addition, although it is interrupt driven, considering that most usage scenarios are synchronous, a synchronous state variable is set and detected in the read and write functions. If it is changed to an interrupt, you only need to change the judgment of the state variable to judgment on the application side.
1. Read and write buffer and identification value definition
#define UART_BUF_SIZE 128
/* Read buffer */
uint8_t read_ok = 0; // read completion flag
uint8_t read_idx = 0;
uint8_t read_len = 0;
@near uint8_t read_buffer[UART_BUF_SIZE]; // When the buffer is set to be large, @near can be used
/* Write buffer */
uint8_t writ_ok = 0; // Write completed flag
uint8_t writ_idx = 0;
uint8_t writ_len = 0;
@near uint8_t writ_buffer[UART_BUF_SIZE]; // When the buffer is set to be large, @near can be used
2. Serial port initialization
STM8S105K4 has only one serial port, namely UART2
int8_t uart_init(void)
{
// Please modify the serial port parameters as required
UART2_DeInit();
UART2_Init((uint32_t)38400,
UART2_WORDLENGTH_8D,
UART2_STOPBITS_1,
UART2_PARITY_NO,
UART2_SYNCMODE_CLOCK_DISABLE,
UART2_MODE_TXRX_ENABLE);
// Explicitly turn off interrupts (off by default)
// Notice:
// The read interrupt name is UART2_IT_RXNE_OR, not UART2_IT_RXNE
// Write interrupt name as UART2_IT_TXE
UART2_ITConfig(UART2_IT_RXNE_OR, DISABLE);
UART2_ITConfig(UART2_IT_TXE, DISABLE);
//Enable the serial port
UART2_Cmd(ENABLE);
return 0;
}
3. Read and write functions
// Write multiple bytes
void uart_send_n_byte(uint8_t* data, uint8_t len)
{
uint16_t count = 0;
UART2_ITConfig(UART2_IT_TXE, DISABLE);
// Prepare to write data buffer (copy from user data area to serial port write buffer, initialize index value, etc.)
memcpy(writ_buffer, data, len);
writ_idx = 0;
writ_len = len;
// Enable write interrupt
UART2_ITConfig(UART2_IT_TXE, ENABLE);
while(!writ_ok) { // Wait for writing to complete (synchronous processing)
count++;
if( count >= 10000 ) { // Simple timeout processing, can be removed if no timeout is needed
writ_idx = 0;
writ_len = 0;
break;
}
}
writ_ok = 0; // Writing completed, reset writing completed flag
return;
}
// Read multiple bytes
void uart_read_n_byte(uint8_t* data, uint8_t len)
{
// Disable read interrupt
UART2_ITConfig(UART2_IT_RXNE_OR, DISABLE);
// Clear the read buffer (reset the read index value)
read_idx = 0;
read_len = len;
// Enable read interrupt
UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);
while(!read_ok); // Wait for the read operation to complete (synchronization processing), add timeout processing, refer to the above write operation
read_ok = 0; // Write completed, reset write completed flag
memcpy(data, read_buffer, read_len); // Copy data to user buffer
return;
}
4. Interrupt handling
INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20)
{
// Write operations automatically clear interrupts, so there is no need to explicitly clear interrupts
//UART2_ClearITPendingBit(UART2_IT_TXE);
// Write 1 byte from the write buffer
UART2_SendData8(writ_buffer[writ_idx++]);
// Complete all writing, turn off writing interrupt, set writing completion flag (synchronization processing)
if( writ_idx == writ_len ) {
UART2_ITConfig(UART2_IT_TXE, DISABLE);
write_ok = 1;
}
}
INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21)
{
// The read operation automatically clears the interrupt, so there is no need to explicitly clear the interrupt
// Note that the interrupt name here is RXNE, not RXNE_OR
UART2_ClearITPendingBit(UART2_IT_RXNE);
// Read 1 byte
read_buffer[read_idx++] = UART2_ReceiveData8();
// After reading all, turn off interrupt (UART2_IT_RXNE_OR), set the read completion flag (synchronization processing)
if( read_idx == read_len ) {
UART2_ITConfig(UART2_IT_RXNE_OR, DISABLE);
read_ok = 1;
}
}
5. Use code examples
// Write 2 bytes
uint8_t buf[32];
memset(buf, 0x00, sizeof(buf));
buf[0] = 0xCC;
buf[1] = 0xDD;
uart_send_n_byte(buf, 2);
// Simple read (must read 24 bytes before returning)
memset(buf, 0x00, sizeof(buf));
uart_send_n_byte(buf, 24);
Previous article:Usage of UART in stm8s (four types of UART interrupts)
Next article:UART0 serial port programming (III): interrupt mode serial port programming; use interrupt to write and send
Recommended ReadingLatest update time:2024-11-16 12:48
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
- [AutoChips AC7801x motor demo board review] + unboxing and GPIO lighting
- About the master: zhang2018yi
- Qorvo has a few things to tell you about WiFi 6
- What kind of switch is this? Where can I buy one?
- Chapter 3: Use of GPIO
- Software Installation
- If you don’t lose weight in spring, you will regret it in summer. Let me share some tips on how to lose weight and keep in shape!
- [Embedded Linux] RK3399 Android7.1 CPU is overheating
- 【Chuanglong TL570x-EVM】Button control LED light
- TI Automotive SPD-SmartGlass Driver Reference Design