单片机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这个中断就可以了。

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