Complete o código baseado no sistema cooperative multitasking abaixo de forma que os níveis lógicos nos pinos de I/O RD1, RD2, RD3, RD4 e RD5 sejam alternados a cada 200 \mathrm{~ms}, 600 \mathrm{~ms}, 300 \mathrm{~ms}, 300 \mathrm{~ms} e 150 ms respectivamente. (0,70 pontos)
Obs1: em cada tarefa só pode ser relacionado um pino de I/O.
Obs2: em cada intervalo de tempo (loop) só podem ser executadas no máximo 3 tarefas.
unsigned char slot=0; unsigned char cont =0;
void START_TIMER(void){
TMROH=0xFC;
TMROL =0 \times 2 \mathrm{~F};
INTCONbits.TMROIF=0;
}
void VERIFY_END_TIMER(void){
while(INTCONbits.TMROIF==0) {}
}
void TAREFA1(void){
cont++;
if (cont==4){
PORTDbits.RD1=!PORTDbits.RD1; cont=0;
}
}
void TAREFA2(void){
switch(slot){
case 0:
slot=1;
break;
}
void TAREFA3(void){
}
void TAREFA4(void){
}
VERIFY_END_TIMER();
}}
}

Passo 1

O enunciado pede que a gente complete um sistema simples de cooperative multitasking em C para um PIC, de forma que cinco pinos de PORTD sejam alternados (toggle) a cada 200 ms, 600 ms, 300 ms, 300 ms e 150 ms (respectivamente RD1, RD2, RD3, RD4 e RD5). O temporizador está ajustado para gerar um tick de 50 ms a cada estouro de TMR0 (com TMR0H=0xFC; TMR0L=0x2F). Em cada tarefa podemos usar apenas um pino e, em cada loop (cada intervalo de 50 ms) não podemos chamar mais de 3 tarefas. Vamos usar um slot que alterna entre dois estados, chamando 3 tarefas num slot=0 e 2 tarefas em slot=1. Cada tarefa terá o seu próprio contador (contX) e um limiar igual ao período desejado dividido por 50 ms.

Passo 2

Calcular quantos ticks de 50 ms são necessários para cada período:
  • 200 ms → 200/50 = 4 ticks
  • 600 ms → 600/50 = 12 ticks
  • 300 ms → 300/50 = 6 ticks
  • 300 ms → 300/50 = 6 ticks
  • 150 ms → 150/50 = 3 ticks

Passo 3

Declarar cinco contadores globais e implementar cada tarefa para incrementar o seu contador e, quando atingir o limiar, alternar o pino correspondente e zerar o contador.
unsigned char slot = 0;
unsigned char cont1 = 0, cont2 = 0, cont3 = 0, cont4 = 0, cont5 = 0;

void START_TIMER(void) {
    TMR0H = 0xFC;
    TMR0L = 0x2F;
    INTCONbits.TMR0IF = 0;
}

void VERIFY_END_TIMER(void) {
    while (INTCONbits.TMR0IF == 0) { }
}

void TAREFA1(void) {
    cont1++;
    if (cont1 == 4) {
        PORTDbits.RD1 = !PORTDbits.RD1;
        cont1 = 0;
    }
}

void TAREFA2(void) {
    cont2++;
    if (cont2 == 12) {
        PORTDbits.RD2 = !PORTDbits.RD2;
        cont2 = 0;
    }
}

void TAREFA3(void) {
    cont3++;
    if (cont3 == 6) {
        PORTDbits.RD3 = !PORTDbits.RD3;
        cont3 = 0;
    }
}

void TAREFA4(void) {
    cont4++;
    if (cont4 == 6) {
        PORTDbits.RD4 = !PORTDbits.RD4;
        cont4 = 0;
    }
}

void TAREFA5(void) {
    cont5++;
    if (cont5 == 3) {
        PORTDbits.RD5 = !PORTDbits.RD5;
        cont5 = 0;
    }
}

Passo 4

No main ou na rotina principal de loop fazemos:
  1. START_TIMER() para reiniciar TMR0;
  2. pelo switch(slot) chamamos até 3 tarefas;
  3. atualizamos slot para a próxima posição;
  4. esperamos VERIFY_END_TIMER() antes de repetir o ciclo.
void main(void) {
    // Configuração de PORTD como saída, configuração de TMR0 etc.
    TRISD = 0x00;
    // ... outras iniciais ...

    while (1) {
        START_TIMER();
        switch (slot) {
            case 0:
                TAREFA1();
                TAREFA2();
                TAREFA3();
                slot = 1;
                break;
            case 1:
                TAREFA4();
                TAREFA5();
                slot = 0;
                break;
        }
        VERIFY_END_TIMER();
    }
}

Resposta

O código completo acima implementa as cinco tarefas com contadores independentes, alternando somente até 3 tarefas por intervalo de 50 ms e garantindo os períodos de 200 ms, 600 ms, 300 ms, 300 ms e 150 ms em RD1, RD2, RD3, RD4 e RD5, respectivamente.

Exercícios relacionados