以51单片机为例,直接上干货——代码:
#define BUFFER_SIZE 128
typedef struct
{
unsigned char ri, wi, ct, run;
unsigned char buff[BUFFER_SIZE];
} UARTFIFO;
static volatile UARTFIFO Uart1TxFifo;
void Uart1Init(void) //[email protected]
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xD0; //设定定时初值
TH1 = 0xFF; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
Uart1TxFifo.ri = 0;
Uart1TxFifo.wi = 0;
Uart1TxFifo.ct = 0;
Uart1TxFifo.run = 0;
ES = 1; //开启串口中断,别忘开启总中断
}
void Uart1PutC(unsigned char d)
{
unsigned int i;
while (Uart1TxFifo.ct >= BUFFER_SIZE) ;
i = Uart1TxFifo.wi;
Uart1TxFifo.buff[i++] = d;
Uart1TxFifo.wi = i % BUFFER_SIZE;
ES= 0;//因为下面这些值只在串口中断中才有机会被改变,所以只关闭串口中断,如果在实际应用中,在多处中断里值被改变,建议直接关总中断
Uart1TxFifo.ct++;
if (!Uart1TxFifo.run)
{
Uart1TxFifo.run = 1;
TI = 1;
}
ES = 1;
}
void Uart1PutS(const char *st)
{
while (*st)
{
Uart1PutC(*st++);
}
}
void Uart1IRQ(void) interrupt 4
{
if (TI)
{
unsigned int i;
TI = 0;
i = Uart1TxFifo.ct;
if (i)
{
Uart1TxFifo.ct = --i;
i = Uart1TxFifo.ri;
SBUF = Uart1TxFifo.buff[i++];
Uart1TxFifo.ri = i % BUFFER_SIZE;
}
else
{
Uart1TxFifo.run = 0;
}
}
if (RI)
{
RI = 0;
}
}
上面这种方式发送数据的好处就不多说了,懂的人自然懂,不懂的人说了也白说。
额外再多说一句,如果是用STM32,则不需要run这个变量,直接开启TXE这个中断就可以了。