Här är koden iaf. Någon som orkar kika igenom och kanske kan hjälpa mig att ändra den så att pinne 17 går hög i 5-10 sekunder, när tiden är slut???
Kan isf betala för jobbet eller något annat som önskas....
Kod: Markera allt
// -----------------------------------------------------------------------
//
// Timer - Timer switch with 1 hour lamp-on-period.
// Designed for UV-lamp for photographic PCB exposure and darkroom
//
// Functional Specifications:
// - rotary encoder to select the lamp-on-period
// - button/switch to start timer function
// - 4-digit display of lamp-on-period, counting down after start
//
// -----------------------------------------------------------------------
// Summary of changes
// 1.0.7 - Uses structure for time and special update routines.
// 1.1.0 - Time maintained in binary form (in seconds), was in stucture.
// 1.1.1 - No more use of interrupt-on-change facility.
// - FOSC set to 1 MHz (was 4 MHz) for somewhat better handling of
// fast rotations of rotary encoder.
// - LED and MOC3041 now controlled by different PIC pins.
// 1.1.2 - Modified time selection algorith: more exponential.
// -----------------------------------------------------------------------
//
// Implementation notes:
//
// - DISPLAY:
// A 4 digit 7-segment display shows the time in mm:ss format.
// The 7-segment displays are multiplexed: 1 digit is on at a time.
// Multiplexing frequency 220 Hz (refresh cycle 1/55 second).
// The multiplexing is done by the interrupt routine. At every
// interrupt the next digit will be displayed. The segment patterns are
// provided by the mainline.
// When the specific PIC has a CCP module the CCP ('special event') will
// be used, otherwise Timer1 interrupt will be used for the
// multiplexing functionality.
//
// - TIME:
// Controlled via internal oscillator and Timer1.
// The timer interrupt routine sets a 'one-second' flag. The flag is
// reset by the mainline which provides the display patterns for the
// display of the new time (when the timer is in 'ON'-state).
// Time variables are stored as 4 decimal values in a structure 'mmss'
// and maintained via special functions. This prevents binary to decimal
// conversions.
//
// - SWITCHES:
// State changes of input signals are detected by a 'change-on-input'
// interrupt. The mainline decides about the appropriate action.
// All input pins are on PORTA and are debounced in the mainline.
//
// - Control of the lamp-on-period:
// Selecting the lamp-on-period is performed by a rotary encoder.
// At very first power-on the default period is 02:30, but the last
// actually used period will be remembered and become the new default
// value (stored in EEPROM at the start of the lamp-on-period).
// To reach the desired on-period quickly turning the rotary encoder
// clockwise increases the lamp-on-period, turning it counter clockwise
// decreases it. The amount varies with the current value, as follows:
// 00:00 - 01:00 1 second
// 01:00 - 02:00 2 seconds
// 02:00 - 05:00 5 seconds
// 05:00 - 10:00 10 seconds
// 10:00 - 20:00 20 seconds
// 20:00 - 60:00 30 seconds
// The timer has a maximum lamp-on-period of 1 hour, time setting wraps
// around in both directions. When set to 00:00 the timer is inactive,
// and the lamp will not switch off automatically, only manually.
// When the lamp is on it is not possible to change the lamp-on-period.
//
// - Assignments of Ports, Oscillators, Timers, and other PIC features.
// PortA is assigned to switch and rotary encoder input, except for
// pin 2, which controls the lamp.
// PortB (4 pins) is dedicated to display digit selection (multiplexed).
// PortC (8 pins) is dedicated to display segment pattern selection.
// Internal oscillator set to 1 MHz
// Timer0 not used
// Timer1 used for all timer services
// Timer2 not used (is not present in all supported chips)
// All analog functions are disabled.
//
// - Code optimization
// Since the program is relatively small (<1024 code words) only one
// code page is really used and code page switching could be disabled
// for several functions with "#pragma update_RP". When making
// changes: check if this optimisation is still allowed by removing
// these pragma statements.
//
// ----------------------------------------------------------------------
//
// This program can be used for several types of PICs.
// Supported: PIC16F631,677,685,687,689,690
// Although the differences will be minimal, for each chip a separate hex
// file will be generated.
// The target PIC must be defined on the commandline with the '-p' parameter
// (see file the makefile timer.mak for compilation details).
// ID bytes:
#pragma config ID = PGMVERSION // defined in make file
// EEPROM data
#pragma cdata[0x2100]
// compiler version info
#pragma cdata.major = (__CC5X__ / 1000)
#pragma cdata.minor = ((__CC5X__ % 1000) / 100)
#pragma cdata.minor2 = ((__CC5X__ % 100) / 10)
#pragma cdata.suffix = (__CC5X__ % 10)
// compile date and time
#pragma packedCdataStrings 0
#pragma cdata.ctime = __DATE2__
#pragma cdata.cdate = __TIME__
// #pragma cdata.chiptype = __CHIP__
// program data: default lamp_on_period
#pragma cdata.lamponlow = 150 // 2 minutes and 30 seconds
#pragma cdata.lamponhigh = 0 // (high order byte)
// ----------------------------------------------------------------------
// Common config bit settings for all supported types of PICs
#pragma config &= ~0b11.1111.1111.1111 // all config bits OFF
#if defined(_16F631) | defined(_16F677) | defined(_16F685) | \
defined(_16F687) | defined(_16F689) | defined(_16F690)
#pragma config |= 0b11.0011.1110.0100
// xxx . . . . . INTOSC, RA4,5 = I/O
// x . . . . . . WDT disabled
// x . . . . . . . PWRTE enabled
// x . . . . . . . . /MCLR = /MCLR
// x . . . . . . . . no code protection
// x . . . . . . . . . no data protection
// xx . . . . . . . . . . BOR enabled
// x . . . . . . . . . . IESO disabled
// x . . . . . . . . . . . FCMEM disabled
// xx . . . . . . . . . . . . not used
#else
#error Program does not support the specified PIC (chip)!
#endif
// ---------------------------------------------------------------------
#include <int16cxx.h> // interrupt support
#define Fosc 1000000 // oscillator frequency
#define MPXFREQ 220 // 1/55 sec for all 4 digits
#if defined(_16F685) | defined(_16F690)
#define CCP1DELAY (Fosc/4/MPXFREQ - 1) // CCP1 load value
#define CCP1DELAYLOW (CCP1DELAY % 256) // low byte value
#define CCP1DELAYHIGH (CCP1DELAY / 256) // high byte value
#else
#define TMR1DELAY (65536 - Fosc/4/MPXFREQ + 35) // TMR1 preload
#define TMR1DELAYLOW (TMR1DELAY % 256) // low byte value
#define TMR1DELAYHIGH (TMR1DELAY / 256) // high byte value
#endif
typedef bit BOOL,BOOLEAN; // boolean variable type
#define FALSE 0
#define TRUE 1
// digit configuration
#define DIGIT0 0b0001.0000 // portb.4
#define DIGIT1 0b0010.0000 // 5
#define DIGIT2 0b0100.0000 // 6
#define DIGIT3 0b1000.0000 // 7
// segment configuration
#define sega 0b0010.0000 // portc.5
#define segb 0b0001.0000 // 4
#define segc 0b0000.1000 // 3
#define segd 0b0100.0000 // 6
#define sege 0b1000.0000 // 7
#define segf 0b0000.0001 // 0
#define segg 0b0000.0010 // 1
#define segp 0b0000.0100 // 2
// global constants
static const uns8 ucSegmentPattern[10] = {
/* 0 */ sega | segb | segc | segd | sege | segf ,
/* 1 */ segb | segc ,
/* 2 */ sega | segb | segd | sege | segg,
/* 3 */ sega | segb | segc | segd | segg,
/* 4 */ segb | segc | segf | segg,
/* 5 */ sega | segc | segd | segf | segg,
/* 6 */ sega | segc | segd | sege | segf | segg,
/* 7 */ sega | segb | segc ,
/* 8 */ sega | segb | segc | segd | sege | segf | segg,
/* 9 */ sega | segb | segc | segd | segf | segg,
};
// global variables
#pragma bit ledcontrol @ PORTA.1 // LED: true=ON false=OFF
#pragma bit lampcontrol @ PORTA.2 // lamp: true=ON false=OFF
static uns8 systemstate; // 1 second tick flag
enum _syssts {STOPPED, STARTING, RUNNING, STOPPING};
static bit tick; // 1 second tick flag
static uns8 intervalsec; // counter for 1 sec ticks
static uns16 lamp_on_period; // desired lamp-on-period
static uns16 time_remaining; // remaining lamp-on-time
static uns8 digitcurrentnumber; // currently displayed digit
static uns8 digitsecondspattern; // segment pattern seconds
static uns8 digittensecondspattern; // " " ten-seconds
static uns8 digitminutespattern; // " " minutes
static uns8 digittenminutespattern; // " " ten-minutes
// local function prototypes
static void build_patterns(void); // build 7-segment patterns
static void EEPROMReadTime(void); // read time from data EEPROM
static void EEPROMWriteTime(void); // write time to data EEPROM
static void setupPIC(void); // PIC init
static void time_decrement(void); // decrement lamp-on-period
static void time_increment(void); // increment lamp-on-period
// ---------------------------------------------------------------
// Interrupt service routine
//
// Interrupt for general time management (either CCP1 or TMR1)
// - first in the interrupt handler (when using Timer1 for accuracy)
// - performs multiplexing of 7-segment displays
// - sets 1 second interval flag for handling by mainline
//
// Interrupt on change of input PortA
// - only PortA used for input
// - saves current status of PortA for handling by mainline
//
// Note: When a CCP module is available (16F685,16F690), the special event
// interrupt feature is used. This provides a somewhat higher
// accuracy in keeping time than when using a Timer1 interrupt,
// which is used otherwise.
// ------------------------------------------------------------------
#pragma origin 4
interrupt isr(void) {
int_save_registers
#pragma update_RP 0
#if defined(_16F685) | defined(_16F690) // chips with CCP module
if (CCP1IF) { // CCP1 interrupt
#else // chips without CCP module
if (T1IF) { // TMR1 interrupt
TMR1L += TMR1DELAYLOW; // )
TMR1H += Carry; // ) reload Timer1
TMR1H += TMR1DELAYHIGH; // )
#endif
if ((++intervalsec) > MPXFREQ) { // 1 second period
tick = TRUE; // set flag (reset by mainline)
intervalsec = 0; // restart counting
}
digitcurrentnumber = (++digitcurrentnumber) & 3; // next digit / wrap
// Note: a switch()/case construct takes more cycles then if / else if
PORTB = 0b0000.0000; // previous digit off
if (0 == digitcurrentnumber) {
PORTC = digitsecondspattern; // second digit
PORTB = DIGIT0; // show digit 0
}
else if (1 == digitcurrentnumber) {
PORTC = digittensecondspattern; // 10 second digit
PORTB = DIGIT1; // show digit 1
}
else if (2 == digitcurrentnumber) {
PORTC = digitminutespattern; // minute digit
PORTB = DIGIT2; // show digit 2
}
else { // otherwise (digit 3!)
PORTC = digittenminutespattern; // 10 minute digit
PORTB = DIGIT3; // show digit 3
}
#if defined(_16F685) | defined(_16F690)
CCP1IF = FALSE; // reset interrupt flag
#else
T1IF = FALSE; // reset interrupt flag
#endif
}
#pragma update_RP 1
int_restore_registers
} // end of interrupt service
// --------------------------------------------------------------------
// Library functions to be included AFTER the interrupt service routine
// --------------------------------------------------------------------
#include <math16.h> // math support
// -------------------------------------------------------
// Perform all required basic PIC setup
// -------------------------------------------------------
static void setupPIC(void) {
#pragma updateBank exit = 0
PORTA = 0b0000.0000; // reset port
PORTB = 0b0000.0000; // " "
PORTC = 0b0000.0000; // " "
TMR1L = 0; // )
TMR1H = 0; // ) reset Timer1
T1CON = 0b0000.0001; // Timer 1 on, internal src
ANSEL = 0b0000.0000; // ) all analog off
CM1CON0 = 0b0000.0000; // Comparator 1 disabled
CM2CON0 = 0b0000.0000; // Comparator 2 disabled
#if defined(_16F631)
PIE1 = 0b0000.0001; // TMR1 interrupts enabled
#elif defined(_16F677)
ANSELH = 0b0000.0000; // )
ADCON0 = 0b0000.0000; // disable ADC
PIE1 = 0b0000.0001; // TMR1 interrupts enabled
#elif defined(_16F685)
ANSELH = 0b0000.0000; // )
ADCON0 = 0b0000.0000; // disable ADC
CCP1CON = 0b0000.1011; // Cmp mode, trig. spec. event
CCPR1L = CCP1DELAYLOW; // )
CCPR1H = CCP1DELAYHIGH; // ) Timer1 cycle
T2CON = 0b0000.0000; // Timer 2 off
PIE1 = 0b0000.0100; // CCP1 interrupts enabled
#elif defined(_16F687)
ANSELH = 0b0000.0000; // )
ADCON0 = 0b0000.0000; // disable ADC
PIE1 = 0b0000.0001; // TMR1 interrupts enabled
#elif defined(_16F689)
ANSELH = 0b0000.0000; // )
ADCON0 = 0b0000.0000; // disable ADC
PIE1 = 0b0000.0001; // TMR1 interrupts enabled
#elif defined(_16F690)
ANSELH = 0b0000.0000; // )
ADCON0 = 0b0000.0000; // disable ADC
CCP1CON = 0b0000.1011; // Cmp mode, trig. spec. event
CCPR1L = CCP1DELAYLOW; // )
CCPR1H = CCP1DELAYHIGH; // ) Timer1 cycle
T2CON = 0b0000.0000; // Timer 2 off
PIE1 = 0b0000.0100; // CCP1 interrupts enabled
#endif
OSCCON = 0b0100.0000; // 1 MHz, SCS see
// .. config bits)
TRISA = 0b0011.1001; // in: rotary, start-switch
// out: lamp/led ctl
TRISB = 0b0000.0000; // 7-segment digit control
TRISC = 0b0000.0000; // 7-segment segment control
OPTION = 0b1000.0111; //
// *** . . . . . . . . . . . . prescaler TMR0 1:256
// * . . . . . . . . . . . . . prescaler assigned to TMR0
// * . . . . . . . . . . . . . . (irrelevant: not counter)
// * . . . . . . . . . . . . . . . TMR0 clock source Fosc/4
// * . . . . . . . . . . . . . . . (irrelevant: no INT)
// * . . . . . . . . . . . . . . . . RABPU - pullups disabled (1)
INTCON = 0b1100.0000;
// * . . . . . . . . . . . . . . . . GEI general
// * . . . . . . . . . . . . . . . PEIE - external
}
// -------------------------------------------------------
// Read lamp_on_period from EEPROM data memory
// -------------------------------------------------------
static void EEPROMReadTime(void) {
#pragma updateBank exit = 0
EEADR = (uns8)lamponlow; // position in EEPROM
EECON1 = 0b0000.0001; // read data EEPROM
lamp_on_period.low8 = EEDATA; // copy to lamp_on_period
EEADR = (uns8)lamponhigh; // next position in EEPROM
EECON1 = 0b0000.0001; // read data EEPROM
lamp_on_period.high8 = EEDATA; // copy to lamp_on_period
return; // back to caller
}
// -------------------------------------------------------
// Write lamp_on_period to EEPROM data memory
// -------------------------------------------------------
static void EEPROMWriteTime(void) {
#pragma updateBank exit = 0
EEADR = (uns8)lamponlow; // offset in EEPROM memory
EEDATA = lamp_on_period.low8; // new contents
EECON1 = 0b0000.0100; // data mem, write enable
GIE = FALSE; // disable interrupts
while (GIE == TRUE) // ) check
; // )
EECON2 = 0x55; // prescribed..
EECON2 = 0xAA; // ..instruction..
WR = TRUE; // ....cycles
WREN = FALSE; // no more writes
while (WR == TRUE) // loop until..
; // ..write completed
GIE = TRUE;
EEADR = (uns8)lamponhigh; // offset in EEPROM memory
EEDATA = lamp_on_period.high8; // new contents
EECON1 = 0b0000.0100; // data mem, write enable
GIE = FALSE; // disable interrupts
while (GIE == TRUE) // ) check
; // )
EECON2 = 0x55; // prescribed..
EECON2 = 0xAA; // ..instruction..
WR = TRUE; // ....cycles
WREN = FALSE; // no more writes
while (WR == TRUE) // loop until..
; // ..write completed
GIE = TRUE; // re-enable interrupts
}
// -----------------------------------------------------------------
// Time increment function (add a number of seconds)
// NB: Only used for lamp-on-period selection
// -----------------------------------------------------------------
static void time_increment(void) {
#pragma update_RP 0
if (lamp_on_period >= 1200) { // 20:00 - 59:59
lamp_on_period += 30; // step up 30 seconds
if (lamp_on_period > 3600) // check hour overflow
lamp_on_period = 0; // wrap to 00:00
}
else if (lamp_on_period >= 600) // 10:00 - 19:59
lamp_on_period += 20; // step up 20 seconds
else if (lamp_on_period >= 300) // 05:00 - 09:59
lamp_on_period += 10; // step up 10 seconds
else if (lamp_on_period >= 120) // 02:00 - 04:59
lamp_on_period += 5; // step up 5 seconds
else if (lamp_on_period >= 60) // 01:00 - 01:59
lamp_on_period += 2; // step up 2 seconds
else // 00:00 - 01:59
++lamp_on_period; // step up 1 second
#pragma update_RP 1
} // return to caller
// -----------------------------------------------------------------
// time decrement function (substract 1 second)
// - parm is pointer to MMSS structure
// -----------------------------------------------------------------
static void time_decrement(void) {
#pragma update_RP 0
if (lamp_on_period > 1200) // 20:00 - 59:59
lamp_on_period -= 30; // step down 30 seconds
else if (lamp_on_period > 600) // 10:00 - 19:59
lamp_on_period -= 20; // step down 20 seconds
else if (lamp_on_period > 300) // 05:00 - 09:59
lamp_on_period -= 10; // step down 10 seconds
else if (lamp_on_period > 120) // 02:00 - 04:59
lamp_on_period -= 5; // step down 5 seconds
else if (lamp_on_period > 60) // 01:00 - 01:59
lamp_on_period -= 2; // step down 2 seconds
else { // 00:00 - 00:59
if (lamp_on_period > 0) // still positive
--lamp_on_period; // step down 1 second
else // currently zero
lamp_on_period = 3600; // wrap to 60:00
}
#pragma update_RP 1
}
// -----------------------------------------------------------------
// build 7-segment patterns for display of remaining time
// -----------------------------------------------------------------
static void build_patterns(void) {
#pragma update_RP 0
uns16 time_calc; // bin to dec conversion
uns8 index; // dec to 7-segment
time_calc = time_remaining; // copy
index = time_calc % 10;
digitsecondspattern = ucSegmentPattern[index];
time_calc /= 10;
index = time_calc % 6;
digittensecondspattern = ucSegmentPattern[index];
time_calc /= 6;
index = time_calc % 10;
digitminutespattern = ucSegmentPattern[index];
time_calc /= 10;
index = time_calc;
digittenminutespattern = ucSegmentPattern[index];
digitminutespattern |= segp; // minutes/seconds separator
#pragma update_RP 1
}
// ====================================================================
// M A I N L I N E
//
// - initial setup
// - for all rotary switches continously
// - check input signals
// - debounce inputs (done with 2-bits vertical counter)
// - when debounce state changed construct new
// bit pattern for output port
//
//----------------------------------------------------------------
// Rotary encoder function:
//
// Output behaviour when turning clockwise:
//
// A: --------- closed
// --- -------- open
// (Gray code 00 01 11 10 00)
// B: --------- closed
// ------ ----- open
//
// Output behaviour when turning counter clockwise:
//
// A: --------- closed
// ------ ----- open
// (Gray code 00 10 11 01 00)
// B: --------- closed
// --- -------- open
//
// Direction of rotation table: 0 - nochange or error
// 1 - clockwise
// 2 - counter clockwise
static const uns8 dirtab[16] = {0,1,2,0, 2,0,0,1, 1,0,0,2, 0,2,1,0};
// Mechanical switches, incl rotary encoders may suffer of contact
// bouncing,therefore a debouncing algorithm is applied, with vertical
// counters (method Scott Dattalo).
// There is no explicit delay between two 'forever' cycles, so debouncing
// is done at short intervals. This allows quick turning of the rotary
// encoder, but may also cause (insignificant) glitches.
//
// ======================================================================
void main(void) {
#pragma update_RP 0
uns8 CountA, CountB; // counters for debouncing
uns8 inputstate; // PORTA status
uns8 debouncedstate; // debounced input state
uns8 previousstate; // previous debounced state
uns8 delta; // changed debounced state
uns8 dirindex; // ) determination of ..
uns8 rotation; // ) .. direction of rotation
setupPIC(); // perform basic PIC setup
intervalsec = 0; // init tick counter
lampcontrol = FALSE; // lamp switched off
ledcontrol = FALSE; // LED switched off
systemstate = STOPPING; // init finite state machine
EEPROMReadTime(); // read default
time_remaining = lamp_on_period; // show lamp_on_period
build_patterns(); // initial time pattern
CountA = 0b0000.0000; // init A-bit counter
CountB = 0b0000.0000; // init B-bit counter
debouncedstate = 0b0000.0000; // init debounced state
previousstate = 0b0000.0000; // init previous state
for (;;) { // forever
// --- time management and display ---
if (STOPPED == systemstate) { // quiesced
if (time_remaining != lamp_on_period) { // reset required
time_remaining = lamp_on_period; // show lamp_on_period
build_patterns(); // new time pattern
}
}
else { // starting, running, stopping
if (tick) { // another second
tick = FALSE; // handled, reset flag
if (RUNNING == systemstate) { // counting down
if (lamp_on_period) { // not zero (continuous)
--time_remaining; // count down
build_patterns(); // new time pattern
if (time_remaining <= 0) { // end of lamp_on_period
lampcontrol = FALSE; // lamp switched off
ledcontrol = FALSE; // LED switched off
systemstate = STOPPING; // being stopped
}
}
}
else if (STARTING == systemstate) //
systemstate = RUNNING;
else if (STOPPING == systemstate) //
systemstate = STOPPED;
}
}
// --- debouncing all input signals, on PORTA ---
CountA ^= CountB; // update vertical ..
CountB = ~CountB; // .. debounce counters
inputstate = PORTA; // read Port A
delta = inputstate ^ debouncedstate; // determine changes
CountA &= delta; // reset counters ..
CountB &= delta; // .. when no changes
debouncedstate &= (CountA | CountB); // set and reset new bits
debouncedstate |= (~(CountA | CountB) & inputstate); // rewrite
// already filtered bits
if (debouncedstate ^ previousstate) { // any of the input signals
// changed (after debounce)
// --- handle rotary encoder on PORTA.4/5
if (STOPPED == systemstate) { // handle only when lamp off
if ((debouncedstate & 0b0011.0000) == 0b0011.0000) { // 1 of 4 states
dirindex = (previousstate >> 2); // prev bits 5,4 -> 3,2
dirindex &= 0b0000.1100; // keep only bits 3,2
dirindex |= ((debouncedstate >> 4) & 0b0000.0011); // add cur bits
rotation = dirtab[dirindex]; // obtain dir. of rotation
if (1 == rotation) // clock wise
time_increment(); // increment lamp_on_time
else if (2 == rotation) // counter clock wise
time_decrement(); // decrement lamp_on_period
if (rotation) { // CW or CCW
time_remaining = lamp_on_period; // copy for pattern building
build_patterns(); // new time pattern
}
}
}
// --- handle start button on PORTA.0
if ((debouncedstate ^ previousstate) & 0b0000.0001) { // state change
if (debouncedstate & 0b0000.0001) { // start button pushed
if (STOPPED == systemstate) {
systemstate = STARTING;
lampcontrol = TRUE; // lamp switched on
ledcontrol = TRUE; // LED switched on
intervalsec = 0; // ) re-init tick ..
tick = FALSE; // ) .. timer
}
else if (RUNNING == systemstate) {
systemstate = STOPPING;
lampcontrol = FALSE; // lamp switched off
ledcontrol = FALSE; // LED switched off
intervalsec = 0; // ) re-init tick ..
tick = FALSE; // ) .. timer
}
}
else { // start switched OFF
if (STARTING == systemstate) { // was switched on
systemstate = RUNNING;
EEPROMWriteTime(); // new default
}
}
}
previousstate = debouncedstate; // new previous state!
}
}
#pragma update_RP 1
}