Si observamos el esquemático del AVR-MT, veremos que los botones se encuentran conectados a los pines PB5, PB6 y PB7. Para detectar si es que un botón ha sido pulsado, se debe poner uno de los tres pines en 1, para luego preguntar en los otros dos pines si es que su valor es 1 (previa configuración de los puertos).

Si se quiere verificar si el botón 4 esta siendo pulsado, entonces se deberá poner en 1 el bit correspondiente al pin PB6 (configurándolo como un pin de salida), y preguntar si es que el pin PB5 (configurado como un pin de entrada) es 1. Si en estas condiciones el pin PB5 reporta un valor 1, entonces el botón está siendo pulsado.

Por lo tanto, el código para esa verificación, sería,

//ConfigurarparaquePB6seasalida DDRB |= 1 << DDB6; //ConfigurarparaquePB5yPB7seanentradas DDRB &= ~(1 << DDB5 | 1 << DDB7); PORTB &= ~(1 << PB5 | 1 << PB7); //Enviarun1enPB6 PORTB |= 1 << PB6; for(;;) { //VerificarsiB4estásiendopresionado if(PINB & (1 << PB5)) { if('A' + i > 'Z') { usart_transmit('\n'); usart_transmit('\r'); i = 0; } usart_transmit('A' + i); ++i; } } 

Se debe tener especial cuidado al trabajar con los puertos de entrada y salida, pues el registro de datos es PORTB, pero los pines se deben leer desde PINB.

Una vez que tenemos el código para detectar si esq ue un botón está siendo presionado, entonces podemos ampliar el ejemplo y hacer que detecte si alguno de los 6 botones del AVR-MT ha sido presionado.

Una buena idea para completar el ejemplo es hacer que el microcontrolador mande a través del puerto serial, el botón que está siendo pulsado. Si un botón ya fue pulsado en un ciclo, el resto de los botones se ignora en ese ciclo. Veamos el código,

int main(void) { //Acaguardaremoselnumerodelboton //queseestepresionando volatile unsigned char boton; //9600baudiosconcristalde10MHz usart_init(64); //Revisarbotones for(;;) { //Noseestápresionando //botonalguno boton = 0; //ConfigurarparaquePB5seasalida DDRB |= 1 << DDB5; //ConfigurarparaquePB6yPB7seanentradas DDRB &= ~(1 << DDB6 | 1 << DDB7); PORTB &= ~(1 << PB6 | 1 << PB7); //Enviarun1enPB5 PORTB |= 1 << PB5; //DartiempoaPINB //parapoderleercorrectamente asm volatile("nop"); //Leerbotones if(PINB & (1 << PB6)) boton = 1; else if(PINB & (1 << PB7)) boton = 6; //Siesquenosehapulsadounboton if(!boton) { //ConfigurarparaquePB6seasalida DDRB |= 1 << DDB6; //ConfigurarparaquePB5yPB7seanentradas DDRB &= ~(1 << DDB5 | 1 << DDB7); PORTB &= ~(1 << PB5 | 1 << PB7); //Enviarun1enPB6 PORTB |= 1 << PB6; //DartiempoaPINB //parapoderleercorrectamente asm volatile("nop"); //Leerbotones if(PINB & (1 << PB5)) boton = 4; else if(PINB & (1 << PB7)) boton = 2; } //Siesquenosehapulsadounboton if(!boton) { //_delay_ms(100); DDRB |= 1 << DDB7; DDRB &= ~(1 << DDB5 | 1 << DDB6); PORTB &= ~(1 << PB5 | 1 << PB6); PORTB |= 1 << PB7; //DartiempoaPINB //parapoderleercorrectamente asm volatile("nop"); //Leerbotones if(PINB & (1 << PB5)) boton = 3; else if(PINB & (1 << PB6)) boton = 5; } //Enviarporelpuertoserial //unmensajeconelnumero //delbotonpulsado if(boton) { usart_transmit('B'); usart_transmit('o'); usart_transmit('t'); usart_transmit('o'); usart_transmit('n'); usart_transmit(''); usart_transmit('0' + boton); usart_transmit('\n'); usart_transmit('\r'); } } } 

Dado que el código anterior se ejecuta muchísimas veces por segundo, cuando presionemos un botón, lo más probable es que se envíe varias veces el mensaje con el número del botón, por lo que no hay que alarmarse si lo anterior ocurre, ya que es el funcionamiento normal del programa.

El código completo de este ejemplo se encuentra en el archivo Botones.c.