Reputation: 11
I was trying to finish my project using an physical OUSB-IO board on a ATmega32A board using Microchip Studio's C to create a stopwatch and timer on the same LED board to indicate that it's working. Every detail works from switching a timer to stopwatch and back, setting the timer up (besides 0 which is the major issue due to the fact I can't make it seconds and only minutes) and having a reset/stop button to stop the whole program.
Could anyone help me understand or show me why my 0 doesn't work on the keypad when every button works?
#define F_CPU 1000000UL // 1 MHz clock speed
#include <avr/io.h>
#include <util/delay.h>
// Define keypad and LED ports
#define KEYPAD_PORT PORTC
#define KEYPAD_DDR DDRC
#define KEYPAD_PIN PINC
#define LED_PORT PORTB
#define LED_DDR DDRB
// Stopwatch/Timer variables
uint8_t mode = 0; // 0 = stopwatch, 1 = timer
uint16_t time_left = 0; // Time remaining (timer) or elapsed (stopwatch)
uint8_t is_running = 0; // Running flag for the timer/stopwatch
uint8_t flash_leds = 0; // Flag to flash LEDs when timer ends
uint8_t digit_count = 0; // Track input digits
uint8_t input_digits[4]; // Store digits for MM:SS input
// Keypad initialization
void keypad_init() {
KEYPAD_DDR = 0xF0; // Upper 4 bits as output, lower 4 bits as input
KEYPAD_PORT = 0x0F; // Enable pull-up resistors for the lower 4 bits
}
// Scan the keypad and return the key pressed
char keypad_scan() {
const char keys[4][4] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
for (uint8_t row = 0; row < 4; row++) {
KEYPAD_PORT = ~(1 << (row + 4)); // Ground one row at a time
_delay_ms(5); // Debounce delay
for (uint8_t col = 0; col < 4; col++) {
if (!(KEYPAD_PIN & (1 << col))) { // Check if the key is pressed
_delay_ms(20); // Additional debounce delay
while (!(KEYPAD_PIN & (1 << col))); // Wait for key release
return keys[row][col]; // Return the pressed key
}
}
}
return 0xFF; // No key pressed
}
// Initialize LEDs
void led_init() {
LED_DDR = 0xFF; // Set all PORTB pins as outputs (for LEDs)
LED_PORT = 0x00; // Turn off all LEDs initially
}
// Display the time on the LEDs
void display_time(uint16_t time) {
uint8_t minutes = time / 60;
uint8_t seconds = time % 60;
LED_PORT = (minutes << 4) | (seconds & 0x0F); // Show minutes and seconds
}
// Convert MM:SS format into total seconds
uint16_t convert_mmss_to_seconds() {
uint8_t minutes = input_digits[0] * 10 + input_digits[1];
uint8_t seconds = input_digits[2] * 10 + input_digits[3];
return minutes * 60 + seconds; // Total time in seconds
}
// Flash all LEDs when the timer hits zero
void flash_all_leds() {
LED_PORT ^= 0xFF; // Toggle all LEDs
_delay_ms(500); // 500ms delay for flashing
}
// Main function
int main(void) {
led_init(); // Initialize LEDs
keypad_init(); // Initialize the keypad
while (1) {
char key = keypad_scan(); // Get the key input
if (key != 0xFF) { // If a key is pressed
// Handle only number inputs (including 0) for setting the time
if ((key >= '0' && key <= '9') && digit_count < 4) { // Treat '0' as input along with '1-9'
input_digits[digit_count++] = key - '0'; // Store the digit, including '0'
display_time(convert_mmss_to_seconds()); // Show entered time
}
// Switch between Timer and Stopwatch modes
if (key == '*') {
mode = !mode; // Toggle the mode
LED_PORT = (mode == 1) ? 0x01 : 0x02; // Indicate mode (Timer: LED 0, Stopwatch: LED 1)
}
// Start/Stop the timer or stopwatch
if (key == 'A') {
if (!is_running) {
if (mode == 1) {
time_left = convert_mmss_to_seconds(); // Set time_left for Timer mode
digit_count = 0; // Reset digit count
} else {
time_left = 0; // In Stopwatch mode, start from 0
}
}
is_running = !is_running; // Toggle running state
}
// Stop and reset Timer/Stopwatch
if (key == 'C') {
time_left = 0;
is_running = 0;
flash_leds = 0;
LED_PORT = 0x00; // Turn off all LEDs
digit_count = 0; // Reset digit count
}
}
// Timer/Stopwatch logic
if (is_running) {
_delay_ms(1000); // 1-second delay
if (mode == 1 && time_left > 0) { // Timer mode: countdown
time_left--;
} else if (mode == 0) { // Stopwatch mode: count up
time_left++;
}
display_time(time_left); // Update the time on the LEDs
// Check if timer has reached zero
if (mode == 1 && time_left == 0 && is_running) {
flash_leds = 1; // Start flashing LEDs when timer hits 0
is_running = 0; // Stop the timer
}
}
// Flash LEDs when the timer hits zero
if (flash_leds && mode == 1) {
flash_all_leds(); // Flash all LEDs when timer hits 0
}
}
}
I've tried isolating the 0 button and making it a function like A, * and #, but it doesn't work, I've tried making it a normal key_pad scan with 1-9, but it doesn't work. When i press 0 at first the button doesnt register so i would click on 1-9 to create the timer after i set the timer using 1-9, Button 0 would then only pause the timer and nothing else.
Upvotes: 1
Views: 80