⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f_14_21_alarm.c

📁 PIC_Hi-Tech_C_Mike_Pearces_I2C_routines Microchi PIC_Hi-Tech C_I2C_for_EEPROM_24LC01B Code
💻 C
字号:

#include "config.h"
#include "delay.h"
#include "lcd_module.c"
#include "serial.c"
#include "serio.c"

#include "i2cmsu.c"
#include "temp_module.c"

#include "rot_module.c"
#include "ee_module.c"

#define ALARM_DELAY 10  //delay audible alarm after pushbutton
#define DEBOUNCE  4     //debounce time

// variables
volatile unsigned char left_button,left_debounce,right_button,right_debounce;
volatile unsigned char motion, alarm_count,update_flag;
volatile unsigned char t_hour, t_min, t_sec,hour, min, sec,old_sec;
volatile unsigned char hour1, min1, sec1, hour2, min2, sec2;
volatile unsigned char int0_cnt,int0_last,int1_cnt,int1_last;
volatile long cur_time;
unsigned long alarm_start, alarm_stop;
volatile signed int raw_temp, temp_c,temp_f, temp_mode;

void do_debounce(void) {
  //debounce pushbuttons
  if (!right_button && !INT1IE) {
    if (RB1) right_debounce++;
    else right_debounce=0;
    if (right_debounce == DEBOUNCE){
      //re-enable interrupt
      INT1IF=0;INT1IE=1;
    }
  }
  if (!left_button && !INT2IE) {
    if (RB2) left_debounce++; else left_debounce=0;
    if (left_debounce == DEBOUNCE){
      //re-enable interrupt
      INT2IF=0;INT2IE=1;
    }
  }
  if (ROT0 != int0_last) {// debounce rotary inputs
    int0_cnt++;
    if (int0_cnt == DEBOUNCE) {
      update_flag = 1; int0_cnt = 0;int0_last = ROT0;
    }
  }
  // reset cnt, if pulse width not long enough
  else if (int0_cnt)  int0_cnt = 0;
  if (ROT1 != int1_last) {
    int1_cnt++;
    if (int1_cnt == DEBOUNCE) {
      update_flag = 1; int1_cnt = 0; int1_last = ROT1;
    }
  }
  // reset cnt, if pulse width not long enough
  else if (int1_cnt)   int1_cnt = 0;
  if (update_flag) {
    // can read the rotary inputs
    update_rotary_state(); update_flag = 0;
  }
}

#if defined(HI_TECH_C)
void interrupt isr(void)
#endif
#if defined(__18CXX)
#pragma interrupt isr
void isr(void)
#endif
{
  if (TMR1IF && TMR1IE) { // time-of-day
    TMR1IF=0; sec = sec + 2; // seconds
    cur_time=cur_time+2;
    if (sec > 59) {
      min++; sec = sec-60;
      if (min == 60) {
	hour++; min = 0; 
	if (hour == 24) {
	  hour = 0; cur_time = 0;
	}
      }
    }
  }
  if (INT1IF && INT1IE) {// pushbutton detected
    INT1IE = 0;right_button = 1;right_debounce = 0;
  }
  if (INT2IF && INT2IE) {// pushbutton detected
    INT2IE = 0; left_button = 1; left_debounce = 0;
  }
  if (INT0IF && INT0IE) { // motion sensor
    motion = 1; INT0IE = 0;
  }
  if (TMR3IF) {// debouncing timer
    TMR3IF = 0;
    do_debounce();
  }
}

#define BUFSIZE 64
char buf[64];

void update_lcd_time1(unsigned char pos) {
  lcd_write(pos,0,1,1);  // 1st line
  printf("%02d:%02d:%02d",t_hour,t_min,t_sec);
}

void update_lcd_time(void)
{
  unsigned char status, c;
  lcd_write(0x80,0,1,1);  // 1st line
  printf("%02d:%02d:%02d",hour,min,sec);
  lcd_write(0xC0,0,1,1);  // 2nd line
  // check if temp conversion done, if yes, update
  status = ds1621_read1(ACCESS_CONFIG);
  if (bittst(status,7)){
    ds1621_read2(READ_TEMP,(unsigned char *)&raw_temp);
    // start new conversion
    ds1621_send0(START_CONVERT);
  }
  if (motion) c = 'M';  else c = ' ';
  temp_c = (raw_temp >> 8);
  temp_f = (temp_c*9)/5 + 32;
  if (temp_mode)  printf("%c%5d C",c,temp_c);
  else  printf("%c%5d F",c,temp_f);
}

