以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這個中斷就可以了。