#define F_CPU 16000000UL // 16MHz clock from the debug processor
#define BAUD 9600 // set the baud rate to 9600
#define BAUDRATE ((F_CPU/(16UL*BAUD)) - 1) // calculate the baudrate
#include <avr/io.h> // library to be able to use the functions
#include <util/delay.h> // time delay library
#include <string.h> // include string library
char Keyboard[4][4] = { {'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
void USART_initialize() {
// clear the high bits because they are not needed for this lab. Don't need that many bits
UBRR0H = (BAUDRATE>>8);
UBRR0L = BAUDRATE; // set the Low byte register to the BAUDRATE
UCSR0B |= (1<<TXEN0); // enable the receiver and transmitter
UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01); // set to 8 bit data format
// don't need to set the stop bit since it is 1 by default
}
void Transmit(char strChar) {
// Wait for empty transmit buffer (isolates the 5th bit)
while ( !( UCSR0A & (1<<5) ) ) {}
UDR0 = strChar; // transmit the character
}
char initialize_Rows_and_Columns() {
for (int i = 0; i < 4; i++){ // iterate though PB0 - PB4
DDRB &= ~(1 << i); // sets columns as input
PORTB |= (1 << i); // set the columns as the pull up
}
for (int i = 4; i < 8; i++) { // iterate though PD4 - PD7
DDRD |= (1 << i); // sets rows output
PORTD |= (1 << i); // set the rows as high (default)
}
}
char keyboard_scan() {
for (int i = 4; i < 8; i++){
PORTD &= ~(1 << i); // set the rows low one at a time and then check each column:
for (int j = 0; j < 4; j++) { // iterate through each column
if ((PINB & (1 << j)) == 0) { // check which column is pulled low
// transmit the pressed key character to the screen
Transmit(Keyboard[i-4][j]);
// busy while, waiting for another key press to leave the if condition
while ((PINB & (1 << j)) == 0);
}}
PORTD |= (1 << i);
}}
int main(void){
USART_initialize();
initialize_Rows_and_Columns();
while (1) {
keyboard_scan(); // constantly check if a key has been pressed
}
}
A 2D array “ Keyboard[4][4] ” is initialized representing the layout of the physical 4x4 keypad where each each element corresponds to a specific key. The program uses USART registers: UCSR0A, UCSR0B, UCSR0C, UBRR0H, UBRR0L. UCSR0A is used to check for the transmit buffer's status: busy or empty. UDR0 is used to transmit data over to USART. When a key is pressed, its corresponding character is sent through this register. UCSR0B is used to enable or disable the receiver and transmitter; in this case, the transmitter was enabled by setting TXEN to 1. UCSR0C is used to configure the 8-bit data format by using UCSZ00 and UCZ01. UBRR0H and UBRR0L are used to set the baud rate for the high and low bits of UBRR0 - the USART baud rate register. In addition to registers, variables are also utilized in the code. Other variables such as F_CPU, BAUD, and BAUDRATE are also used in the program. While F_CPU defines the CPU clock frequency, BAUD specifies the baud rate for the USART communications. Lastly, BAUDRATE stores the calculated value in UBRR0. Port registers were also utilized in this code. DDRB and DDRD are used to set the pins in Port B and Port D to input and output, respectively. PORTB is used to enable the pull-up registers for the columns. PORTD is used to set the rows to high or low during the keyboard scanning function. The program is composed of four functions excluding ‘main’. The USART_initialize() function is used to configure the USART settings based on the baud rate formula. The initialize_Rows_and_Columns() function is used to initialize the data direction and pull-up register settings for the rows and columns. The Transmit(char strChar) function checks to see if the buffer is busy or empty, sending over the character if the buffer is empty. This iterative_scan() function scans the defined matrix to detect which key is pressed and transmits the corresponding character. Lastly, the main() calls both initializing functions and repeatedly scans to see if a key has been pressed.
The FT232R Breakout board and the Atmel Xplained Mini board were utilized. Pin PD1 on the Atmel board was connected to the TXD pin on the FT232R board using a wire to set up the transmission. The grounds of both boards were also connected. Lastly, the keypad was connected to the AVR microcontroller. Pins PD3-PD7 were used to represent the rows and PB0-PB3 were used to represent the columns of the keypad.