|
发表于 2021-1-7 10:58:00
|
显示全部楼层
//请看我一直使用的串口中断接收与发送的代码,一直运行的非常好
/*----------------------------------------------------------------------------
* Name: Usart.c
* Purpose: USART usage for STM32
* Version: V1.10
*----------------------------------------------------------------------------
* 关于usart接收中断的BUG和注意事项:
* 1.USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
* 使能了接收中断,那么ORE中断也同时被开启了。
*
* 2.ORE中断只能使用USART_GetFlagStatus(USART1, USART_FLAG_ORE)
* 读到(没有使能USART_IT_ERR中断时)
*----------------------------------------------------------------------------*/
#define TBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
#define RBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
struct buf_st {
unsigned int in; // Next In Index
unsigned int out; // Next Out Index
char buf [RBUF_SIZE]; // Buffer
};
static struct buf_st rbuf = { 0, 0, };
#define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))
static struct buf_st tbuf = { 0, 0, };
#define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))
static unsigned int tx_restart = 1; // NZ if TX restart is required
/*------------------------------------------------------------------------------
buffer_Init
initialize the buffers
*------------------------------------------------------------------------------*/
void uart_buffer_Init (void) {
tbuf.in = 0; // Clear com buffer indexes
tbuf.out = 0;
tx_restart = 1;
rbuf.in = 0;
rbuf.out = 0;
}
/*------------------------------------------------------------------------------
SenChar
transmit a character
*------------------------------------------------------------------------------*/
int SendChar (int c) {
struct buf_st *p = &tbuf;
if (SIO_TBUFLEN >= TBUF_SIZE) /* If the buffer is full */
return (-1); /* return an error value */
p->buf [p->in & (TBUF_SIZE - 1)] = c; /* Add data to the transmit buffer. */
p->in++;
if (tx_restart) { /* If TX interrupt is disabled */
tx_restart = 0; /* enable it */
USART1->CR1 |= USART_SR_TXE; /* enable TX interrupt */
}
return (0);
}
/*------------------------------------------------------------------------------
GetKey
receive a character
*------------------------------------------------------------------------------*/
char GetKey (void) {
struct buf_st *p = &rbuf;
if (SIO_RBUFLEN == 0)
return (char)-1;
return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);
}
/*----------------------------------------------------------------------------
USART1_IRQHandler
Handles USART1 global interrupt request.
*----------------------------------------------------------------------------*/
void USART1_IRQHandler (void)
{
volatile unsigned short rcv_rd;
volatile unsigned int IIR;
struct buf_st *p;
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL();
OSIntNesting++;
OS_EXIT_CRITICAL();
IIR = USART1->SR;
if (IIR & USART_FLAG_RXNE) { // read interrupt
USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt
p = &rbuf;
if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0) {
p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
p->in++;
}
else //继续读取
rcv_rd= (USART1->DR & 0x1FF);
}
if (IIR & USART_FLAG_TXE) {
USART1->SR &= ~USART_FLAG_TXE; // clear interrupt
p = &tbuf;
if (p->in != p->out) {
USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
p->out++;
tx_restart = 0;
}else {
tx_restart = 1;
USART1->CR1 &= ~USART_FLAG_TXE; // disable TX interrupt if nothing to send
}
}
//如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET){
USART_ClearFlag(USART1,USART_FLAG_ORE); //读SR
USART_ReceiveData(USART1); //读DR
}
OSIntExit();
}
|
|