Olá Maurício, é verdade, estou usando interrupção em função da abordagem dada ao sistema operacional como um todo.
Gostei do ponto de partida que você publicou. Vou tentar fazer por aí, porque minhas funções ficaram meio que uma bosta

.
Na realidade utilizo um loop infinito que executa sempre um ciclo do tipo:
- Ler entradas (sensores, botões de comando e teclas da IHM)
- Processar variáveis (internas, equações de processo, etc.)
- Atualizar saídas (display, LEDs e buzzer)
As teclas estão ligadas a um buffer 74HC245 (do jeito convencional - chave ao GND e com pullup de 10K), e este ao Port-B do ATmega32, que utilizo como barramento de dados, pois tenho um monte de outras coisas conectadas a ele (essencialmente latches 74HC573, para display, LEDs, relés, etc.). É um circuito bastante grande, não é complexo, mas tem coisa prá chuchu.
Utilizo interrupção do Timer0 para contagem de tempo, do Timer1 para PWM, da Int0 para detecção de zero crossing, e também a UART está por interrupção.
Na realidade essas minhas teclas não estão diretamente numa interrupção do microcontrolador, mas num loop do sistema que volta e meia é interrompido. De início não fui muito específico para ir direto ao assunto, mas creio que devo ter criado uma certa confusão. De ser assim, por favor me disculpem. É que o fato é que não posso ficar preso num loop de tratamento da edição da variável, ou seja, devo verificar a tecla pressionada, atualizar a variável e o display e então cair fora até a próxima verificação.
Bem, de todas maneiras, e como citei lá no começo, uma das atribuições do meu loop infinito é chamar as rotinas de teclado, que fazem o debounce e atualizam os flags, pelo que posso utilizar uma lógica de if-else para saber qual tecla foi pressionada.
Então eu tenho o seguinte:
- Código: Selecionar todos
// -----------------------------------------------------------------------
// Tecla ENTER
// -----------------------------------------------------------------------
if (Ckey == K_ENTER) // Se ocorreu transição por tecla pressionada
{
FieldEdit(fieldbuf, 6, 1, 5, Ckey);
Ckey = K_NONE; // Aguarda nova transição por tecla
}
// -----------------------------------------------------------------------
// Tecla UP
// -----------------------------------------------------------------------
else if (Ckey == K_UP) // Se ocorreu transição por tecla pressionada
{
FieldEdit(fieldbuf, 6, 1, 5, Ckey);
Ckey = K_NONE; // Aguarda nova transição por tecla
}
// -----------------------------------------------------------------------
// Tecla DOWN
// -----------------------------------------------------------------------
else if (Ckey == K_DOWN) // Se ocorreu transição por tecla pressionada
{
FieldEdit(fieldbuf, 6, 1, 5, Ckey);
Ckey = K_NONE; // Aguarda nova transição por tecla
}
Por enquanto nem vou me preocupar com a tecla CANCEL, porque ela não irá fazer nada durante a edição.
Repare que a idéia inicial é a de fazer uma função genérica, que nem a que você postou como ponto de partida. A que eu estou tentando implementar (e que está feinha feinha) é essa que chamei de "FieldEdit", cujo protótipo é
- Código: Selecionar todos
void FieldEdit(char *fieldbuf, unsigned char fieldsize, unsigned char row, unsigned char col, unsigned char key);
onde "fieldbuf" foi definida como "char fieldbuf[8];" e é o buffer para impressão no LCD, o qual é feito via:
- Código: Selecionar todos
// Exibe o buffer
LCD_GotoXY(row,col); // Posiciona o cursor
LCD_PutStr(fieldbuf); // Imprime valor atual no LCD
//
finalmente "fieldsize" é a variável que utilizo para limitar a exibição e a edição (atualmente em 6 caracteres, portanto 6 dígitos).
Então minha função está assim (por favor não riam - hehehe)
- Código: Selecionar todos
extern unsigned char ind; // Índice para edição de dados
//
void FieldEdit(char *fieldbuf, unsigned char fieldsize, unsigned char row, unsigned char col, unsigned char key)
{
char rasc[3]; // Buffer de rascunho p/ conversão p/ ASCII
//
// Verifica de qual tecla se trata
//
if (key == K_UP) // Tecla UP
{
if (fieldbuf[ind] < '9') // Maior dígito é o 9
{
fieldbuf[ind]++; // Incrementa o dígito
}
}
else if (key == K_DOWN) // Tecla DOWN
{
if (fieldbuf[ind] > '0') // Menor dígito é o 0
{
fieldbuf[ind]--; // Decrementa o dígito
}
}
else if (key == K_ENTER) // Tecla ENTER
{
if (ind < fieldsize) // Se ainda há digitos a editar
{
ind++; // Avança para o próximo dígito da edição
}
else // Se o último dígito foi editado
{
// Converter aqui o buffer e guardar o valor na memória
}
}
//
// Exibe o buffer
LCD_GotoXY(row,col); // Posiciona o cursor
LCD_PutStr(fieldbuf); // Imprime valor atual no LCD
//
col = col + ind; // Atualiza para a coluna editada
//
LCD_GotoXY(row,col); // Posiciona o cursor sobre o dígito a editar
}
//
Falei que tava feia!!!
Vou tentar adaptar a sua Maurício, e se der certo depois eu posto, ok?
De todas maneiras, valeu pela força. Vamos em frente!
... e assim falou Zaratustra !