电竞比分网-中国电竞赛事及体育赛事平台

分享

51單片機(jī)串口通信 環(huán)形緩沖區(qū)隊(duì)列(FIFO)

 袁先森lemon 2018-12-21

51單片機(jī)串口通信 環(huán)形緩沖區(qū)隊(duì)列

最近在做畢業(yè)設(shè)計(jì)剛好涉及到51單片機(jī),簡單的研究一下發(fā)現(xiàn)51單片機(jī)串口只有一個字節(jié)的緩存,如果遇到單片機(jī)串口中斷沒有及時(shí)處理SBUF的值或者串口中斷長時(shí)間未退出很容易照成數(shù)據(jù)丟失,于是就自己寫了個緩沖區(qū),代價(jià)就是消耗一部分內(nèi)存空間,時(shí)間-空間本來就是一對矛盾體,想減少串口通信中數(shù)據(jù)丟失問題只能犧牲部分空間,來減少數(shù)據(jù)通信過程中的丟失問題。

  1. 核心代碼如下所示:
/**
    用途:     小內(nèi)存環(huán)形緩沖區(qū)(FIFO模式)
    作者: 南梔<kellygod95@gmail.com>
*/
#define BUFFER_MAX  16      //緩沖區(qū)大小

typedef struct _circle_buffer{
    unsigned char head_pos;             //緩沖區(qū)頭部位置
    unsigned char tail_pos;             //緩沖區(qū)尾部位置   
    unsigned char circle_buffer[BUFFER_MAX];    //緩沖區(qū)數(shù)組 
}circle_buffer;

circle_buffer buffer;

void bufferPop(unsigned char* _buf)
{
    if(buffer.head_pos==buffer.tail_pos)        //如果頭尾接觸表示緩沖區(qū)為空
        *_buf=0xFF;
    else
    {
        *_buf=buffer.circle_buffer[buffer.head_pos];    //如果緩沖區(qū)非空則取頭節(jié)點(diǎn)值并偏移頭節(jié)點(diǎn)
        if(++buffer.head_pos>=BUFFER_MAX)
            buffer.head_pos=0;
    }
}

void bufferPush(const unsigned char _buf)
{   
    buffer.circle_buffer[buffer.tail_pos]=_buf; //從尾部追加
    if(++buffer.tail_pos>=BUFFER_MAX)           //尾節(jié)點(diǎn)偏移
        buffer.tail_pos=0;                      //大于數(shù)組最大長度 制零 形成環(huán)形隊(duì)列
        if(buffer.tail_pos==buffer.head_pos)    //如果尾部節(jié)點(diǎn)追到頭部節(jié)點(diǎn) 則修改頭節(jié)點(diǎn)偏移位置丟棄早期數(shù)據(jù)
        if(++buffer.head_pos>=BUFFER_MAX)
            buffer.head_pos=0;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

考慮到看到此博文的人可能有很多小白并不知道如何使用,在此簡單的說一下,假設(shè)你已經(jīng)能進(jìn)行簡單的串口發(fā)送接收了,然后串口中斷部分可以這樣寫

void serial1(void) interrupt 4
{
    if(RI)
    {
        bufferPush(SBUF);
        RI=0;       
    }
    if(TI)
    {
        TI=0;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在主程序中我們只需要調(diào)用函數(shù)就行了如:

void main()
{
    unsigned char dat ;
//讀取緩沖區(qū)一個字符,如果dat=0xff表示緩沖區(qū)為空,所以接收的字符不能有0xff。
    bufferPop(&dat);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

bufferPop函數(shù)中沒調(diào)用一次,便從緩沖區(qū)取出一個字符,頭部指針就會進(jìn)行偏移,具體看源碼并不是很復(fù)雜 只是一個數(shù)組類型的環(huán)形FIFO緩沖區(qū)。

有一點(diǎn)要注意的是,如果緩沖區(qū)滿的話,后面的數(shù)據(jù)會覆蓋最前面的數(shù)據(jù)。

你可以把緩沖區(qū)設(shè)置大些,就可以盡可能的減少數(shù)據(jù)覆蓋問題,但是帶來的額外問題就是51或者其他系列的單片機(jī)RAM是非常小的,并不像PC中緩沖區(qū)動不動就1024KB。所以緩沖區(qū)設(shè)置多大,根據(jù)自己需求調(diào)整就行了。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多