Untitled
unknown
c_cpp
3 years ago
4.7 kB
14
Indexable
/* Defines */ #define LED PORTA.F0 #define BTN PORTB.F0 #define OUTPUT LED /* Output is the LED */ #define enable_interrupts() INTCON.GIE = 1 /* Enable global interrupts */ #define disable_interrupts() INTCON.GIE = 0 /* Disable global interrupts */ #define BTN_TIME (32/TIMESTEP) /* 32ms button debounce */ #define TMR0_PRELOAD 131 /* Timer 0 preload */ #define TIMESTEP 8 /* 8ms step */ #define DELAY_TIME (10000/TIMESTEP) /* 10s delay */ #define UP_TIME (30000/TIMESTEP) /* 30s up time */ #define DOWN_TIME (30000/TIMESTEP) /* 30s down time */ /* Variables */ struct{ volatile unsigned int timer0; // volatile because it's modified inside an interrupt volatile unsigned int button; unsigned int output; unsigned int now; }count; union{ unsigned char data; struct{ unsigned enable:1; unsigned button:1; unsigned output:1; unsigned delay:1; }; } status; /* Functions */ void clearTimer0(void){ disable_interrupts(); count.timer0 = 0; // Clear Timer0 counter enable_interrupts(); } void initTimer0(void){ // Default internal clock = 4MHz, (1 MIPS, CLKOUT=1MHz) OPTION_REG = 0x05; // TMR0 source = CLKOUT, 1:64, WDT = 1:32. Timer0 clock = 15625Hz INTCON = 0b10110000; // GIE=1, T0IE=1, RB0/INT=1 TMR0 = TMR0_PRELOAD; // 15625Hz / ((255-131)+1) = 125Hz = 8ms clearTimer0(); } void toggle_state(void){ clearTimer0(); if(status.output){ status.output = 0; // Clear state OUTPUT = 0; // Disable output } else{ status.output = 1; // Set state OUTPUT = 1; // Enable output } } /* ISR */ void Interrupt(void){ if (TMR0IF_bit) { TMR0 = TMR0_PRELOAD; TMR0IF_bit = 0; count.timer0++; count.button++; } } /* Main */ void main() { TRISA.F0=0; TRISB.F0=1; TRISB.F1=0; TRISA.F1=0; PORTA.F1=0; LED=0; InitTimer0(); // Init and start Timer0 while(1) { /* Read Timer0 counter at the start of the loop */ disable_interrupts(); // Interrupts must be paused when handling timer0 and button counters count.now = count.timer0; // Save counter status enable_interrupts(); /* 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){ // Stop state? count.out = count.now; // Save counter status into output counter variable status.enable = 0; // Disabled state OUTPUT = 0; // Disable output } else{ // Run state? clearTimer0(); // Clear timer status.enable = 1; // Enabled state status.delay = 1; // Enable delay } } } else{ // Button didn't change disable_interrupts(); count.button = 0; // Clear button counter enable_interrupts(); } /* If enabled, handle delay and output signal */ if(status.enable){ if(status.delay){ if(now >= DELAY_TIME { // If counter >= delay time status.delay = 0; // Delay done, clear flag disable_interrupts(); count.timer0 = count.out; // Restore counter status from output counter variable enable_interrupts(); if(status.output){ // Restore output state OUTPUT = 1; } } } else{ // Running if(status.output){ // If output high if(count.now >= UP_TIME) { // Check for elapsed up time toggle_state(); } } else{ // If output low if(count.now >= DOWN_TIME) { // Check for elapsed down time toggle_state(); } } } } } }
Editor is loading...