There are three basic ways to send and receive data in STM32F10x UART: polling, interrupt and DMA
1. Polling method
The following is an example of polling UART initialization and sending and receiving. Both sending and receiving use polling.
uint8_t TxBuffer[] = "Buffer Send from USARTy to USARTz using Flags";
uint8_t RxBuffer[TxBufferSize];
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file
*/
/* System Clocks Configuration */
RCC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
/* USARTy and USARTz configuration ---------------------------------------------------- ----------*/
/* USARTy and USARTz configured as follow:
- BaudRate = 230400 baud
- Word Length = 8 Bits
- One Stop Bit
- Even parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 230400;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USARTy */
USART_Init(USARTy, &USART_InitStructure);
/* Configure USARTz */
USART_Init(USARTz, &USART_InitStructure);
/* Enable the USARTy */
USART_Cmd(USARTy, ENABLE);
/* Enable the USARTz */
USART_Cmd(USARTz, ENABLE);
while(TxCounter < TxBufferSize)
{
/* Send one byte from USARTy to USARTz */
USART_SendData(USARTy, TxBuffer[TxCounter++]);
/*
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DATA(Data));
USARTx->DR = (Data & (uint16_t)0x01FF); //Write the data to be sent to DR
}
*/
/* Loop until USARTy DR register is empty */
while(USART_GetFlagStatus(USARTy, USART_FLAG_TXE) == RESET)
{
}
//Here it means data sending is complete (USART_FLAG_TXE can refer to STM32F10x usart register description)
/* Loop until the USARTz Receive Data Register is not empty */
while(USART_GetFlagStatus(USARTz, USART_FLAG_RXNE) == RESET)
{
}
//Here it means data reception is complete (USART_FLAG_RXNE can refer to STM32F10x usart register description)
/* Store the received byte in RxBuffer */
RxBuffer[RxCounter++] = (USART_ReceiveData(USARTz) & 0x7F);
}
//The following is just to see whether the sent and received data are consistent. This is related to the test conditions and will not be repeated here.
/* Check the received data with the send ones */
TransferStatus = Buffercmp(TxBuffer, RxBuffer, TxBufferSize);
/* TransferStatus = PASSED, if the data transmitted from USARTy and
received by USARTz are the same */
/* TransferStatus = FAILED, if the data transmitted from USARTy and
received by USARTz are different */
while (1)
{
}
}
2. Interrupt mode reading and writing
The STM32F10x USART has many types of interrupts, each of which has an enable flag.
The process of interrupt setting and using ringbuffer input and output is as follows
(1) Interrupt initialization
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USARTy_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable USARTy Receive and Transmit interrupts */
USART_ITConfig(USARTy, USART_IT_RXNE, ENABLE);
USART_ITConfig(USARTy, USART_IT_TXE, ENABLE);
Generally, for a USART port, an interrupt bit must be set for input and output to trigger input and output interrupts. Generally, only the following two interrupts need to be set for input and output.
USART_IT_RXNE:Receive Data register not empty interrupt
USART_IT_TXE: Transmit Data Register empty interrupt
There are other interrupt bits explained as follows:
USART_IT_CTS: CTS change interrupt
USART_IT_LBD: LIN Break detection interrupt
USART_IT_TC: Transmission complete interrupt
USART_IT_IDLE: Idle line detection interrupt
USART_IT_PE: Parity Error interrupt
USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
After setting the USART_IT_RXNE and USART_IT_TXE interrupts, both reading and writing will trigger interrupts.
Here we generally do not use USART_IT_TC interrupt, because generally use the transmit data register empty interrupt (USART_IT_TXE)
The sending efficiency will be higher.
The following example uses a ringbuffer and interrupt mode to familiarize yourself with interrupt reading and writing.
(Reference: http://blog.csdn.net/liyuanbhu/article/details/8886407)
The framework of the interrupt processing function is as follows: if an error is detected, the error is cleared, and if a number is received, it is processed. After the current data is sent, the next one is sent.
void USART1_IRQHandler(void)
{
unsigned int data;
if(USART1->SR & 0x0F)
{
// See if we have some kind of error, Clear interrupt
data = USART1->DR;
}
else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
{
data = USART1->DR;
// Process the received data, or do something else
}
else if(USART1->SR & USART_FLAG_TXE)
{
{ // Data can be sent. If there is no data to send, turn off the send interrupt here
USART1->DR = something; // Yes, Send character
}
}
}
Below is a serial port driver that uses a ring buffer.
#ifndef _COM_BUFFERED_H_
#define _COM_BUFFERED_H_
#define COM1 0
#define COM2 1
#define COM_RX_BUF_SIZE 64 /* Number of characters in Rx ring buffer */
#define COM_TX_BUF_SIZE 64 /* Number of characters in Tx ring buffer */
#define COM_NO_ERR 0 /* Function call was successful */
#define COM_BAD_CH 1 /* Invalid communications port channel */
#define COM_RX_EMPTY 2 /* Rx buffer is empty, no character available */
#define COM_TX_FULL 3 /* Tx buffer is full, could not deposit character */
#define COM_TX_EMPTY 4 /* If the Tx buffer is empty. */
/************************************************************
* function : COMGetCharB
* parameter: char port, port can be COM1 / COM2
* parameter: char* err is a pointer to where an error code will be placed:
* *err is set to COM_NO_ERR if a character is available
* *err is set to COM_RX_EMPTY if the Rx buffer is empty
* *err is set to COM_BAD_CH if you have specified an invalid channel
* return : char
* usage : This function is called by your application to obtain a character from the communications
* channel.
* changelog:
*************************************************************/
unsigned char COMGetCharB (unsigned char ch, unsigned char *err);
/************************************************************
* function : COMPutCharB
* parameter: char port, port can be COM1 / COM2
* return : COMM_NO_ERR if the function was successful (the buffer was not full)
* COMM_TX_FULL if the buffer was full
* COMM_BAD_CH if you have specified an incorrect channel
* usage : This function is called by your application to send a character on the communications
* channel. The character to send is first inserted into the Tx buffer and will be sent by
* the Tx ISR. If this is the first character placed into the buffer, the Tx ISR will be
* enabled. If the Tx buffer is full, the character will not be sent (i.e. it will be lost)
* changelog:
*************************************************************/
unsigned char COMPutCharB (unsigned char port, unsigned char c);
/************************************************************
* function : COMBufferInit
* parameter:
* return :
* usage : This function is called by your application to initialize the communications module. You
* must call this function before calling any other functions.
* changelog:
*************************************************************/
void COMBufferInit (void);
/************************************************************
* function : COMBufferIsEmpty
* parameter: char port, port can be COM1 / COM2
* return : char
* usage : This function is called by your application to see
* if any character is available from the communications channel.
* If at least one character is available, the function returns
* FALSE(0) otherwise, the function returns TRUE(1).
* changelog:
*************************************************************/
unsigned char COMBufferIsEmpty (unsigned char port);
/************************************************************
* function : COMBufferIsFull
* parameter: char port, port can be COM1 / COM2
* return : char
* usage : This function is called by your application to see if any more characters can be placed
* in the Tx buffer. In other words, this function check to see if the Tx buffer is full.
* If the buffer is full, the function returns TRUE otherwise, the function returns FALSE.
* changelog:
*************************************************************/
unsigned char COMBufferIsFull (unsigned char port);
#endif
/*
* file: com_buffered.c
* author: Li Yuan
* platform: STM32F107
* date: 2013-5-5
* version: 0.0.1
* description: UART Ring Buffer
**/
#include "stm32f10x_usart.h"
#include "com_buffered.h"
#define OS_ENTER_CRITICAL() __set_PRIMASK(1)
#define OS_EXIT_CRITICAL() __set_PRIMASK(0)
/**
* Enables Transmiter interrupt.
**/
static void COMEnableTxInt(unsigned char port)
{
static USART_TypeDef* map[2] = {USART1, USART2};
USART_ITConfig(map[port], USART_IT_TXE, ENABLE);
}
/*
*********************************************************************************************************
* DATA TYPES
*********************************************************************************************************
*/
typedef struct {
short RingBufRxCtr; /* Number of characters in the Rx ring buffer */
unsigned char *RingBufRxInPtr; /* Pointer to where next character will be inserted */
unsigned char *RingBufRxOutPtr; /* Pointer from where next character will be extracted */
unsigned char RingBufRx[COM_RX_BUF_SIZE]; /* Ring buffer character storage (Rx) */
short RingBufTxCtr; /* Number of characters in the Tx ring buffer */
unsigned char *RingBufTxInPtr; /* Pointer to where next character will be inserted */
unsigned char *RingBufTxOutPtr; /* Pointer from where next character will be extracted */
unsigned char RingBufTx[COM_TX_BUF_SIZE]; /* Ring buffer character storage (Tx) */
} COM_RING_BUF;
/*
*********************************************************************************************************
* GLOBAL VARIABLES
*********************************************************************************************************
*/
COM_RING_BUF COM1Buf;
COM_RING_BUF COM2Buf;
/************************************************************
* function : COMGetCharB
* parameter: char port, port can be COM1 / COM2
* parameter: char* err is a pointer to where an error code will be placed:
* *err is set to COM_NO_ERR if a character is available
* *err is set to COM_RX_EMPTY if the Rx buffer is empty
* *err is set to COM_BAD_CH if you have specified an invalid channel
* return : char
* usage : This function is called by your application to obtain a character from the communications
* channel.
* changelog:
*************************************************************/
unsigned char COMGetCharB (unsigned char port, unsigned char *err)
{
// unsigned char cpu_sr;
unsigned char c;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
*err = COM_BAD_CH;
return (0);
}
OS_ENTER_CRITICAL();
if (pbuf->RingBufRxCtr > 0) /* See if buffer is empty */
{
pbuf->RingBufRxCtr--; /* No, decrement character count */
c = *pbuf->RingBufRxOutPtr++; /* Get character from buffer */
if (pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE])
{
pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0]; /* Wrap OUT pointer */
}
OS_EXIT_CRITICAL();
*err = COM_NO_ERR;
return (c);
} else {
OS_EXIT_CRITICAL();
*err = COM_RX_EMPTY;
c = 0; /* Buffer is empty, return 0 */
return (c);
}
}
/************************************************************
* function : COMPutCharB
* parameter: char port, port can be COM1 / COM2
* return : COMM_NO_ERR if the function was successful (the buffer was not full)
* COMM_TX_FULL if the buffer was full
* COMM_BAD_CH if you have specified an incorrect channel
* usage : This function is called by your application to send a character on the communications
* channel. The character to send is first inserted into the Tx buffer and will be sent by
* the Tx ISR. If this is the first character placed into the buffer, the Tx ISR will be
* enabled. If the Tx buffer is full, the character will not be sent (i.e. it will be lost)
* changelog:
* 1.first implimented by liyuan 2010.11.5
*************************************************************/
unsigned char COMPutCharB (unsigned char port, unsigned char c)
{
// unsigned char cpu_sr;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
return (COM_BAD_CH);
}
OS_ENTER_CRITICAL();
if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) { /* See if buffer is full */
pbuf->RingBufTxCtr++; /* No, increment character count */
*pbuf->RingBufTxInPtr++ = c; /* Put character into buffer */
if (pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE]) { /* Wrap IN pointer */
pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];
}
if (pbuf->RingBufTxCtr == 1) { /* See if this is the first character */
COMEnableTxInt(port); /* Yes, Enable Tx interrupts */
OS_EXIT_CRITICAL();
} else {
OS_EXIT_CRITICAL();
}
return (COM_NO_ERR);
} else {
OS_EXIT_CRITICAL();
return (COM_TX_FULL);
}
}
/************************************************************
* function : COMBufferInit
* parameter:
* return :
* usage : This function is called by your application to initialize the communications module. You
* must call this function before calling any other functions.
* changelog:
*************************************************************/
void COMBufferInit (void)
{
COM_RING_BUF *pbuf;
pbuf = &COM1Buf; /* Initialize the ring buffer for COM0 */
pbuf->RingBufRxCtr = 0;
pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];
pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
pbuf->RingBufTxCtr = 0;
pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];
pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
pbuf = &COM2Buf; /* Initialize the ring buffer for COM1 */
pbuf->RingBufRxCtr = 0;
pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];
pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
pbuf->RingBufTxCtr = 0;
pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];
pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
}
/************************************************************
* function : COMBufferIsEmpty
* parameter: char port, port can be COM1 / COM2
* return : char
* usage : This function is called by your application to see
* if any character is available from the communications channel.
* If at least one character is available, the function returns
* FALSE(0) otherwise, the function returns TRUE(1).
* changelog:
*************************************************************/
unsigned char COMBufferIsEmpty (unsigned char port)
{
// unsigned char cpu_sr;
unsigned char empty;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
return (1);
}
OS_ENTER_CRITICAL();
if (pbuf->RingBufRxCtr > 0)
{ /* See if buffer is empty */
empty = 0; /* Buffer is NOT empty */
}
else
{
empty = 1; /* Buffer is empty */
}
OS_EXIT_CRITICAL();
return (empty);
}
/************************************************************
* function : COMBufferIsFull
* parameter: char port, port can be COM1 / COM2
* return : char
* usage : This function is called by your application to see if any more characters can be placed
* in the Tx buffer. In other words, this function check to see if the Tx buffer is full.
* If the buffer is full, the function returns TRUE otherwise, the function returns FALSE.
* changelog:
*************************************************************/
unsigned char COMBufferIsFull (unsigned char port)
{
// unsigned char cpu_sr;
char full;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
return (1);
}
OS_ENTER_CRITICAL();
if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) { /* See if buffer is full */
full = 0; /* Buffer is NOT full */
} else {
full = 1; /* Buffer is full */
}
OS_EXIT_CRITICAL();
return (full);
}
// This function is called by the Rx ISR to insert a character into the receive ring buffer.
static void COMPutRxChar (unsigned char port, unsigned char c)
{
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
return;
}
if (pbuf->RingBufRxCtr < COM_RX_BUF_SIZE) { /* See if buffer is full */
pbuf->RingBufRxCtr++; /* No, increment character count */
*pbuf->RingBufRxInPtr++ = c; /* Put character into buffer */
if (pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE]) { /* Wrap IN pointer */
pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];
}
}
}
// This function is called by the Tx ISR to extract the next character from the Tx buffer.
// The function returns FALSE if the buffer is empty after the character is extracted from
// the buffer. This is done to signal the Tx ISR to disable interrupts because this is the
// last character to send.
static unsigned char COMGetTxChar (unsigned char port, unsigned char *err)
{
unsigned char c;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
*err = COM_BAD_CH;
return (0);
}
if (pbuf->RingBufTxCtr > 0) { /* See if buffer is empty */
pbuf->RingBufTxCtr--; /* No, decrement character count */
c = *pbuf->RingBufTxOutPtr++; /* Get character from buffer */
if (pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE])
{
pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0]; /* Wrap OUT pointer */
}
*err = COM_NO_ERR;
return (c); /* Characters are still available */
} else {
*err = COM_TX_EMPTY;
return (0); /* Buffer is empty */
}
}
void USART1_IRQHandler(void)
{
unsigned int data;
unsigned char err;
if(USART1->SR & 0x0F)
{
// See if we have some kind of error
// Clear interrupt (do nothing about it!)
data = USART1->DR;
}
else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
{
data = USART1->DR;
COMPutRxChar(COM1, data); // Insert received character into buffer
}
else if(USART1->SR & USART_FLAG_TXE)
{
data = COMGetTxChar(COM1, &err); // Get next character to send.
if (err == COM_TX_EMPTY)
{ // Do we have anymore characters to send ?
// No, Disable Tx interrupts
//USART_ITConfig(USART1, USART_IT_TXE| USART_IT_TC, ENABLE);
USART1->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;
}
else
{
USART1->DR = data; // Yes, Send character
}
}
}
void USART2_IRQHandler(void)
{
unsigned int data;
unsigned char err;
if(USART2->SR & 0x0F)
{
// See if we have some kind of error
// Clear interrupt (do nothing about it!)
data = USART2->DR;
}
else if(USART2->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
{
data = USART2->DR;
COMPutRxChar(COM2, data); // Insert received character into buffer
}
else if(USART2->SR & USART_FLAG_TXE)
{
data = COMGetTxChar(COM2, &err); // Get next character to send.
if (err == COM_TX_EMPTY)
{ // Do we have anymore characters to send ?
// No, Disable Tx interrupts
//USART_ITConfig(USART2, USART_IT_TXE| USART_IT_TC, ENABLE);
USART2->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;
}
else
{
USART2->DR = data; // Yes, Send character
}
}
}
Here is an example main program to demonstrate how to use the above serial port driver code.
#include "misc.h"
#include "stm32f10x.h"
#include "com_buffered.h"
void UART_PutStrB (unsigned char port, uint8_t *str)
{
while (0 != *str)
{
COMPutCharB(port, *str);
str++;
}
}
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure );
USART_Cmd(USART1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure );
USART_Cmd(USART2, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
unsigned char c;
unsigned char err;
USART1_Init();
USART2_Heat();
COMBufferInit();
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
UART_PutStrB(COM1, "Hello World!\n");
for(;;)
{
c = COMGetCharB(COM1, &err);
if(err == COM_NO_ERR)
{
COMPutCharB(COM1, c);
}
}
}
Previous article:STM32 implements IAP and APP file merging
Next article:Use xmake to build STM32 program
- Popular Resources
- Popular amplifiers
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
- 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
- Notice on the one-week ban of netizen "深圳小花"
- MicroPython v2.0 roadmap
- LOTO Lesson 5: Triode Audio Amplifier Circuit Practice
- Computer power supply plus current regulation
- PCB design software Protel 99 SE and AD copper-free hole and copper-free slot design
- Why is a bootstrap circuit used in BUCK power chip?
- The circuit observation room has changed
- The states of the terminal device in the TI ZigBee protocol stack involved in the protocol stack
- Shanghai Hangxin ACM32F070 Development Board + Touch Function Evaluation Board Evaluation - Chapter 6 CAN Error Handling
- Has anyone encountered Ubuntu 20.04's suspended animation?