fork download
  1. // PIC16F877A Countdown Timer - Base Template (XC8 - MPLAB X)
  2. // Includes: Timer0 for millis, display multiplexing, LED, buzzer, buttons
  3.  
  4. #include <xc.h>
  5. #include <stdint.h>
  6.  
  7. // CONFIG
  8. #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
  9. #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
  10. #pragma config PWRTE = ON // Power-up Timer Enable bit (enabled)
  11. #pragma config BOREN = ON // Brown-out Reset Enable bit (enabled)
  12. #pragma config LVP = OFF // Low-Voltage (single-supply) In-Circuit Serial Programming Enable bit
  13. #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (disabled)
  14. #pragma config WRT = OFF // Flash Program Memory Write Enable bits (disabled)
  15. #pragma config CP = OFF // Flash Program Memory Code Protection bit (disabled)
  16.  
  17. #define _XTAL_FREQ 20000000 // 20 MHz crystal
  18.  
  19. // Pin definitions (adjust as needed)
  20. #define SEGMENTS_PORT LATD
  21. #define SEGMENTS_TRIS TRISD
  22. #define DIGIT1 LATCbits.LATC0
  23. #define DIGIT2 LATCbits.LATC1
  24. #define DIGIT3 LATCbits.LATC2
  25. #define LED LATCbits.LATC3
  26. #define BUZZER LATCbits.LATC4
  27.  
  28. #define BT_START PORTBbits.RB0
  29. #define BT_UP PORTBbits.RB1
  30. #define BT_DOWN PORTBbits.RB2
  31.  
  32. // Variables
  33. volatile unsigned long millis_counter = 0;
  34. unsigned int countdown = 120; // default countdown in seconds
  35. uint8_t digits[3];
  36.  
  37. // 7-segment digit patterns (common cathode)
  38. const uint8_t numbers[10] = {
  39. 0b00111111, // 0
  40. 0b00000110, // 1
  41. 0b01011011, // 2
  42. 0b01001111, // 3
  43. 0b01100110, // 4
  44. 0b01101101, // 5
  45. 0b01111101, // 6
  46. 0b00000111, // 7
  47. 0b01111111, // 8
  48. 0b01101111 // 9
  49. };
  50.  
  51. // Interrupt for Timer0 (1ms)
  52. void __interrupt() isr(void) {
  53. if (TMR0IF) {
  54. TMR0IF = 0;
  55. TMR0 = 6; // preload for 1ms (with 1:256 prescaler)
  56. millis_counter++;
  57. }
  58. }
  59.  
  60. unsigned long millis() {
  61. return millis_counter;
  62. }
  63.  
  64. void setup_timer0() {
  65. OPTION_REG = 0b00000111; // prescaler 1:256, assigned to TMR0
  66. TMR0 = 6;
  67. TMR0IE = 1;
  68. TMR0IF = 0;
  69. PEIE = 1;
  70. GIE = 1;
  71. }
  72.  
  73. void display_number(uint16_t number) {
  74. digits[0] = number / 100;
  75. digits[1] = (number / 10) % 10;
  76. digits[2] = number % 10;
  77. }
  78.  
  79. void update_display() {
  80. static uint8_t index = 0;
  81.  
  82. DIGIT1 = 0;
  83. DIGIT2 = 0;
  84. DIGIT3 = 0;
  85.  
  86. SEGMENTS_PORT = numbers[digits[index]];
  87.  
  88. if (index == 0) DIGIT1 = 1;
  89. else if (index == 1) DIGIT2 = 1;
  90. else if (index == 2) DIGIT3 = 1;
  91.  
  92. index = (index + 1) % 3;
  93. }
  94.  
  95. void beep(uint8_t times) {
  96. for (uint8_t i = 0; i < times; i++) {
  97. BUZZER = 1;
  98. __delay_ms(100);
  99. BUZZER = 0;
  100. __delay_ms(100);
  101. }
  102. }
  103.  
  104. void main(void) {
  105. // Setup
  106. SEGMENTS_TRIS = 0x00;
  107. TRISC = 0x00;
  108. TRISB = 0xFF; // Buttons as input
  109. PORTB = 0xFF; // Enable pull-ups if needed
  110.  
  111. setup_timer0();
  112.  
  113. unsigned long prev_time = 0;
  114. uint8_t running = 0;
  115.  
  116. while (1) {
  117. update_display();
  118. display_number(countdown);
  119.  
  120. if (!BT_START) {
  121. __delay_ms(50);
  122. if (!BT_START) running = !running;
  123. while (!BT_START);
  124. }
  125.  
  126. if (!BT_UP && !running && countdown < 999) {
  127. __delay_ms(50);
  128. if (!BT_UP) countdown++;
  129. while (!BT_UP);
  130. }
  131.  
  132. if (!BT_DOWN && !running && countdown > 0) {
  133. __delay_ms(50);
  134. if (!BT_DOWN) countdown--;
  135. while (!BT_DOWN);
  136. }
  137.  
  138. if (running && millis() - prev_time >= 1000) {
  139. prev_time = millis();
  140. if (countdown > 0) countdown--;
  141. if (countdown == 0) {
  142. running = 0;
  143. beep(3);
  144. }
  145. }
  146.  
  147. __delay_ms(5); // Small delay for multiplexing stability
  148. }
  149. }
  150.  
