單片機FIFO串口中斷髮送數據

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章