📄 f_14_21_alarm.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 + -