#include <16F876A.h>#device adc=10#FUSES NOWDT //No Watch Dog Timer#FUSES NOLVP,NOPROTECT,XT,NOBROWNOUT#use delay(clock=4000000)//#define EEPROM_SCL PIN_C3//#define EEPROM_SDA PIN_C4#use rs232(baud=9600,xmit=PIN_C6,disable_ints)//#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3)#define LCD_RS PIN_C7 // rizeni registru LCD displeje <lcd.c>#define LCD_E PIN_B7 // enable LCD displeje <lcd.c>#define LCD_D0 PIN_B3 // data LCD <lcd.c>#define LCD_D1 PIN_B2#define LCD_D2 PIN_B1#define LCD_D3 PIN_B0#define PWM_OUT PIN_C2 // kontrast LCD - menic#define LCD_ENABLE PIN_A1#define GM_PIN PIN_A4 // vstup od GMT#define HV_ENABLE PIN_A3 // start 400V#define CHARGE PIN_A2 // nabijeni baterie#define KBD_K4 0 //tlacitko na PIN_B7 neexistuje <kbd.c>#define TL3 0x10 //tlacitko PIN_B4 -ostatni default, viz <kbd.c>#define TL2 0x20 //tlacitko PIN_B5 <kbd.c>#define TL1 0x40 //tlacitko PIN_B6 <kbd.c>#define KBD_CALMTIME 1 //x*40ms - doba na zakmity tlacitek <kbd.c>#define KEYDELAY 30 //x*40ms - doba podrzeni tlacitka do opakovani#define KEYREPEAT 6 //x*40ms - doba opakovani stiskleho tlacitka#define LOG_PERIOD 30 //perioda logovani v min#define TIME_TO_SLEEP 19 //x*16s - doba do uspani, pokud zadny stisk a HV nebezi#define MAX_EEPROM 255 //max velikost vnitrni ee pameti#define EE_LOG_SWITCH 1 //misto v ee, kam se uklada zpusob logovani#define EE_LOG_OFFSET 0 //misto v ee, kde je ulozen offset dalsiho volneho mista#define ECHO_MAX_CYCLE 700 //ryhlost hlavni smyèky za 40ms /cca 20kHz/ (700)#define ECHO_PIN1 PIN_C4 //piezo#define ECHO_PIN2 PIN_C5 //piezo#define TEST_V_BATT 0x0f //maska minut pro test baterie#define BATT_ENABLE 525 //1024/ADC*1.5+0.18 ADC=525 .. Ubat=3.1V; jeli Ubat nizsi pak sleep#include <lcd.c>#include <kbd.c>int8 ms7RTC,sRTC,mRTC,hRTC,dRTC,mdRTC,yRTC; //promenne RTCint1 vypocet,refresh,counters,sleep,log,piezo; //povoleni vypoctu,zobrazeni,citani,uspani,logovani,cvak piezaint16 avg,bkg,min,max,dif; //hlavni zobrazované promìnneint32 gmcount,mincount; //citac trubice GM,citac minut od startuint8 timer_n,timer_s; //citace pulzù do 40ms, v celych 40ms, v predchozi 40msint32 gmcount_p; //pocet pulzu od zapnuti v predchozi cele minuteint32 gmcount_sm; //pocet pulzu od zapnuti precteno v cele minuteint8 s25tik,sTIK; //tiky pro casovani trubice 25tiku do sekundy, 60s do minint8 key_timer,save_key,keyp; //pomocny citac pro tlacitka,ulozeni stiskleho tlacitka,provedeni akce stiskleho tl.int8 menu_A,menu_B; //vektor pro pohyb v menu na LCDint8 log_interval; //minutovy citac do dalsiho loguint8 log_switch; //prepinac zpusobu logovaniint8 ee_offset; //kam v ee ulozit dalsi zaznamint8 echo_switch,echo_tik; //povolení echa,poèet tiku za 40msint16 echo_timer,echo_cycle; //èitaè rychlosti smyèky pro echo,cvaknuti v cykluint8 pwm; //kontrastint8 tik_to_sleep; //casovac pro uspanifloat analog; //napeti baterieint1 test_batt; //test napeti baterieint1 test; //pokusint8 timertest; //pokus#priority timer2,timer1,rb#int_TIMER2 //nastaven presne na 40ms,cte casovac timer0 GMTTIMER2_isr(){kbd_ticktimer();if (key_timer) key_timer--;if (!counters) {set_timer0(0);s25TIK=0;sTIK=0;return;}if (echo_switch) echo_switch=2;timer_n=get_timer0();s25TIK++;if (timer_n!=timer_s) //nastala zmena v citaci,pak proved pricteni puslu{if (timer_n < timer_s) {timer_s=256-timer_s+timer_n;gmcount=gmcount+timer_s;} //test preteceni casovaceelse {timer_s=timer_n-timer_s;gmcount=gmcount+timer_s;}echo_tik=timer_s;timer_s=timer_n;if (menu_A==1 && menu_B==0) refresh=true;}else echo_tik=0;if (s25TIK==25) //cela sekunda{s25TIK=0;sTIK++;if (menu_A==1 && menu_B==5) refresh=true;if (sTIK==60) //cela minuta{sTIK=0;mincount++;vypocet=true;gmcount_sm=gmcount;}}}#int_RBRB_isr(){kbd_pullkbd();tik_to_sleep = TIME_TO_SLEEP;}int8 modulo(int8 h,int8 m) //pomocna fce pro modulo x{if (h<m) return (h);return(h-m);}void clear_lcd(){printf(lcd_putc,"\f");}void set_date() //citac datumu{dRTC++;switch (mdRTC){case 1:case 3:case 5:case 7:case 8:case 10:case 12: if(dRTC>=32) {dRTC=1;mdRTC++;if(mdRTC==13) {mdRTC =1;yRTC=modulo(yRTC++,100);}} break;case 4:case 6:case 9:case 11: if(dRTC>=31) {dRTC=1;mdRTC++;} break;case 2: if (dRTC >= 30) {dRTC=1;mdRTC++;break;}if (dRTC ==29) {if (!(yRTC & 0x03)) break;dRTC=1;mdRTC++;}}}#int_TIMER1 // RTCTIMER1_isr(){sRTC=sRTC+16;if (sRTC >= 60){mRTC++;sRTC=modulo(sRTC,60); //1minif (mRTC>=60) {hRTC++;mRTC=0;} //1hodif ((mRTC & TEST_V_BATT) == TEST_V_BATT) test_batt=true;if (hRTC>=24) {hRTC=0;set_date();} //1den}refresh=true;if (tik_to_sleep) tik_to_sleep--;}void ee_head() //ulozeni hlavicky do ee cas,datum,zpusob logovani{ //v ee 100hhhhh /hodiny/,l0mmmmmm /log + minuty/,000ddddd /den/,yyyymmmm /rok-7,mesic/int8 data;log=true;if (!log_switch) return;if (ee_offset>5) {data=read_eeprom(ee_offset-4);if (bit_test(data,7)) ee_offset=ee_offset-4;}if (ee_offset>=(MAX_EEPROM-5)) {log=false;return;}log_interval=0;data=hRTC;bit_set(data,7);write_eeprom(ee_offset++,data);data=mRTC;if (bit_test(log_switch,0)) bit_set(data,7);write_eeprom(ee_offset++,data);write_eeprom(ee_offset++,dRTC);data=((yRTC-7) << 4)|mdRTC;write_eeprom(ee_offset++,data);}void menu_proces(int8 key) //menu zobrazene na LCD pri citani{switch (key){case TL1: menu_A=2;refresh=true;clear_lcd();return;case TL2: if (log) log=false;else ee_head();break;case TL3: menu_B=modulo(++menu_B,6);break;}printf(lcd_putc,"\rdif=%lu ",dif);lcd_gotoxy(11,1);if (log) printf(lcd_putc,"L"); //pokud se loguje, zobraz Lelse printf(lcd_putc," ");if (bkg) printf(lcd_putc,"B"); //pokud jiz je BKG,zobraz Blcd_gotoxy(14,1);printf(lcd_putc,"%3u\n",(int8)(MAX_EEPROM-ee_offset)/2); //zbivajici misto v eeswitch (menu_B){case 0: printf(lcd_putc,"n=%lu",gmcount);break;case 1: printf(lcd_putc,"min=%Lu",min);break;case 2: printf(lcd_putc,"max=%lu",max);break;case 3: printf(lcd_putc,"avg=%lu",avg);break;case 4: printf(lcd_putc,"bkg=%lu",bkg);break;case 5: printf(lcd_putc,"ontime=%lu:%02d ",mincount,sTIK);break;}}void send_data() //posle data z ee na rs232 9600 8N1{int8 i;int16 data;int8 *adr;for (i=2;i<ee_offset;i){adr=&data;*adr=read_eeprom(i++);if (bit_test(*adr,7)) //test, zda se nejedna o hlavicku v ee{bit_clear(*adr,7);printf("\r\n%d:",*adr);*adr=read_eeprom(i++);printf("%02d ",(0x3f&*adr));adr++;*adr=read_eeprom(i++);printf("%d/",*adr);*adr=read_eeprom(i++);printf("%02d/",*adr&0x0f);*adr=(*adr>>4)+7;printf("%02d ",*adr);adr--;if (bit_test(*adr,7)) printf("1min");else {*adr=LOG_PERIOD;printf("%umin",*adr);}}else{data=data<<8;*adr=read_eeprom(i++);printf("\r\n%lu",data);}}}void display(int8 key) //zobrazeni na LCD - zakladni menu{int8 mon,year; //pomocne promenneif (key) clear_lcd();keyp=0;refresh=false;if (menu_A>1) { //zmena pri stisku tl spolecna pro vetsinu menu_Aif (key==TL3) {menu_A++;if (menu_A>11) menu_A=2;} //TL3 pak rolluj v menu_Aif ( ( menu_A != 10 ) && ( menu_A != 6 ) && (menu_A != 11) ){if (key==TL1){if (counters) menu_A=1;else menu_A=0;key=0;}else printf(lcd_putc,"\r\nesc cr roll\r");}}switch (menu_A) //hlavni menu{case 0: min=0xffff; //zakladni menu po resetu, nastaveni promennychmax=gmcount=gmcount_sm=gmcount_p=timer_s=timer_n=mincount=dif=avg=bkg=0;vypocet=sleep=counters=log=echo_switch=false;test_batt = true;log_switch=read_eeprom(EE_LOG_SWITCH);ee_offset=read_eeprom(EE_LOG_OFFSET);output_high(HV_ENABLE);printf(lcd_putc,"\r%d:%02d %d.%d.%02d \nmenu off start",hRTC,mRTC,dRTC,mdRTC,yRTC);switch (key){case TL1: menu_A=2;break;case TL2: menu_A=menu_B=0;sleep=true;break;case TL3: menu_A=1;menu_B=0;output_low(HV_ENABLE);printf(lcd_putc,"\fSTART HV 400V");delay_ms(2000);counters=true;break;}if (key) {refresh=true;clear_lcd();}break;case 1: menu_proces(key);break; //skok na menu zobrazujici vypoctene a nacitane promennecase 3: if (key==TL2) {log_switch=modulo(++log_switch,3);write_eeprom(EE_LOG_SWITCH,log_switch);log=false;}switch (log_switch){case 0: printf(lcd_putc,"log \176 rs232");break;case 1: printf(lcd_putc,"log \176 eeprom 1m");break;case 2: mon=LOG_PERIOD;printf(lcd_putc,"log \176 eeprom %um",mon);break;//case 3: printf(lcd_putc,"log \176 off ");break;}break;case 9: printf(lcd_putc,"OFF (stand by)");if (key==TL2) {menu_A=menu_B=0;sleep=true;output_high(HV_ENABLE);}break;case 8: if (key==TL2) if (echo_switch) echo_switch=0;else echo_switch=1;if (echo_switch) printf(lcd_putc,"echo on");else printf(lcd_putc,"echo off");break;case 4: if (key==TL2) send_data();printf(lcd_putc,"send log \176 rs232");break;case 5: if (key==TL2) {log=false;ee_offset=2;write_eeprom(EE_LOG_OFFSET,2);}printf(lcd_putc,"erase eeprom %3u",(int8)(MAX_EEPROM-ee_offset)/2);break;case 2: printf(lcd_putc,"STOP & clear");if (key==TL2) {menu_A=0;menu_B=0;refresh=true;}break;case 7: printf(lcd_putc,"batterie ");//if (!input(CHARGE)) {printf(lcd_putc,"charge");break;}if ( key == TL2 || counters ){if ( !counters ) {output_low(HV_ENABLE);delay_ms(30);}analog = (float) (read_adc());analog = 1024/analog*1.5 + 0.18;if ( !counters ) output_float(HV_ENABLE);printf(lcd_putc,"%1.2fV",analog);}break;case 6: if (key == TL2) {pwm++;if (pwm > 10) pwm --;}if (key == TL1) {pwm--;if (pwm < 2) pwm ++;}set_pwm1_duty(pwm);printf(lcd_putc,"contrast: %d\n - + roll",pwm);break;case 10: if (key==TL2) {set_timer1(0);sRTC=0;mRTC=modulo(++mRTC,60);}if (key==TL1) hRTC=modulo(++hRTC,24);printf(lcd_putc,"\rtime %2d:%02d\nhod min roll",hRTC,mRTC);break;case 11: if (key==TL1) {mon=mdRTC;year=yRTC;set_date();mdRTC=mon;year=yRTC;}if (key==TL2) {mon=dRTC;year=yRTC;dRTC=32;set_date();year=yRTC;}if (key==0x30) {mon=mdRTC;yRTC++;dRTC--;set_date();}printf(lcd_putc,"\rdate %2d.%02d.%02d\nday mon roll",dRTC,mdRTC,yRTC);break;}}void counters_fce(){int8 *adr;if (vypocet) //1x za minutu se provede vypocet a log{dif=gmcount_sm-gmcount_p;gmcount_p=gmcount_sm;avg=gmcount_sm/mincount;if (dif>max) max=dif;if (dif<min) min=dif;if (mincount==5) bkg=gmcount_sm/5;vypocet=false;refresh=true;if (log){//if (log_switch && (ee_offset>(MAX_EEPROM-2))) {log=false;return;}switch (log_switch){case 0: printf("\n\r%d:%02d %2d/%02d/%02d dif=%lu",hRTC,mRTC,dRTC,mdRTC,yRTC,dif);break;case 2: if (log_interval) break;case 1: adr=&dif;adr++;bit_clear(*adr,7);write_eeprom(ee_offset++,*adr);write_eeprom(ee_offset++,*(--adr));write_eeprom(EE_LOG_OFFSET,ee_offset);if (ee_offset > (MAX_EEPROM-2)) log=false;break;}log_interval=modulo(++log_interval,LOG_PERIOD);}}}void echo_fce(){int8 a,c;int16 b;if (!echo_tik || !counters) return;//if (echo_switch==2) {echo_switch=1;echo_cycle=ECHO_MAX_CYCLE/echo_tik;echo_timer=0;}if (echo_tik == 1){for (a=0;a<2;a++) {output_high(ECHO_PIN1);delay_us(160);output_low(ECHO_PIN1);delay_us(160);}echo_tik=0;}else /*if ((echo_timer == echo_cycle) || (!echo_timer))*/{echo_switch=1;c=echo_tik;if (echo_tik <40) {a=40/c;b=0;}if ((echo_tik >=40) && (echo_tik < 60)) {a=0;b=40000/c;}if (echo_tik >=60) {a=0;b=160;}while (echo_tik && (echo_switch==1) && !kbd_press()){echo_timer=0;output_high(ECHO_PIN1);delay_us(160);output_low(ECHO_PIN1);piezo=~piezo;delay_us(b);delay_ms(a);}//output_bit(ECHO_PIN2,piezo);}echo_timer++;}void pin_set_sleep(){#use fast_IO(A)set_tris_A(0x15);output_A(0x2a);#use standard_IO(A)#use fast_IO(B)set_tris_B(0x70);output_B(0x8f);#use standard_IO(B)#use fast_IO(C)set_tris_C(0x2);output_C(0x84);#use standard_IO(C)}void sleep_fce(){/*if (!input(CHARGE)) // pokud se nabiji, pak nespi{printf(lcd_putc,"\fcharged batt");tik_to_sleep = 0;while (!tik_to_sleep) if (input(CHARGE)) return;kbd_getc();sleep = false;}else */{//setup_timer_0(RTCC_DIV_1|RTCC_INTERNAL);//setup_timer_1(T1_DISABLED);//setup_timer_2(T2_DIV_BY_16,249,10);counters=false;printf(lcd_putc,"\fchrrr");delay_ms(1000);setup_adc_ports(ADC_OFF);setup_ccp1(CCP_OFF);//SET_TRIS_A(0xFF);//SET_TRIS_B(0xFF);//SET_TRIS_C(0xFF);pin_set_sleep();do {sleep();delay_cycles(1);} while ( kbd_state!=0x20 /*&& input(CHARGE)*/ );#use fast_IO(B)set_tris_B(0x70);output_B(0);#use standard_IO(B)setup_adc_ports(AN0);setup_adc(ADC_CLOCK_DIV_16);set_adc_channel(0);//setup_timer_0(RTCC_DIV_1|RTCC_EXT_L_TO_H);//setup_timer_2(T2_DIV_BY_16,249,10);//setup_ccp1(CCP_PWM);menu_A=menu_B=0;setup_ccp1(CCP_PWM);set_PWM1_duty(pwm);delay_ms(200);output_low(LCD_ENABLE);output_high(HV_ENABLE);lcd_init();//printf(lcd_putc,"\fhello");delay_ms(1000);kbd_getc();keyp=0;sleep=false;refresh=true;}}void main(){setup_adc_ports(AN0);setup_adc(ADC_CLOCK_DIV_16);set_adc_channel(0);setup_timer_0(RTCC_DIV_1|RTCC_EXT_L_TO_H);setup_timer_1(T1_EXTERNAL|T1_DIV_BY_8|T1_CLK_OUT);setup_timer_2(T2_DIV_BY_16,249,10);setup_ccp1(CCP_PWM);set_PWM1_duty(0x5);enable_interrupts(INT_TIMER2);enable_interrupts(INT_RB);enable_interrupts(INT_TIMER1);enable_interrupts(GLOBAL);output_low(LCD_ENABLE);KBD_init();LCD_init();pwm=5;sRTC=0;mRTC=0;hRTC=0;dRTC=18;mdRTC=10;yRTC=07;menu_A=menu_B=0;refresh=true;keyp=0;while (TRUE){if (refresh) display(keyp); //povoleni zobrazeni(menu + fce tlacitek)if (counters) { tik_to_sleep = TIME_TO_SLEEP;counters_fce();} //povoleni citacu,vypoctu a logovanielse if (! tik_to_sleep) sleep = true; //necita a zadny stisk tlacitek do TIME_TO_SLEEP pak sleepif (echo_switch) echo_fce();if (kbd_press()) //test stisku tlacitek,repeat, delay{if (!save_key) {save_key=kbd_getc();keyp=save_key;refresh=true;key_timer=KEYDELAY;} //delay keyif (!key_timer) {refresh=true;keyp=save_key;key_timer=KEYREPEAT;} //repeat key}else key_timer=save_key=keyp=0;//echo (piezo)if (test_batt && counters) //test napeti baterie{if (read_adc() > BATT_ENABLE){printf(lcd_putc,"\flow batt");delay_ms(2000);sleep = true;}test_batt=false;}if (sleep) sleep_fce(); //sleep//if (!timertest) {timertest=30;output_bit(PIN_C3,test);test=~test;}//timertest--;}}