//right button advances cursor
//left button exits
void do_settime(void){
  char pos;
  GIE=0;
  pos = 0x81; // hours position
  lcd_write(0x0E,0,0,1);  // turn on cursor
  while(1){
    switch (pos) {
    case 0x81: rotcount=t_hour;rot_min=0;rot_max=23;
      break;
    case 0x84: rotcount = t_min;rot_min=0;rot_max=59;
      break;
    case 0x87: rotcount =t_sec;rot_min=0;rot_max=59;
      break;
    }
    update_lcd_time1(0x80);
    lcd_write(pos,0,1,1); //position cursor
    // wait for change of input
    last_rotcount = rotcount;
    right_button=0; left_button=0;
    GIE=1;
    while(!left_button && !right_button 
	  && (rotcount == last_rotcount));
    GIE=0;
    if (rotcount != last_rotcount){
      // update values
      switch (pos) {
      case 0x81: t_hour=rotcount;break;
      case 0x84: t_min=rotcount;break;
      case 0x87: t_sec=rotcount;break;
      }
    }
    if (right_button) {
      pos = pos+3;
      if (pos == 0x8A) pos = 0x81;
    }
    if (left_button) {
      // turn off cursor
      lcd_write(0x0C,0,0,1);  // turn off cursor
      break; // exit loop
    }
  } // end while(1)
  // before returning, clear input flags, restore interrupts
  last_rotcount = rotcount;
  right_button=0;
  left_button=0;
  GIE=1;
}


const char stime_msg[]="Set Time";
const char blank_msg[]="        ";
const char mon1_msg[]="Set Strt";
const char mon2_msg[]="Set Stop ";

void new_choice(const char *s){
  lcd_write(0x80,0,1,1);  // 1st line
  printf("%s",s);
  lcd_write(0xC0,0,1,1);  // 2nd line
  printf("%s",blank_msg);
}

#if defined(__18CXX)
char * get_data(char *s,volatile unsigned char *data, char aflag)
{
 
  *data = (unsigned char) atoi(s);
  if (aflag) {
	while (isdigit(*s)) {
	s++;
	}
	while (isspace(*s)){
	 s++;
	}
  }
  return(s);
}
#endif
  

void read_start_stop(void) {
  eedata_readstr((unsigned char *)buf,0,BUFSIZE);
#if defined(HI_TECH_C) 
  sscanf(buf,"%d %d %d %d %d %d",&hour1,&min1,&sec1,&hour2,&min2,&sec2);
#endif
#if defined(__18CXX)
  { //MCC18 does not have sscanf
    char *s;
	s = buf;
    s = get_data(s,&hour1,1);
	s = get_data(s,&min1,1);
	s = get_data(s,&sec1,1);
    s = get_data(s,&hour2,1);
	s = get_data(s,&min2,1);
	s = get_data(s,&sec2,0);
  }

#endif 
}

void save_start_stop(void) {
  sprintf(buf,"%d %d %d %d %d %d",hour1,min1,sec1,
	  hour2,min2,sec2);
  eedata_writestr((unsigned char *)buf,0);
}



void do_config(void) {
  char unsigned status;

  left_button = 0; right_button = 0;
  motion = 0; alarm_count = 0;
  hour=0;min=0;sec=0;
  RBPU = 0; // enable the weak pullup on port B
  read_start_stop(); // read old alarm values from eeprom
  alarm_start = hour1*60+min1*60+sec1;
  alarm_stop = hour2*60+min2*60+sec2;

  i2c_init(72);// init I2C interface
  ds1621_send1(ACCESS_CONFIG,0x01); // one shot mode
  ds1621_send0(START_CONVERT); // start conversion
  do{ // wait until first conversion is done
    status = ds1621_read1(ACCESS_CONFIG);
  } while(!bittst(status,7));


  // rotary setup
  ROT0_IN;  ROT1_IN;
  int0_last = ROT0;  int1_last = ROT1;
  last_state = 0;
  if (ROT0) last_state = last_state | 0x01;//set LSb
  if (ROT1) bitset(last_state,1);

  E_OUTPUT;  RS_OUTPUT;  RW_OUTPUT;  ELOW; RSLOW;  RWLOW; 
  lcd_init();  update_lcd_time();

  // initialize timer 1, prescale by 1, ext. async. clock
  T1CKPS1 = 0;  T1CKPS0 = 0;  T1OSCEN = 0;   TMR1CS = 1;  T1SYNC = 1; 
  TRISC0 = 1;  // set T1CKI/RC0 as input

  // confg. tmr2 for PWM mode, 0% duty cycle,pre=16, CCP1 output
  T2CKPS1 = 1; PR2 = 255; CCPR1L = 0;  
  bitclr(CCP1CON, 5);  bitclr(CCP1CON, 4);  bitclr(TRISC,2);
  bitset(CCP1CON, 3);  bitset(CCP1CON, 2);
  TMR2ON = 1;

  // use timer3 for debounce, int. clock
  T3CKPS1 = 0;  T3CKPS0 = 0; TMR3CS = 0;  T3SYNC = 0;
  TMR3IF = 0;  TMR3IE = 1;  TMR3ON = 1;

  // pushbutton input configuration, fall. edge interrupt
  TRISB1 = 1; INT1IF = 0; INTEDG1 = 0;INT1IE = 1;
  TRISB2 = 1; INT2IF = 0; INTEDG2 = 0;INT2IE = 1;
  // motion sensor input, rising edge interrupt
  TRISB0 = 1;  INTEDG0 = 1;  INT0IF=0; INT0IE=1;

  // enable timer 1 and general interrupts
  TMR1IF = 0;  TMR1IE = 1;  TMR1ON = 1;   
  IPEN = 0;  PEIE = 1;  GIE = 1;  
}
  