Success #stdin #stdout 0.03s 25924KB
stdin
Standard input is empty
stdout
// PIC16F877A Countdown Timer - Base Template (XC8 - MPLAB X)
// Includes: Timer0 for millis, display multiplexing, LED, buzzer, buttons

#include <xc.h>
#include <stdint.h>

// CONFIG
#pragma config FOSC = HS     // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF    // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON    // Power-up Timer Enable bit (enabled)
#pragma config BOREN = ON    // Brown-out Reset Enable bit (enabled)
#pragma config LVP = OFF     // Low-Voltage (single-supply) In-Circuit Serial Programming Enable bit
#pragma config CPD = OFF     // Data EEPROM Memory Code Protection bit (disabled)
#pragma config WRT = OFF     // Flash Program Memory Write Enable bits (disabled)
#pragma config CP = OFF      // Flash Program Memory Code Protection bit (disabled)

#define _XTAL_FREQ 20000000  // 20 MHz crystal

// Pin definitions (adjust as needed)
#define SEGMENTS_PORT LATD
#define SEGMENTS_TRIS TRISD
#define DIGIT1 LATCbits.LATC0
#define DIGIT2 LATCbits.LATC1
#define DIGIT3 LATCbits.LATC2
#define LED     LATCbits.LATC3
#define BUZZER  LATCbits.LATC4

#define BT_START PORTBbits.RB0
#define BT_UP    PORTBbits.RB1
#define BT_DOWN  PORTBbits.RB2

// Variables
volatile unsigned long millis_counter = 0;
unsigned int countdown = 120; // default countdown in seconds
uint8_t digits[3];

// 7-segment digit patterns (common cathode)
const uint8_t numbers[10] = {
    0b00111111, // 0
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111  // 9
};

// Interrupt for Timer0 (1ms)
void __interrupt() isr(void) {
    if (TMR0IF) {
        TMR0IF = 0;
        TMR0 = 6; // preload for 1ms (with 1:256 prescaler)
        millis_counter++;
    }
}

unsigned long millis() {
    return millis_counter;
}

void setup_timer0() {
    OPTION_REG = 0b00000111; // prescaler 1:256, assigned to TMR0
    TMR0 = 6;
    TMR0IE = 1;
    TMR0IF = 0;
    PEIE = 1;
    GIE = 1;
}

void display_number(uint16_t number) {
    digits[0] = number / 100;
    digits[1] = (number / 10) % 10;
    digits[2] = number % 10;
}

void update_display() {
    static uint8_t index = 0;

    DIGIT1 = 0;
    DIGIT2 = 0;
    DIGIT3 = 0;

    SEGMENTS_PORT = numbers[digits[index]];

    if (index == 0) DIGIT1 = 1;
    else if (index == 1) DIGIT2 = 1;
    else if (index == 2) DIGIT3 = 1;

    index = (index + 1) % 3;
}

void beep(uint8_t times) {
    for (uint8_t i = 0; i < times; i++) {
        BUZZER = 1;
        __delay_ms(100);
        BUZZER = 0;
        __delay_ms(100);
    }
}

void main(void) {
    // Setup
    SEGMENTS_TRIS = 0x00;
    TRISC = 0x00;
    TRISB = 0xFF; // Buttons as input
    PORTB = 0xFF; // Enable pull-ups if needed

    setup_timer0();

    unsigned long prev_time = 0;
    uint8_t running = 0;

    while (1) {
        update_display();
        display_number(countdown);

        if (!BT_START) {
            __delay_ms(50);
            if (!BT_START) running = !running;
            while (!BT_START);
        }

        if (!BT_UP && !running && countdown < 999) {
            __delay_ms(50);
            if (!BT_UP) countdown++;
            while (!BT_UP);
        }

        if (!BT_DOWN && !running && countdown > 0) {
            __delay_ms(50);
            if (!BT_DOWN) countdown--;
            while (!BT_DOWN);
        }

        if (running && millis() - prev_time >= 1000) {
            prev_time = millis();
            if (countdown > 0) countdown--;
            if (countdown == 0) {
                running = 0;
                beep(3);
            }
        }

        __delay_ms(5); // Small delay for multiplexing stability
    }
}