O principal objetivo do teclado é digitar. Mas também pode ser usado para escrever código no microcontrolador. O método não é convencional, mas pode ser útil quando não há mais nada à mão. Ou como entretenimento com um teclado que não é mais adequado para o trabalho normal. Abaixo está como fazê-lo.
Exemplo de circuito programador:

ScrollLock define o nível na entrada RESET, CapsLock - na entrada SCK, NumLock - na entrada MOSI. O LED (VD4) na saída MISO é usado para controlar a entrada no modo de programação. Os detalhes marcados com um asterisco (*) são opcionais.
Algoritmo de programação (para microcontroladores AT90 ou ATmega):
1) Defina 0 como SCK e MOSI (ative CapsLock e NumLock). O SCK deve estar em 0 antes que RESET vá para 0.
2) Defina 0 como RESET (ative o ScrollLock).
3) Forme, alterando o estado de SCK e MOSI (ScrollLock e NumLock), a sequência de transferência do controlador para o modo de programação.
4) Se o LED na saída MISO não acender, é necessário gerar um único pulso na linha SCK e repetir a sequência (ponto 3).
Se após 32 tentativas a transição para o modo de programação não ocorreu, parece que algo deu errado. Se for bem-sucedido, uma programação adicional será realizada via ScrollLock e NumLock (SCK e MOSI). Uma lança atenta e persistente pode programar o microcontrolador manualmente.
Por que isso não está funcionando?
O principal problema ao implementar esse programador é a própria lógica do teclado. Definir o status dos LEDs por um programa externo corresponde ao resultado no teclado, mas o processo de transição para ligar / desligar os LEDs é da sua conta. Abaixo estão os oscilogramas da comutação real:

Ativando o NumLock (CapsLock e ScrollLock incluído).

Desativando o ScrollLock (CapsLock e NumLock estão ativados).
Podemos dizer que nem todos os teclados são igualmente úteis para programar microcontroladores. Dos três que eu tinha, apenas um tinha os LEDs ligados de forma independente.
O que fazer se você é tão azarado com o teclado?
Todos os "transitórios" são empilhados no tempo em alguns microssegundos e um certo nível é definido como SCK, MOSI e RESET com um atraso de mais de 1 ms. Nesse caso, os sinais de programação podem ser extraídos usando um filtro passa-baixo. Aqui está um exemplo de filtro:

74HC14 - Schmitt trigger, destina-se à formação de níveis de saída. Pode ser substituído por um comparador analógico (por exemplo, LM2901). Nos microcontroladores, as entradas do AVR possuem um gatilho Schmitt interno, que permite contornar a cadeia RC se os níveis de saída 1 e 0 corresponderem aos necessários.
Como exemplo. Teclado que se tornou um programador:

→ Implementação suave do programador