Operação
O tempo no display esta no formato MM:SS (minutos : segundos). A operação é bastante simples e utiliza os três botões do display:
- O primeiro botão é usado para parar e inciar a contagem. Se o valor no display for zero, será ativada a função de cronômetro, com o valor sendo incrementado a cada segundo (ao atingir 99:59 voltará a zero e continuará contando). Se o valor for diferente de zero ele será decrementado a cada segundo, parando quando atingir zero (modo timer).
- O segundo botão incrementa os segundos, quando o timer estiver parado. A contagem vai de 0 a 59.
- O terceiro botão incrementaros minutos, quando o timer estiver parado. A contragem vai de 0 a 99.
Código
O código aproveita o gerador de caracteres e a rotina de escrita anteriores, acrescentando o caracter "dois pontos":
// Matriz de Caracteres 5x7 // Contem os dígitos de 0 a 9 e dois pontos uint8_t digitos [11][7] PROGMEM = { { 0x0E, 0x11, 0x15, 0x15, 0x15, 0x11, 0x0E }, { 0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x1F }, { 0x0E, 0x11, 0x02, 0x04, 0x08, 0x10, 0x1F }, { 0x0E, 0x11, 0x01, 0x06, 0x01, 0x11, 0x0E }, { 0x11, 0x11, 0x11, 0x1F, 0x01, 0x01, 0x01 }, { 0x1F, 0x10, 0x10, 0x1E, 0x01, 0x11, 0x0E }, { 0x06, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x0E }, { 0x1F, 0x11, 0x01, 0x02, 0x04, 0x04, 0x04 }, { 0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E }, { 0x0E, 0x11, 0x11, 0x0F, 0x01, 0x02, 0x0C }, { 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00 } }; // Mostra o digito d a partir da posição x static void display (uint8_t x, uint8_t d) { uint8_t i, y, mask, gc; for (y = 0; y < 7; y++) { gc = pgm_read_byte(&(digitos[d][y])); mask = 0x10; for (i = 0; i < 5; i++) { ht1632c_setLED (x+i, y, gc & mask); mask = mask >> 1; } } }Um vetor guarda o valor atual do display e uma variável o modo atual de operação.
// Variaveis static volatile uint8_t tempo[5]; static volatile enum { PARADO, SUBINDO, DESCENDO } modo;O programa principal inicia as variáveis e o hardware.
// Programa principal int main(void) { uint8_t i; // Zera o relogio tempo[0] = 0; tempo[1] = 0; tempo[2] = 10; tempo[3] = 0; tempo[4] = 0; modo = PARADO; for (i = 0; i < 5; i++) display (6*i, tempo[i]); // Liga pullup das teclas TEC_DDR &= ~(TEC_KEY1|TEC_KEY2|TEC_KEY3); TEC_PORT |= TEC_KEY1|TEC_KEY2|TEC_KEY3; ht1632c_init(); // inicia o controlador do display ht1632c_send_screen (); // limpa o display tempo_init(); // inicia a contagem de tempo // Loop perpétuo - somente tratando a interrupção de timer for (;;) { } } // Inicia a contagem de tempo static void tempo_init (void) { ASSR |= (1<<AS2); // timer2 async from external quartz TCCR2 = 0b00000010; // normal,off,/8; 32768Hz/256/8 = 16 Hz TIMSK |= (1<<TOIE2); // enable timer2 overflow int sei(); // enable interrupts }A ação toda está na rotina de interrupção do timer.
// Interrupção do Timer2 ISR(TIMER2_OVF_vect) { static uint8_t cnt_seg = 16; static uint8_t teclas = TEC_KEY1|TEC_KEY2|TEC_KEY3; uint8_t mudou = FALSE; uint8_t i; if (--cnt_seg == 0) { cnt_seg = 16; // Atualiza a contagem if (modo == SUBINDO) { mudou = TRUE; if (++tempo[4] == 10) { tempo[4] = 0; if (++tempo[3] == 6) { tempo[3] = 0; if (++tempo[1] == 10) { tempo[1] = 0; if (++tempo[0] == 10) tempo[0] = 0; } } } } else if (modo == DESCENDO) { mudou = TRUE; if (tempo[4] == 0) { tempo[4] = 9; if (tempo[3] == 0) { tempo[3] = 5; if (tempo[1] == 0) { tempo[1] = 9; tempo[0]--; } else tempo[1]--; } else tempo[3]--; } else tempo[4]--; if ((tempo[0] + tempo[1] + tempo[3] + tempo[4]) == 0) modo = PARADO; } } // Trata as teclas if (((teclas & TEC_KEY1) == 0) && ((TEC_PIN & TEC_KEY1) != 0)) { // soltou tecla de modo if (modo == PARADO) { if ((tempo[0] + tempo[1] + tempo[3] + tempo[4]) == 0) modo = SUBINDO; else modo = DESCENDO; } else modo = PARADO; } if (modo == PARADO) { if (((teclas & TEC_KEY2) == 0) && ((TEC_PIN & TEC_KEY2) != 0)) { mudou = TRUE; if (++tempo[4] == 10) { tempo[4] = 0; if (++tempo[3] == 6) tempo[3] = 0; } } if (((teclas & TEC_KEY3) == 0) && ((TEC_PIN & TEC_KEY3) != 0)) { mudou = TRUE; if (++tempo[1] == 10) { tempo[1] = 0; if (++tempo[0] == 10) tempo[0] = 0; } } } teclas = TEC_PIN; if (mudou) { // Atualiza o display for (i = 0; i < 5; i++) display (6*i, tempo[i]); } }Uma sugestão de aperfeiçoamento é detectar o acionamento de dois botões e zerar o display nesta condição.
Outra melhoria possível é fazer o display piscar quando estiver no modo timer e a contagem chegar a zero. Pode-se também conectar um alto-falante ou buzzer para gerar um alarme sonoro.
O Timer em Funcionamento
O vídeo abaixo mostra o resultado obtido.
Nenhum comentário:
Postar um comentário