fork download
  1. /*
  2.  * Project: Single Button Timer for PIC12F508 using HI-TECH C
  3.  * Compiler: HI-TECH C for PIC10/12/16 (v9.70 or similar)
  4.  * Environment: MPLAB IDE v8.xx
  5.  * MCU: PIC12F508
  6.  * Oscillator: Internal 4MHz
  7.  */
  8.  
  9. #include <htc.h>
  10.  
  11. // Configuration fuses are set using __CONFIG() macro in HI-TECH C.
  12. // __CONFIG(CPDIS & WDTDIS & IntRC & MCLRDIS); // Example config line
  13.  
  14. // Define the pins using the header file's standard register names
  15. #define RELAY_PIN GP2
  16. #define BUTTON_PIN GP3
  17. #define LED_30MIN GP0
  18. #define LED_45MIN GP1
  19. #define LED_60MIN GP4
  20.  
  21. // Time definitions in minutes
  22. #define TIME_30M 30
  23. #define TIME_45M 45
  24. #define TIME_60M 60
  25.  
  26. // Global variables
  27. // Use 'volatile' for variables changed within a timing loop
  28. volatile unsigned char timer_options[] = {TIME_30M, TIME_45M, TIME_60M};
  29. volatile unsigned char current_time_index = 0;
  30. volatile unsigned long time_remaining_seconds = 0;
  31. volatile unsigned char button_press_counter = 0;
  32. volatile unsigned char is_pressed = 0;
  33. volatile unsigned char timer0_tick_count = 0;
  34. volatile unsigned char timer_running = 0;
  35.  
  36. void InitMCU(void) {
  37. // Configure I/O pins: GP3 input, others output
  38. TRIS = 0b00001000; // GP3 is input (1), others are outputs (0)
  39.  
  40. // Set initial output states
  41. GPIO = 0x00;
  42. RELAY_PIN = 0;
  43.  
  44. // OPTION register configuration for Timer0 polling:
  45. // T0CS=0 (internal clock Fosc/4)
  46. // PSA=0 (prescaler assigned to Timer0)
  47. // PS2:PS0 = 111 (1:256 prescaler)
  48. // GPPU=1 (Enable weak pull-ups on GPIO, assuming MCLRE is off)
  49. OPTION = 0b01000111;
  50. }
  51.  
  52. // Function to update the indicator LEDs
  53. void UpdateLEDs(void) {
  54. LED_30MIN = 0;
  55. LED_45MIN = 0;
  56. LED_60MIN = 0;
  57.  
  58. if (current_time_index == 0) LED_30MIN = 1;
  59. else if (current_time_index == 1) LED_45MIN = 1;
  60. else if (current_time_index == 2) LED_60MIN = 1;
  61. }
  62.  
  63. // Main loop function to handle the timer overflow check
  64. void TimerService(void) {
  65. // Check if Timer0 overflowed (T0IF flag in INTCON register)
  66. if (INTCONbits.T0IF) {
  67. INTCONbits.T0IF = 0; // Clear the flag
  68. // TMR0 register does not need a full reload for this approach
  69.  
  70. timer0_tick_count++;
  71.  
  72. // We need about 61 overflows for 1 second (~16.4ms per tick)
  73. if (timer0_tick_count >= 61) {
  74. timer0_tick_count = 0;
  75. // 1 second has passed
  76. if (timer_running && time_remaining_seconds > 0) {
  77. time_remaining_seconds--;
  78. if (time_remaining_seconds == 0) {
  79. // Timer finished, turn off relay
  80. RELAY_PIN = 0;
  81. timer_running = 0;
  82. }
  83. }
  84. }
  85. }
  86. }
  87.  
  88. // Function to handle button presses and state
  89. void ButtonService(void) {
  90. // Simple Debounce and Press Detection
  91. if (BUTTON_PIN == 0) { // Button is pressed (LOW)
  92. if (!is_pressed) {
  93. is_pressed = 1;
  94. button_press_counter = 0; // Start counting duration
  95. } else {
  96. // Count how long it's pressed (using the 16.4ms ticks)
  97. if (button_press_counter < 255) {
  98. button_press_counter++;
  99. }
  100. }
  101. } else { // Button is released (HIGH)
  102. if (is_pressed) {
  103. is_pressed = 0;
  104.  
  105. // Determine if short or long press
  106. // Threshold for long press is roughly 1 second (approx 61 ticks)
  107. if (button_press_counter < 61) {
  108. // Handle Short Press: Start/Stop the timer
  109. if (!timer_running) {
  110. // Start time is minutes * 60 seconds
  111. time_remaining_seconds = (unsigned long)timer_options[current_time_index] * 60;
  112. RELAY_PIN = 1; // Turn relay ON
  113. timer_running = 1;
  114. } else {
  115. // Stop the timer if running
  116. time_remaining_seconds = 0;
  117. RELAY_PIN = 0;
  118. timer_running = 0;
  119. }
  120. } else {
  121. // Handle Long Press: Change the timer function
  122. if (!timer_running) { // Only change time if not running
  123. current_time_index++;
  124. if (current_time_index >= 3) {
  125. current_time_index = 0;
  126. }
  127. UpdateLEDs();
  128. }
  129. }
  130. button_press_counter = 0; // Reset counter
  131. }
  132. }
  133. }
  134.  
  135. void main(void) {
  136. InitMCU();
  137. UpdateLEDs(); // Set the initial LED state (30 min)
  138.  
  139. while (1) {
  140. TimerService();
  141. ButtonService();
  142. }
  143. }
  144.  
Success #stdin #stdout 0.03s 25264KB
stdin
Standard input is empty
stdout
/*
 * 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();
    }
}