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