[an error occurred while processing this directive]
|
Вначале дам три функции (файл event.c) для работы с событиями, чтобы проще было объяснять:
// ==================================================================
// Проверить наличие текущего события в очереди
// ------------------------------------------------------------------
// Вход: описатель текущего события
// Выход: 0/? - нет события(замаскировано)/описатель текущего события
// ==================================================================
unsigned char check_event(unsigned char handle) {
INTA_DISABLE();
handle = ((system.event.mask & handle) == handle) ?
handle & system.event.handle :
NUL;
INTA_ENABLE();
return handle;
}
// ==================================================================
// Поместить текущее событие в очередь
// ------------------------------------------------------------------
// Вход: описатель текущего события
// ==================================================================
void put_event(unsigned char handle) {
INTA_DISABLE();
if((system.event.mask & handle) == handle)
system.event.handle |= handle;
INTA_ENABLE();
}
// ==================================================================
// Обработчик событий
// ==================================================================
void handle_event(void) {
unsigned char mask = 0x01;
INTA_DISABLE();
while(system.event.handle) {
switch(system.event.handle & mask) {
case ID_TICK:
WDT_RST();
INIT_KEYB();
INT1_ENABLE(); // Клавиатура
break;
case ID_MEASURE:
case ID_MINUTE:
system.display.screen.draw = YES;
break;
case ID_BUTTON:
P0_7 = 0; // Включить подсветку
system.display.screen.draw = YES;
system.keyboard.button = NUL;
break;
}
system.event.handle &= ~mask;
mask <<= 1;
}
INTA_ENABLE();
}
-------------------------------------------------
1) В handle_event() универсальная обработка, то что кочует из одного проекта в другой практически без изменений, то что по if(check_event(...)) {...} уникально для каждого проекта, мне так удобнее.
2, 3) Генерация события ID_TICK, на него многое можно повесить, в текущем проекте один тик = 20мс, минимальный квант для измерительного цикла, я по нему дополнительно обрабатываю входной буфер (при приеме команды по последовательному порту). Универсальная обработка в handle_event().
4) Никакого стека, событие должно быть отработано за один тик. Иначе, есть потенцияльная опасность потерять событие. Но т.к. в моих проектах все важные события привязаны к 0.36с, что является достаточно большим временем, конфликтов не возникает. При удачном нажатии кнопки (не дребезг) прерывание от клавиатуры запрещается, разрешается после обработки в handle_event(). В удаленном доступе, для приема команды заведен таймаут (5 * 20мс), в случае не приема или частичного приема команды, буфер сбрасывается и ожидается снова команда. В случае успешного приема команды (пришло событие ID_RECEIVE) генерится событие ID_SEND, по которому идет разбор команды и отправка требуемого пакета (зависит от команды).
Нарезка из разных файлов для понимания того, что было выше.
---------------------------------
/* Маски событий */
enum EVENT { ID_TICK = 0x01,
ID_MEASURE = 0x02,
ID_MINUTE = 0x04,
ID_BUTTON = 0x08,
ID_RECEIVE = 0x10,
ID_SEND = 0x20,
ID_SPI_SEND = 0x40,
ID_ALL = ID_TICK | ID_MEASURE | ID_MINUTE | ID_BUTTON | ID_RECEIVE | ID_SEND | ID_SPI_SEND
};
typedef struct { unsigned char handle;
unsigned char mask;
} EVENT;
typedef struct { unsigned short ticks;
} RTCLOCK;
typedef struct { unsigned char button;
unsigned char previous;
} KEYBOARD;
typedef struct { unsigned char* line;
unsigned char draw;
} LINE;
typedef struct { unsigned char place;
unsigned char line;
unsigned char cursor;
LINE screen;
} DISPLAY;
typedef struct { EVENT event;
RTCLOCK rtclock;
KEYBOARD keyboard;
DISPLAY display;
} SYSTEM;
SYSTEM system;
------------------------------
Чуствую сумбурно объяснил, ну не писатель я :)
E-mail: info@telesys.ru