Кто бы еще толково описал подобное построение программ с помощью таймеров.
А то я тут читал у Ди-Халта про это, но там одно по одному и путано, в итоге он как-то сразу переходит на диспетчер задач и РТОС.
Надо бы, чтобы понятно было расписано, как использовать таймер, какие промежутки считать, как использовать и на пальцах. ))))))
А что там подробно описывать? Берем задачу, разбиваем ее на этапы и выполняем каждый этап за проход. Вот, скажем, мне как-то нужно было читать тачскрин. Порядок действий представлял себе слегка туманно. В качестве примера нашел такой вот код:
Код: Выделить всё
void TouchScan (void) {
push = 0;
DDRA = 0b10100000; // X_minus, X_plus на выход, сажаем Х пленку на землю
PORTA = 0b01011111; // остальные выводы как входы с подтяжкой
delay_ms(1);
if (read_adc(6) < 100) { // если есть нажатие ( проверяем на 0 вывод Y- )
push = 1;
press_count++;
if (press_count > 1) {
press = 1;
}
PORTA = 0b01111111; // cчитываем X координату, X_minus на землю, X_plus на +5 вольт
delay_ms(1);
x = abs((int) (232 - 0.276*read_adc(4)));
// записываем значения АЦП по 2-м точкам
// сопоставляем координаты
// и через уравнение прямой по 2-м точкам находим промежуточные значения нажатия
// x = 232 - 0.276*ADC
// y = 0.25*ADC - 67.5
DDRA = 0b01011111; // cчитываем Y координату, Y_minus, Y_plus на выход
PORTA = 0b10111111; // Y_minus на землю, Y_plus на +5 вольт
delay_ms(1);
y = abs((int) (0.25*read_adc(5)-67.5));
}
else {
press = 0;
press_count = 0;
}
}
После опытов в железе стало очевидно, что в быстрой многозадачной программе с отзывчивым интерфейсом подобное использовать нельзя, код был переписан и принял такой вид:
Код: Выделить всё
void touchRead(void)
{
// This func is to be fired each ~1ms
// if TFT shared pins used for polling,
// any usual display operations are to be disabled till 'busy' flag clears
push = 0;
static bool c; // keeping state
unsigned static char stage;
switch(stage)
{
case 1:
busy = 1; c = 0; coords = 0;
TOUCHPIN_D = (TOUCHPIN_D & ~YP) | XM;
TOUCHPORT_D = (TOUCHPORT_D & ~XM) | YP;
TOUCHPIN_A = (TOUCHPIN_A & ~YM) | XP;
TOUCHPORT_A = (TOUCHPORT_A & ~XP) | YM;
break;
case 2:
if(read_adc(CH0) < 100)
{
c = 1; push = 1;
if (++touchcount > 1) { keypress = 1; }
TOUCHPIN_D = (TOUCHPIN_D & ~YP) | XM;
TOUCHPORT_D = (TOUCHPORT_D & ~XM) | YP;
TOUCHPIN_A = (TOUCHPIN_A & ~YM) | XP;
TOUCHPORT_A |= XP | YM;
} else { busy = 0; touchRestore(); }
break;
case 3:
if(c) {
coords = (long)read_adc(CH0) << 16;
TOUCHPIN_D = (TOUCHPIN_D & ~XM) | YP;
TOUCHPORT_D |= YP | XM;
TOUCHPIN_A = (TOUCHPIN_A & ~XP) | YM;
TOUCHPORT_A = (TOUCHPORT_A & ~YM) | XP;
}
break;
case 4:
if(c)
coords |= read_adc(CH1);
else {
c = 0;
keypress = 0;
touchcount = 0;
}
busy = 0; touchRestore();
break;
} // end switch
if(++stage > TOUCH_INTERVAL) { stage = 0; } // do nothing for next n iterations
}
И вот теперь у нас простенький цветной ардуиновский экранчик уже успевает и опрашивать тач, и передавать дату по тем же пинам без ощутимой для юзера задержки.