#define DISPLAY_TIME 0
#define SET_TIME     1
#define SET_START    2
#define SET_STOP     3

void main(void){
  char unsigned mode;
  do_config(); //configure subsystems
  mode = DISPLAY_TIME; temp_mode = 0; old_sec = sec;
  while(1) {
    switch (mode) {
    case DISPLAY_TIME:
      while(mode==DISPLAY_TIME) {
	if (left_button) {
	  CCPR1L = 0x00; // turn off alarm
	  alarm_count = 0; // clear alarm delay
	  left_button = 0; //clear flag
	  mode = SET_TIME;
	}
	if (right_button) {
	  CCPR1L = 0x00; // turn off alarm
	  alarm_count = 0;
	  right_button = 0; //clear flag
	  temp_mode = ~temp_mode;
	}
	if (old_sec != sec) {
	  old_sec = sec;
	  if (alarm_count <= ALARM_DELAY)
	    alarm_count = alarm_count+2;
	  update_lcd_time();
	  if (motion) {
	    // see if should turn on alarm
	    motion = 0;
	    INT0IF = 0;
	    INT0IE = 1;
	    if (alarm_count > ALARM_DELAY) {
	      if ((cur_time > alarm_start) && (cur_time < alarm_stop)) {
		CCPR1L = 0x30; // turn on alarm
	      }
	    }
	  }
	}
	GIE = 0;
	if (INT1IE && INT2IE && 
	    !int0_cnt && !int1_cnt && !CCPR1L) {
	  // no debouncing or alarm so sleep, 
	  // wake on timer1 rollover every 2 sec
	  SLEEP();
	}
	GIE = 1;
      }
     break;
    case SET_TIME:
      new_choice(stime_msg);
      while(mode==SET_TIME) {
	if (left_button) {left_button = 0; mode = SET_START;}
	if (right_button) {
	  right_button = 0;
	  GIE=0;t_hour=hour;t_min=min;t_sec=sec; GIE=1;
	  do_settime();
	  GIE=0; hour=t_hour;min=t_min;sec=t_sec;
	  cur_time = hour*60+min*60+sec;
	  GIE=1;
	  new_choice(stime_msg);
 	}
      }break;
    case SET_START:
      t_hour=hour1;t_min=min1;t_sec=sec1;
      new_choice(mon1_msg);
      update_lcd_time1(0xC0);
      while(mode==SET_START) {
	if (left_button) {left_button = 0; mode = SET_STOP;}
	if (right_button) {
	  right_button = 0;
	  GIE=0;t_hour=hour1;t_min=min1;t_sec=sec1; GIE=1;
	  do_settime();
	  GIE=0;hour1=t_hour;min1=t_min;sec1=t_sec; GIE=1;
	  save_start_stop();// write start/stop to eeprom
	  new_choice(mon1_msg); update_lcd_time1(0xC0);
 	}
      } break;
    case SET_STOP:
      t_hour=hour2;t_min=min2;t_sec=sec2;
      new_choice(mon2_msg);
      update_lcd_time1(0xC0);
      while(mode==SET_STOP) {
	if (left_button) {left_button = 0; mode = DISPLAY_TIME;}
	if (right_button) {
	  right_button = 0;
	  GIE=0;t_hour=hour2;t_min=min2;t_sec=sec2;GIE=1;
	  do_settime();
	  GIE=0;hour2=t_hour;min2=t_min;sec2=t_sec; GIE=1;
	  save_start_stop();
	  new_choice(mon2_msg); update_lcd_time1(0xC0);
 	}
      } break;
    }//end switch (mode)
  }// end while(1)
}// end main()

//for MCC18, place the interrupt vector goto
#if defined(__18CXX)
#if defined(HIGH_INTERRUPT)
#pragma code HighVector=HIGH_INTERRUPT
#else
#pragma code HighVector=0x0008  
#endif
void HighVector (void)
{
    _asm goto isr _endasm
}
#pragma code
#endif




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -