/* * Project: Single Button Timer for PIC12F508 using HI-TECH C * Compiler: HI-TECH C for PIC10/12/16 (v9.70 or similar) * Environment: MPLAB IDE v8.xx * MCU: PIC12F508 * Oscillator: Internal 4MHz */ #include <htc.h> // Configuration fuses are set using __CONFIG() macro in HI-TECH C. // __CONFIG(CPDIS & WDTDIS & IntRC & MCLRDIS); // Example config line // Define the pins using the header file's standard register names #define RELAY_PIN GP2 #define BUTTON_PIN GP3 #define LED_30MIN GP0 #define LED_45MIN GP1 #define LED_60MIN GP4 // Time definitions in minutes #define TIME_30M 30 #define TIME_45M 45 #define TIME_60M 60 // Global variables // Use 'volatile' for variables changed within a timing loop volatile unsigned char timer_options[] = {TIME_30M, TIME_45M, TIME_60M}; volatile unsigned char current_time_index = 0; volatile unsigned long time_remaining_seconds = 0; volatile unsigned char button_press_counter = 0; volatile unsigned char is_pressed = 0; volatile unsigned char timer0_tick_count = 0; volatile unsigned char timer_running = 0; void InitMCU(void) { // Configure I/O pins: GP3 input, others output TRIS = 0b00001000; // GP3 is input (1), others are outputs (0) // Set initial output states GPIO = 0x00; RELAY_PIN = 0; // OPTION register configuration for Timer0 polling: // T0CS=0 (internal clock Fosc/4) // PSA=0 (prescaler assigned to Timer0) // PS2:PS0 = 111 (1:256 prescaler) // GPPU=1 (Enable weak pull-ups on GPIO, assuming MCLRE is off) OPTION = 0b01000111; } // Function to update the indicator LEDs void UpdateLEDs(void) { LED_30MIN = 0; LED_45MIN = 0; LED_60MIN = 0; if (current_time_index == 0) LED_30MIN = 1; else if (current_time_index == 1) LED_45MIN = 1; else if (current_time_index == 2) LED_60MIN = 1; } // Main loop function to handle the timer overflow check void TimerService(void) { // Check if Timer0 overflowed (T0IF flag in INTCON register) if (INTCONbits.T0IF) { INTCONbits.T0IF = 0; // Clear the flag // TMR0 register does not need a full reload for this approach timer0_tick_count++; // We need about 61 overflows for 1 second (~16.4ms per tick) if (timer0_tick_count >= 61) { timer0_tick_count = 0; // 1 second has passed if (timer_running && time_remaining_seconds > 0) { time_remaining_seconds--; if (time_remaining_seconds == 0) { // Timer finished, turn off relay RELAY_PIN = 0; timer_running = 0; } } } } } // Function to handle button presses and state void ButtonService(void) { // Simple Debounce and Press Detection if (BUTTON_PIN == 0) { // Button is pressed (LOW) if (!is_pressed) { is_pressed = 1; button_press_counter = 0; // Start counting duration } else { // Count how long it's pressed (using the 16.4ms ticks) if (button_press_counter < 255) { button_press_counter++; } } } else { // Button is released (HIGH) if (is_pressed) { is_pressed = 0; // Determine if short or long press // Threshold for long press is roughly 1 second (approx 61 ticks) if (button_press_counter < 61) { // Handle Short Press: Start/Stop the timer if (!timer_running) { // Start time is minutes * 60 seconds time_remaining_seconds = (unsigned long)timer_options[current_time_index] * 60; RELAY_PIN = 1; // Turn relay ON timer_running = 1; } else { // Stop the timer if running time_remaining_seconds = 0; RELAY_PIN = 0; timer_running = 0; } } else { // Handle Long Press: Change the timer function if (!timer_running) { // Only change time if not running current_time_index++; if (current_time_index >= 3) { current_time_index = 0; } UpdateLEDs(); } } button_press_counter = 0; // Reset counter } } } void main(void) { InitMCU(); UpdateLEDs(); // Set the initial LED state (30 min) while (1) { TimerService(); ButtonService(); } }
Standard input is empty
/*
* Project: Single Button Timer for PIC12F508 using HI-TECH C
* Compiler: HI-TECH C for PIC10/12/16 (v9.70 or similar)
* Environment: MPLAB IDE v8.xx
* MCU: PIC12F508
* Oscillator: Internal 4MHz
*/
#include <htc.h>
// Configuration fuses are set using __CONFIG() macro in HI-TECH C.
// __CONFIG(CPDIS & WDTDIS & IntRC & MCLRDIS); // Example config line
// Define the pins using the header file's standard register names
#define RELAY_PIN GP2
#define BUTTON_PIN GP3
#define LED_30MIN GP0
#define LED_45MIN GP1
#define LED_60MIN GP4
// Time definitions in minutes
#define TIME_30M 30
#define TIME_45M 45
#define TIME_60M 60
// Global variables
// Use 'volatile' for variables changed within a timing loop
volatile unsigned char timer_options[] = {TIME_30M, TIME_45M, TIME_60M};
volatile unsigned char current_time_index = 0;
volatile unsigned long time_remaining_seconds = 0;
volatile unsigned char button_press_counter = 0;
volatile unsigned char is_pressed = 0;
volatile unsigned char timer0_tick_count = 0;
volatile unsigned char timer_running = 0;
void InitMCU(void) {
// Configure I/O pins: GP3 input, others output
TRIS = 0b00001000; // GP3 is input (1), others are outputs (0)
// Set initial output states
GPIO = 0x00;
RELAY_PIN = 0;
// OPTION register configuration for Timer0 polling:
// T0CS=0 (internal clock Fosc/4)
// PSA=0 (prescaler assigned to Timer0)
// PS2:PS0 = 111 (1:256 prescaler)
// GPPU=1 (Enable weak pull-ups on GPIO, assuming MCLRE is off)
OPTION = 0b01000111;
}
// Function to update the indicator LEDs
void UpdateLEDs(void) {
LED_30MIN = 0;
LED_45MIN = 0;
LED_60MIN = 0;
if (current_time_index == 0) LED_30MIN = 1;
else if (current_time_index == 1) LED_45MIN = 1;
else if (current_time_index == 2) LED_60MIN = 1;
}
// Main loop function to handle the timer overflow check
void TimerService(void) {
// Check if Timer0 overflowed (T0IF flag in INTCON register)
if (INTCONbits.T0IF) {
INTCONbits.T0IF = 0; // Clear the flag
// TMR0 register does not need a full reload for this approach
timer0_tick_count++;
// We need about 61 overflows for 1 second (~16.4ms per tick)
if (timer0_tick_count >= 61) {
timer0_tick_count = 0;
// 1 second has passed
if (timer_running && time_remaining_seconds > 0) {
time_remaining_seconds--;
if (time_remaining_seconds == 0) {
// Timer finished, turn off relay
RELAY_PIN = 0;
timer_running = 0;
}
}
}
}
}
// Function to handle button presses and state
void ButtonService(void) {
// Simple Debounce and Press Detection
if (BUTTON_PIN == 0) { // Button is pressed (LOW)
if (!is_pressed) {
is_pressed = 1;
button_press_counter = 0; // Start counting duration
} else {
// Count how long it's pressed (using the 16.4ms ticks)
if (button_press_counter < 255) {
button_press_counter++;
}
}
} else { // Button is released (HIGH)
if (is_pressed) {
is_pressed = 0;
// Determine if short or long press
// Threshold for long press is roughly 1 second (approx 61 ticks)
if (button_press_counter < 61) {
// Handle Short Press: Start/Stop the timer
if (!timer_running) {
// Start time is minutes * 60 seconds
time_remaining_seconds = (unsigned long)timer_options[current_time_index] * 60;
RELAY_PIN = 1; // Turn relay ON
timer_running = 1;
} else {
// Stop the timer if running
time_remaining_seconds = 0;
RELAY_PIN = 0;
timer_running = 0;
}
} else {
// Handle Long Press: Change the timer function
if (!timer_running) { // Only change time if not running
current_time_index++;
if (current_time_index >= 3) {
current_time_index = 0;
}
UpdateLEDs();
}
}
button_press_counter = 0; // Reset counter
}
}
}
void main(void) {
InitMCU();
UpdateLEDs(); // Set the initial LED state (30 min)
while (1) {
TimerService();
ButtonService();
}
}