//******************************************************************************** // Описание и создание циклического буфера , функции доступа к циклическому буферу. // Для того чтобы применить эту структуру у себя в программе необходимо: // 1) Подключить ее к своему проекту. // ---//---- // // #include "CirclBuffer.h" // ---//---- // 2)Создать буфер ( или несколько буферов) с помощью макроса ConstrCirclBuffer. // ---//---- // ConstrCirclBuffer(MyBuffer,10) // --------//------- // 3) Использовать доступ к буферу через функции Write , Read, CheckRead, CheckWrite. // **Примеры использования** // void main(void) // { // -----//--------- // // // char MyVariabl=12; // Опишем и проинициализируем свои переменные // char MyVariab2=0x33; // MyVariabl,MyVariab2 // ------//--------- // WWrite(MyVariable1,&MyBuffer); // Запись переменной MyVariabl // // в циклический буфер MyBuffer без проверки переполнени // IF (CheckWrite(&MyBuffer)) Write(MyVariable2,&MyBuffer); // Запись переменной MyVariab2 // // в циклический буфер MyBuffer c проверкой проверкой переполнени // while (Write(MyVariable1,&MyBuffer)); // Запись переменной MyVariab1 // // в циклический буфер MyBuffer c проверкой проверки переполнени // MyVariabl = Read(&MyBuffer); // Чтения байта из буфера MyBuffer без проверки // // состояния буфера // while (CheckRead(&MyBuffer)) MyVariab2 = Read(&MyBuffer); // Чтения байта из буфера MyBuffer c проверкой // // состояния буфера // -------//------ // } // // // // //******************************************************************************** // ConstrCirclBuffe(MyBuffer,12) // Создает объект - циклический буфер // - структуру с именем MyBuffer и массив размерностью // 12 байт адрес которого содержится в структуре MyBuffer // //******************************************************* #define ConstrCirclBuffer(Name,SizeBuffer) unsigned char (Name##2)[SizeBuffer];\ CirclBuffer Name = {0,0,0,SizeBuffer,(Name##2)} //******************************************************* typedef struct {unsigned char Head; // unsigned char Tail; // unsigned char Flag; // unsigned char Size; // unsigned char *Buffer; // }CirclBuffer; // #define SetBit0( Name) Name|=0x01 #define SetBit1( Name) Name|=0x02 #define ClearBit0( Name) Name&=0xFE #define ClearBit1( Name) Name&=0xFD #define CheckBit0( Name) (Name & 0x01) #define CheckBit1( Name) (Name & 0x02) //******************************************************* // Функция записи байта InByte в буфер структуры CirclBuffer Name // Структура Name передается в функцию в виде указател // ** Пример использовани // Write(MyBuffer,MyVariabl); // Запись переменной MyVariabl в циклический буфер // MyBuffer. (циклический буфер MyBuffer должен быть определен выше макросом // ConstrCirclBuffe ) //*********************************************** unsigned char Write (unsigned char InByte,CirclBuffer *Name ) // Получим адрес структуры { if (!CheckBit1(Name->Flag)) // Проверим флаг БУФЕР ПОЛОН { // Если он сброшен то будем производить запись в буфер // di // Запретим прерывания для исключения одновременного доступа // ( запись , чтение одно в подпрограмме прерывании другое в фоновой программе) // к буферу и его флагам if (++Name->Head >= (Name->Size)) // Проверим на равенство указатель записи и объем буфера // Если указатель записи больше или равен объему буфера { Name->Head = 0; // то обнуляем указатель записи } if ( Name->Tail == Name->Head ) // Проверим на равенство указатель чтения и указатель записи { // Если указатель чтения равен указателю записи SetBit1(Name->Flag); // устанавливаем флаг БУФЕР ПОЛОН } else { // Если указатель чтения не равен указателю записи ClearBit1 (Name->Flag); // сбрасываем флаг БУФЕР ПОЛОН } Name->Buffer[Name->Head]=InByte; // Производим запись в буфер и ClearBit0 (Name->Flag); // сбрасываем флаг БУФЕР ПУСТ // ei // Разрешим прерывани return 0xFF; // признак того что запись в буфер произведена // успешно. } // Если флаг БУФЕР ПОЛОН установлен то return 0x00; // запись в буфер не производилась т.к. БУФЕР ПОЛОН } // Возвращаем признак 0 //******************************************************* // Функция чтения байта из буфера структуры CirclBuffer Name // Структура Name передается в функциюв виде указател // Функция возвращает прочитанный байт // ** Пример использовани // MyVariabl = Read(MyBuffer); // Чтение байта из циклического буфера MyBuffer // в переменную MyVariabl . // (циклический буфер MyBuffer должен быть определен выше макросом // ConstrCirclBuffe ) //*********************************************** //*********************************************** unsigned char Read (CirclBuffer *Name ) { unsigned char Tmp; if (!CheckBit0(Name->Flag)) // Проверим флаг БУФЕР ПУСТ { // Если он сброшен то будем производить чтение из буфера //di // Запретим прерывания для исключения одновременного доступа // ( запись , чтение - одно в подпрограмме прерывании другое в фоновой программе) // к буферу и его флагам if (++Name->Tail >= (Name->Size)) // Проверим на равенство указатель чтения и объем буфера { // Если указатель чтения больше или равен объему буфера Name->Tail = 0; // то обнуляем указатель чтени } if ( Name->Tail == Name->Head ) // Проверим на равенство указатель чтения и указатель записи { // Если они равны SetBit0(Name->Flag); // Флаг БУФЕР ПУСТ установлен } else { // Если указатель чтения не равен указателю записи ClearBit0 (Name->Flag); // Флаг БУФЕР ПУСТ сброшен } ClearBit1 (Name->Flag); // Флаг БУФЕР ПОЛОН сброшен Tmp = Name->Buffer[Name->Tail]; // ei // Разрешим прерывани return Tmp; // Возвращаем прочитанный байт } // Если флаг БУФЕР ПУСТ установлен то // возвращаем результат 0 return 0x00; } //******************************************************* // Функция Проверки доступности буфера структуры CirclBuffer Name // на чтение // структура Name передается в функциюв виде указател // Функция возвращает 0x00 признак того что буфер пуст // и 0xFF признак того что буфер содержит данные доступные // для чтени // ** Пример использовани // while (CheckRead(&MyBuffer)) Tmp = Read(&MyBuffer); // Пока в буфере есть не считанные байты считывать их в переменную TMP. // (циклический буфер MyBuffer должен быть определен выше макросом // ConstrCirclBuffe ) //*********************************************** unsigned char CheckRead (CirclBuffer *Name ) { if (!CheckBit0(Name->Flag)) // Проверим флаг БУФЕР ПУСТ { // Если он сброшен то возвращаем результат 0xFF if (Name->Tail < Name->Head) // Если да то вычисляем и возвращаем результат Число свободных для записи байт return (Name->Head - Name->Tail); // Число непрочитанных байт else return (Name->Size-(Name->Tail - Name->Head)) ; //Если хвост впереди головы? //то вычисляем (по другой формуле) и возвращаем результат } else return 0x00; } //******************************************************* // Функция Проверки доступности буфера структуры CirclBuffer Name // на запись // структура Name передается в функциюв виде указател // Функция возвращает 0x00 признак того что буфер пуст // и 0xFF признак того что буфер содержит данные доступные // для записи // ** Пример использовани // IF (CheckWrite(&MyBuffer)) Write(&MyBuffer); // Если в буфере есть свободное место производим запись в циклический буфер. // (циклический буфер MyBuffer должен быть определен выше макросом // ConstrCirclBuffe ) //*********************************************** unsigned char CheckWrite (CirclBuffer *Name ) { if (!CheckBit1(Name->Flag)) // Проверим флаг БУФЕР ПУСТ { // Если он сброшен то проверяем хвост впереди головы? if (Name->Head < Name->Tail) // Если да то вычисляем и возвращаем результат Число свободных для записи байт return (Name->Tail - Name->Head); else return (Name->Size-(Name->Head - Name->Tail)); //Если голова впереди хвоста то вычисляем (по другой формуле) и возвращаем результат Число свободных для записи байт } else return 0x00; // возвращаем результат 0 признак того что буфер пуст } void InitBuffer(CirclBuffer *Name) { ClearBit1 (Name->Flag); // Флаг БУФЕР ПОЛОН сброшен SetBit0(Name->Flag); // Флаг БУФЕР ПУСТ установлен }