Untitled
unknown
c_cpp
3 years ago
5.6 kB
37
Indexable
/* * File: main.c * Author: David * * Created on 23 de marzo de 2022, 8:55 */ #include <xc.h> #define LED RA0 #define BTN RB0 #define OUTPUT LED /* Output is the LED */ #define enable_interrupts() INTCONbits.GIE = 1 /* Enable global interrupts */ #define disable_interrupts() INTCONbits.GIE = 0 /* Disable global interrupts */ /* Values in ms */ #define BTN_TIME 20 /* 20ms button debounce, set 0 to disable */ #define DELAY_TIME 10000 /* 10s delay */ #define UP_TIME 30000 /* 30s up time */ #define DOWN_TIME 30000 /* 30s down time */ /* Variables */ struct{ volatile unsigned int ms; // volatile because it's modified inside an interrupt volatile unsigned char button; unsigned char tmr; unsigned int out; unsigned int now; }count; union{ unsigned char data; struct{ unsigned enable:1; unsigned button:1; unsigned output:1; unsigned delay:1; }; } status; /* Functions */ void clearTimer(void){ disable_interrupts(); TMR2 = 0; // Clear Timer counter count.ms = 0; // Clear ms counter enable_interrupts(); count.now = 0; // Also clear now value } void readTimer(void){ disable_interrupts(); // Interrupts must be paused when handling timer0 counters count.now = count.ms; // Save counter status enable_interrupts(); } void saveTimer(void){ count.tmr = TMR2; // Save timer counter disable_interrupts(); count.out = count.ms; // Save ms counter enable_interrupts(); } void restoreTimer(void){ TMR2 = count.tmr; // Restore timer counter disable_interrupts(); count.ms = count.out; // Restore ms counter enable_interrupts(); count.now = count.ms; // Update now time } void initTimer(void){ // Default internal clock = 4MHz, (1 MIPS, CLKOUT=1MHz) PR2 = 249; // Period match = 249+1 = 250 T2CON = 0b101; // TMR2 on, pre=1:4, post=1:1 1MHZ/(4*250) = 1KHz PIE1bits.TMR2IE = 1; // Enable Timer2 interrupt clearTimer(); // Clear Timer counter PIR1bits.TMR2IF = 0; // Clear flag INTCON = 0b11000000; // GIE=1, PIE=1 (Enable global and peripheral interrupts) } /* ISR */ void __interrupt() Interrupt(void){ if (PIR1bits.TMR2IF) { PIR1bits.TMR2IF = 0; count.ms++; count.button++; RA1 = !RA1; // Toggle test signal (500Hz), just to detect it's working } } /* Main */ void main() { TRISA0=0; TRISB0=1; TRISB1=0; TRISA1=0; RA1=0; OUTPUT=0; status.output = 1; initTimer(); // Init and start Timer0 while(1) { /* Read Timer0 counter at the start of the loop */ readTimer(); /* Handle button update and debouncing */ if(status.button != BTN){ // If button changed from last stored state if(count.button >= BTN_TIME){ // If button debounce time elapsed status.button = BTN; // Update stored state and take action if(!status.button){ // Input low? if(!status.delay && status.enable){ // If not in delay and enabled saveTimer(); // Save timer status.enable = 0; // Disabled OUTPUT = 0; // Disable output } } else{ // Input high? clearTimer(); // Clear timer status.enable = 1; // Enabled status.delay = 1; // Enable delay } } } else{ // Button didn't change or bounced back to original position count.button = 0; // Clear button counter } // No need to stop interrupts because it's atomic /* If enabled, handle delay and output signal */ if(status.enable){ // Enabled? if(status.delay){ // Delay active? if(count.now >= DELAY_TIME) { // If counter >= delay time status.delay = 0; // Delay done, clear flag restoreTimer(); // Restore previous counter if(status.output){ // Restore output state OUTPUT = 1; } } } else{ // Running? if(status.output){ // If output high if(count.now >= UP_TIME) { // Check for elapsed uptime clearTimer(); OUTPUT = 0; status.output = 0; } } else{ // If output low if(count.now >= DOWN_TIME) { // Check for elapsed downtime clearTimer(); OUTPUT = 1; status.output = 1; } } } } } }
Editor is loading...