بستن اطلاعیه
مهمان عزیز لطفا جهت ثبت نام فقط از ایمیل های گوگل "Gmail" استفاده کنید!

بافر FIFO و نمونه کد

شروع موضوع توسط Alma ‏7/9/17 در انجمن زبان C و خانواده آن

  1. Alma

    Alma مدیر عضو کادر مدیریت

    بافر fifo یکی از کاربردی ترین ،ساده ترین و بهترین راه های بافرهای دیتا هست
    این بافر به صورت حلقه هست به صورتی که دیتایی از بین نمیره و کلیه اطلاعات جدید از اخرین موقعیت دیتایی که در بافر نوشته شده قرار میگیره و دیتایی که خونده میشه از اخرین موقعیت دیتایی که خونده شده کم میشه
    کلا ممکنه سه وضعیت مهم وجود داشته باشه
    1- زمانی که بافر خالی هست :
    در صورتی که متغیر ادرس نوشتن با متغیر ادرس خوندن برابر باشه
    upload_2017-9-7_23-27-8.png
    2- زمانی که دیتایی در بافر داریم :
    در صورتی که متغیر ادرس خوندن و نوشتن برابر نباشن
    upload_2017-9-7_23-27-31.png
    3- زمانی که بافر فول هست و جایی برای دیتایی جدید نیست :
    در صورتی که متغیر کانتر دیتا با تعداد اعضای ماغیر بافر برابر باشه
    upload_2017-9-7_23-27-55.png

    در صورت کلی برای پیاده کردن یه بافر fifo به سه تا متغیر و یک رشته نیاز هست
    متغیر اول کانتر تعداد دیتای نوشته شده در بافر
    متغیر ادرس اخرین دیتای نوشته شده
    متغیر ادرس اخرین دیتای خونده شده
    طبق توضیحات بالا میشه به راحتی با چند خط کد ساده این بافر رو پیاده کرد

    برای راحتی کار به یک استراکچر نیاز داری که همه متغیر های توضیح داده شده بالا توش قرار گرفته باشن
    و همچنین تعداد اعضای بافر رو هم دیفاین کنیم
    یه چیزی مشابه این

    کد:
    #define BUFFSIZE    128
    
    typedef struct{
        uint16_t in;            //index points to start
        uint16_t out;            //index points to start
        uint16_t count;            //bytes in buffer
        //uint8_t ncr;            //new command received
        uint8_t buff[BUFFSIZE];    //buffer
    }FIFO_TypeDef;

    برای خطا ها هم یه یونیون مینویسیم
    که دو تا وضعیت خطا و بدون خطا داشته باشه با این شکل

    کد:
    typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;

    برای راحتی کار میتونیم تعداد بایتی که میخواییم از بافر بخونیم با بنویسیم رو به عنوان ورودی توابع علاوه بر استراکچر بافر به تابع بدیم
    که برای هر بایت خوندن یا نوشتن دیتای تابع فراخانی نشه
    حالا باید دوتا تابع بنویسیم یکی برای نوشتن در بافر به این شکل

    کد:
    ErrorStatus BufferPut(__IO FIFO_TypeDef *buffer, uint8_t ch){
        if(buffer->count==BUFFSIZE)return ERROR;//buffer full
        //if(buffer->buff[buffer->in - 1] == '\r' && ch == '\n')buffer->ncr++;
        buffer->buff[buffer->in++] = ch;
        buffer->count++;
        if(buffer->in==BUFFSIZE)buffer->in=0;//start from beginning
        return SUCCESS;
    }
    و برای خوندن به این شکل

    کد:
    ErrorStatus BufferGet(__IO FIFO_TypeDef *buffer, uint8_t *ch){
        if(buffer->count==0)return ERROR;//buffer empty
        *ch = buffer->buff[buffer->out];
        //if(buffer->buff[buffer->out - 1] == '\r' && *ch == '\n' && buffer->ncr)buffer->ncr--;
        buffer->out++;
        buffer->count--;
        if(buffer->out==BUFFSIZE)buffer->out=0;//start from beginning
        return SUCCESS;
    }
    حالا میتونیم برای پاک کردن سریع بافر هم یه تابع دیگه بنویسیم به این صورت

    کد:
    void BufferInit(__IO FIFO_TypeDef *buffer){
        buffer->count = 0;
        buffer->in = 0;
        buffer->out = 0;
        buffer->ncr = 0;
    }
    میتونیم تابع ساده دیگه ای هم بنویسیم که خالی بودن بافر رو برگردونه به این شکل

    کد:
    ErrorStatus BufferIsEmpty(__IO FIFO_TypeDef buffer){
        if(buffer.count==0)return SUCCESS;//buffer full
        return ERROR;
    }

به اشتراک بگذارید