Вот, ещё примеры - задержка внутри цикла, моргушки с условием и без, обработка долгого кода с понижением его приоритета...
код постарался по максимуму снабдить комментариями.
Спойлер
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
// частота цикла в кГц
#define Speed_temp 0.1
//начинаем поток (имя потока)
#define StartPotok(pot) {static unsigned int pot##_EscapeIteration=1; \
static unsigned char pot##_StepOfPotok=0; \
if (pot##_EscapeIteration) {(pot##_EscapeIteration)--; \
if ((pot##_EscapeIteration)==0) { \
switch (pot##_StepOfPotok){case 0: (pot##_EscapeIteration)=0
//задержка в потоке (имя потока, номер задержки, длительность задержки-циклов)
#define Delay_n(pot,step,tim) pot##_StepOfPotok=step; pot##_EscapeIteration=(tim)+1; \
goto pot##_End; case(step): (pot##_EscapeIteration)=0
//задержка в потоке (имя потока, номер задержки, длительность задержки-мс)
#define Delay_t(x,step,tim) Delay_n(x,step,(tim)*(Speed_temp))
//заканчиваем поток (имя потока)
#define EndPotok_n(pot,tim) default: pot##_EscapeIteration=(tim)+1; pot##_StepOfPotok=0; pot##_End:};};};}
#define EndPotok_t(pot,tim) EndPotok_n(pot,(tim)*(Speed_temp))
#define EndPotok(pot) EndPotok_n(pot,0)
// Timer1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{PORTC.6=1; //diagnostic out
#asm("sei") //подобие вытесняющей многозадачности (без него - кооперативный)
/*в задачу, которую прервало прерывание мы не попадём,
т.к. пока она не отработает - вход в неё блокируется
поэтому в прерывании выполнятся остальные задачи,
прерывание завершится и выполнение приостановленной задачи возобновится*/
StartPotok(key_trigg); //// кнопка-триггер с антидребезгом
if(!PINC.2) //проверка
{
Delay_t(key_trigg,3,10); //задержка 10 ms (номера могут быть не по порядку, главное, чтоб не повторялись и были от 1 до 255)
if(!PINC.2) //повторная проверка
{
PINC.0=1; // переключение d9 (записью 1 в регистр PIN производится переключение 1->0 0->1 порта)
do {
Delay_t(key_trigg,1,0);
}while (!PINC.2);//ждём отпускания
};
}
EndPotok(key_trigg);
StartPotok(morgunchik); // моргунчик d10
if(PINC.0)
{
PORTC.1=1;
Delay_t(morgunchik,1,200);//delay_ms(200);
PORTC.1=0;
Delay_t(morgunchik,2,200);//delay_ms(200);
};
EndPotok(morgunchik);
StartPotok(morgD11); // моргунчик d11 - проверка что мк работает
PINC.3=1; //(моргает всегда, т.к. нет запрещающих моргание условий)
Delay_t(morgD11,1,190); //моргает чуть быстрее чем d10
EndPotok(morgD11);
//приоритет зависшей задачи понижается она продолжит выполняться но только в фоне
//если зависнет 2я задача - первая зависшая будет остановлена, пока не развиснет 2я
StartPotok(largeoperation); //долгая, возможно зависшая задача...
PORTC.4=1; //мигаем желтым светодиодом D13
delay_ms(300); //вот он - зависон (не знаю, какими вычислениями занять, поэтому просто делай)
PORTC.4=0;
Delay_t(largeoperation,1,300);//когда зависание пройдёт - приоритет задачи будет восстановлен
EndPotok(largeoperation); //окончание зависания определяется по достижению меток задержек или конца потока.
//не оформлять код в поток можно только при полной уверенности,
//что он успеет отработать за время между прерываниями и не зависнет!
//очень рекомендую так не делать, и оформить его в поток.
if (!PIND.0) {PORTB.0=1; PORTB.1=0; PORTB.2=0; PORTB.3=0;};
if (!PIND.1) {PORTB.1=1; PORTB.0=0; PORTB.2=0; PORTB.3=0;};
if (!PIND.2) {PORTB.2=1; PORTB.0=0; PORTB.1=0; PORTB.3=0;};
if (!PINC.5) {PORTB.5=1; PORTB.0=0; PORTB.1=0; PORTB.3=0;};
if (!PIND.3) {PORTB.3=1; PORTB.0=0; PORTB.1=0; PORTB.2=0;};
///////// 2-ая группа кнопок
if (!PIND.4) {PORTB.4=1; PORTB.5=0; PORTB.6=0; PORTB.7=0;};
if (!PIND.5) {PORTB.5=1; PORTB.6=0; PORTB.7=0; PORTB.4=0;};
if (!PIND.6) {PORTB.6=1; PORTB.4=0; PORTB.5=0; PORTB.7=0;};
if (!PIND.7) {PORTB.7=1; PORTB.4=0; PORTB.5=0; PORTB.6=0;};
}
void main(void)
{
PORTB = 0x00; PORTC = 0xFC; PORTD = 0xFF;
DDRB = 0xFF; DDRC = 0x5B; DDRD = 0x00;
//Timer/Counter 1: Interrupt Period = 10 ms
TCCR1A=(0<<COM1A0) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (2<<CS10);
TCNT1=0x0000;
OCR1A=0x270F;
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (1<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);
MCUCR=(1<<SE) | (0<<SM0); //sleep mode enable, mode idle
#asm("sei") // Global enable interrupts
while (1)
{
//тут записываются самые низкоприоритетные задачи... наприер сон...
PORTC.6=0; //diagnostic out D12
//на портС.6 (ресет) выведен сигнал загрузки МК когда АЛУ работает, там лог1, когда простаивает/спит - лог0
//#asm("sleep") //disabled for proteus
}
};
