Вот это макросы! А не секрет, как эта магия работает?
COKPOWEHEU,Я где-то приводил ссылку откуда их взял.
Если вкратце, то весь код должен находится внутри макросов crBegin crFinish
макрос crReturn(1,0); позволяет выйти из функции с сохранением место выхода и после вызова функции ещё раз мы перейдём в сохранённое место.
Если смотреть на тот код который приводил выше то функция Process_scan_Key_FSM крутится в главном цикле с аналогичными функциями т.е 1 итерация главного цикла примерно 200-700 тактов
Спойлер
Код: Выделить всё
unsigned char Process_scan_Key_FSM(unsigned char *data){
unsigned char temp;
//----------
crBegin *data=0; // Вход
Set_but_OK // выставляем на мультиплексоре адрес кнопки ОК
crReturn(1,0); // Выходим из функции с сохранением точки выхода
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
// При следующем заходе в функцию переместимся суда
// при этом произойдёт задержка(на 1 проход главного цикла) на переключение мультиплексора.
Key_code2.OK=CTR_IN; // Считаем установившееся значение
Set_but_ESC // выставляем на мультиплексоре адрес кнопки ESC
crReturn(2,0); // Выходим из функции с сохранением точки выхода
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
Key_code2.ESC=CTR_IN;
Set_but_UP
crReturn(3,0);
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
Key_code2.UP=CTR_IN;
Set_but_DW
crReturn(4,0);
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
Key_code2.DW=CTR_IN;
//----------
crFinish
*data=1;
return Key_code2;
}
По переменной *data я смотрю когда произойти полный опрос всех кнопок тогда же можно и начинать работать с переменной Key_code2 (правда в данной реализации у меня сделано всё наоборот по хорошему через return надо смотреть о завершении работы функции а через data выдавать данные)
Если развернуть все макросы то получится обычный switch case
Спойлер
Код: Выделить всё
unsigned char Process_scan_Key_FSM(unsigned char *data){
unsigned char temp;
static int state=0;
switch(state) {
case 0: *data=0;
Set_but_OK // выставляем на мультиплексоре адрес кнопки ОК
state=1; //crReturn(1,0)
return 0; //crReturn(1,0)
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
case 1: //crReturn(1,0)
Key_code2.OK=CTR_IN; // Считаем установившееся значение
Set_but_ESC // выставляем на мультиплексоре адрес кнопки ESC
state=2; //crReturn(2,0)
return 0; //crReturn(2,0)
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
case 2: //crReturn(2,0)
Key_code2.ESC=CTR_IN;
Set_but_UP
state=3; //crReturn(3,0)
return 0; //crReturn(3,0)
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
case 3: //crReturn(3,0)
Key_code2.ESC=CTR_IN;
Set_but_UP
state=4;
return 0;
//>>>>>>>>Выход>>>>>>>>>>>>>>>>>>
//......case 4:
} //crFinish
//----------
*data=1;
return Key_code2;
}
Можно ещё заменить в макросе i на номер строки __LINE__ тогда можно вообще забыть про индексы case
Код: Выделить всё
#define crReturn(x) do { state=__LINE__; return x; case __LINE__:; } while (0)
Самое полезное что я нашёл если передавать в функцию структуру с state. То получается можно запустить одну и туже функцию на параллельную обработку разных данных.
Код: Выделить всё
#define ccrBegin(pt) switch((pt)->lc) { case 0:
#define ccrReturn(x) do { (pt)->lc=__LINE__; return x; case __LINE__:; } while (0)
#define ccrFinish } (pt)->lc=0;
Хотя такое можно сделать и без макросов