Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
php
/
Sources
:
horloge.c
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
/* Commandes Afficheur LCD RS (Register Select) : 0 -> Instr. Reg. * 1 -> Data Reg. bitwise rtc.c realtime controller 2-Channel Time Switch V1.0 Motorola MC908QY4CP 16-pin MCU with external XTAL 4MHz for timebase realtime clock compiled with icc08 Copyright (c) 2004 Wichit Sirichote, kswichit@kmitl.ac.th mode settings state 0 set hour and min NA 1 set day NA 2 manual on/off NA 3 enter scheduler 0 :enter time 1 :enter day 2: set output 4 display scheduler NA */ #include <io908QY4.H> #define key0 (PTA&0x01) #define key1 (PTA&0x02) #define key2 (PTA&0x04) #define key3 (PTA&0x08) char temp,k,mode; char i,n,timer1,timer2,flag; unsigned char sec100,sec,min,hour,day,output; unsigned char sec, warm_boot; char *titre = "Horloge V1.0"; char buffer[8]; char *day_str[] = {"AA","MO","TU","WE","TH","FR","SA","SU","__"}; // "AA" for all days control // "__" for end of program char state; struct pgm{ char set_day; char set_hour; char set_min; char set_control; }; struct pgm PGM[5]; /* signal for lcd interface E PTB1 RS PTB0 D4 PTB4 D5 PTB5 D6 PTB6 D7 PTB7 D0-D3 and R/W# are tied to GND */ // function prototype declarations void commande_LCD(char c); void LCDWD(char c); void print_dec(char d,unsigned int n); void print_time(char d); void tick_display(void); void rafraichir_horloge(void); void scrute_clavier(void); void print_output(char n); void print_record(char d,char n); void compare_time(void); void fire_output(char N); void initialisation_LCD(void); // enter timer overflow every 1/100s or 10ms #pragma interrupt_handler isr_TIM void isr_TIM(void) { // fonction de gestion de l'interruption //PTB ^= 0x08; // toggle PTB.3 to check period // found period was 20.012ms TSC &= ~0x80; // clear TOF flag |= 2; // tick 1/100Hz COPCTL = 0; // clear COP rafraichir_horloge(); tick_display(); // tick every 0.5 sec scrute_clavier(); } #pragma interrupt_handler isrDummy void isrDummy(void) { COPCTL = 0; // clear COP } #pragma abs_address:0xffde void (* const _vectab[])(void) = { isrDummy, /* ADC */ isrDummy, /* KEYBOARD */ isrDummy, /* NOT USED */ isrDummy, /* NOT USED */ isrDummy, /* NOT USED */ isrDummy, /* NOT USED */ isrDummy, /* NOT USED */ isrDummy, /* NOT USED */ isrDummy, /* NOT USED */ isrDummy, /* NOT USED */ isr_TIM, /* TIM OVERFLOW */ isrDummy, /* TIM1 */ isrDummy, /* TIM0 */ isrDummy, /* NOT USED */ isrDummy, /* IRQ */ isrDummy /* SWI */ }; #pragma end_abs_address /********************************************************************/ void rafraichir_horloge() { if(++sec100 >=100) { sec100 = 0; if(mode !=3 && mode !=4) { print_time(0x80); print_output(output); } if(++sec > 59) { sec = 0; compare_time(); if( ++min >59) { min = 0; if(++hour >23) { hour = 0; if(++day > 7) day = 1; } } } } } /********************************************************************/ void tick_display() { if(mode !=3 && mode !=4) { if(++timer1> 50) { timer1 = 0; commande_LCD(0x85); // swap display k^=1; if (k) LCDWD(' '); else LCDWD(':'); } } } /********************************************************************/ void reglage_heure() { ++heure; if(heure>23) { heure=0; } affiche_heure(0x80); } /********************************************************************/ void reglage_minute() { ++min; sec = 0; compare_time(); if(min>59) { min =0; } affiche_heure(0x80); } /********************************************************************/ void reglage_jour() { ++jour; if(jour>7) { day = 1; } affiche_heure(0x80); } /********************************************************************/ void output2_setting() { output^=2; // XOR si x=6 alors x^=3 -> x=x^3 // 0110 // 0011 // 0101 print_output(output); } /********************************************************************/ void output1_setting() { output^=1; print_output(output); } /********************************************************************/ void pgm_setting1() { switch(state) { case 0: temp =PGM[n].set_hour; ++temp; if(temp>23) temp = 0; PGM[n].set_hour = temp; print_record(0x80,n); break; case 1: temp = PGM[n].set_day; ++temp; if(temp>8) temp = 0; PGM[n].set_day = temp; print_record(0x80,n); break; case 2: PGM[n].set_control ^= 2; print_record(0x80,n); break; } } /********************************************************************/ void pgm_setting2() { switch(state) { case 0: temp =PGM[n].set_min; ++temp; if(temp>59) temp = 0; PGM[n].set_min = temp; print_record(0x80,n); break; case 2: PGM[n].set_control ^= 1; print_record(0x80,n); break; } } /********************************************************************/ void traite_touche2() { switch(mode) { case 0: hour_setting(); break; case 1: day_setting(); break; case 2: output2_setting();break; case 3: pgm_setting1(); break; case 4: ++n; if(n>4) n=0; print_record(0x80,n); commande_LCD(0xc7); // mode 4 shows record number LCDWD(n+48); break; } } /********************************************************************/ void servicekey3() { switch(mode) { case 0: min_setting(); break; case 2: output1_setting();break; case 3: pgm_setting2(); break; } } /********************************************************************/ void servicekey0() { switch(mode) { case 0:i_LCD(); // reinit lcd manually break; case 3: ++state; if(state == 3) { state = 0; // back to initial sequence ++n; // next record } if(n>5) n = 0; // loop back to record 0 print_record(0x80,n); commande_LCD(0xc7); LCDWD(state+48); break; } } /********************************************************************/ // use bit 0 and bit 1 for two bits output at port B void print_output(char m) { commande_LCD(0xc1); if(m&2) LCDWD('*'); else LCDWD('-'); commande_LCD(0xc3); if(m&1) LCDWD('*'); else LCDWD('-'); fire_output(m); // send to PTB also } /********************************************************************/ void servicekey1() { ++mode; if(mode>4) mode = 0; commande_LCD(0xc5); LCDWD(mode+48); LCDWD('.'); LCDWD(state+48); // mode 3 has more state switch(mode) { case 3: n=0; print_record(0x80,n); state = 0; break; case 4: n=0; state = 0; print_record(0x80,n); // print record 0 commande_LCD(0xc7); // mode 4 shows record number LCDWD(n+48); break; } } /********************************************************************/ void scrute_clavier() { // controle l'appui sur une touche toutes les 250ms if(++timer2 > 20) { timer2 = 0; if(touche0 == 0) traite_touche0(); if(touche1 == 0) traite_touche1(); if(touche2 == 0) traite_touche2(); if(touche3 == 0) traite_touche3(); } } /********************************************************************/ void tempo(int j) { unsigned int i; for (i = 0; i < j; i++) COPCTL = 0; // clear COP otherwise the cpu itself will be reset } /********************************************************************/ void selection_LCD() { // on utilise la pin ENABLE de l'afficheur PORTB |= 2; // mettre le bit1=1 tempo(1); PORTB &= ~2; // mettre le bit1=0 } /********************************************************************/ void commande_LCD(char c) { /* �crire dans le registre d'instruction */ char temp; temp = c; PTB &= ~3; // clear RS and E PTB &= 0x0f; // clear high nibbel to low c &= 0xf0; // prepare only high nibble PTB |= c; pulseE(); c = temp; c <<=4; PTB &= 0x0f; PTB |= c; pulseE(); delay(5); } /********************************************************************/ void data_LCD(char c) { /* �crire dans le registre de donn�es */ char temp; temp = c; PTB |= 1; // set bit RS PTB &= ~2; // clear bit E PTB &= 0x0f; // clear high nibbel to low c &= 0xf0; // prepare only high nibble PTB |= c; // mearge high nibble first pulseE(); c = temp; c <<=4; PTB &= 0x0f; PTB |= c; pulseE(); delay(5); } /********************************************************************/ void initalisation_LCD() /* circuit standard Hitachi HD44780 mode 4 bits */ { PORTB &= ~3; // clear RS and E PORTB |= 0x30; pulseE(); delay(200); pulseE(); delay(50); pulseE(); delay(50); PORTB &= 0x0f; // et logique PORTB |= 0x20; // ou logique pulseE(); pulseE(); pulseE(); commande_LCD(0x28); // passe le bus en mode 4bits, 1ligne- 16caract�res, 5*7 points commande_LCD(0x0c); // display on/off on display,off cursor, no blink commande_LCD(0x06); // entry mode DDRAM auto address increment commande_LCD(1); // clear display delay(50); 0x28 mode 4 bits, 2 lignes, caract�re 5x8 LDAA #%00001110 Display ON, Cursor ON, Blink OFF BSR LCD_CMD LDAA #%00000110 Auto Inc, Cur. shift R, no Disp shift BSR LCD_CMD } /********************************************************************/ // print LCD text >8 // the 16x1 line LCD has two blocks start address! void affiche_chaine(char *chaine) { char i; commande_LCD(0x01); // efface LCD commande_LCD(0x80); // fixe la position de depart du curseur for(i=0; i<8; i++) LCDWD(*s++); commande_LCD(0xc0); // new address for position 9 for(i=0; i<8; i++) LCDWD(*s++); } /********************************************************************/ void affiche_horloge(char d) { // affiche l'heure sur l'afficheur en 0x80 or 0xc0 buffer[0] = *day_str[day]; buffer[1] = *(day_str[day]+1); buffer[2] = ' '; buffer[3] = hour/10+48; if(buffer[3] =='0') buffer[3] = ' '; buffer[4] = hour%10+48; // buffer[5] = ':'; left for tick display buffer[6] = min/10+48; buffer[7] = min%10+48; commande_LCD(d); for(i=0; i<5; i++) LCDWD(buffer[i]); commande_LCD(0x86); LCDWD(buffer[6]); LCDWD(buffer[7]); } // print record number #n on LCD at location d /********************************************************************/ void print_record(char d,char n) { buffer[0] = *day_str[PGM[n].set_day]; buffer[1] = *(day_str[PGM[n].set_day]+1); buffer[2] = ' '; buffer[3] = PGM[n].set_hour/10+48; if(buffer[3] =='0') buffer[3] = ' '; buffer[4] = PGM[n].set_hour%10+48; buffer[5] = ':'; buffer[6] = PGM[n].set_min/10+48; buffer[7] = PGM[n].set_min%10+48; commande_LCD(d); for(i=0; i<8; i++) LCDWD(buffer[i]); print_output(PGM[n].set_control); } /********************************************************************/ // sink current driving, fire with logic '0' void fire_output(char N) { if(N&1) PTB &= ~0x08; // clear PTB.3 else PTB |= 0x08; // set PTB.3 if(N&2) PTB &= ~0x04; // clear PTB.2 else PTB |= 0x04; // set PTB.2 } /********************************************************************/ // scan 5 records, compare // if matched, fires output void compare_time() { char i; for(i=0; i<5; i++) { if(PGM[i].set_day != 8) // skip comapre time if day = 8 { if(PGM[i].set_day == 0) // daily control { if(PGM[i].set_hour == hour && PGM[i].set_min == min) { output=PGM[i].set_control; print_output(output); } } else { // check day also if(PGM[i].set_day == day && PGM[i].set_hour == hour && PGM[i].set_min == min) { output = PGM[i].set_control; print_output(output); } } } } } /********************************************************************/ void main() { // attend la fin du reset materiel : par exemple 100ms delay(1000); // tempo d�marage du LCD DDRB = 0xff; // configuration port B en output PORTB = 0x30; // clear port B delay(1000); n = k=0; TMODH = 0x04; TMODL = 0xe0; //0xe2; // for 100Hz generation! // value in TMODL can be adjusted for precise timing TSC = 0x43; // run timer with interrupt // 4Mhz/4 = 1Mhz/8 = 125000Hz DDRA = ~0xf; // PA0-PA3 are input PTA = 0xff; // drive oscillator high // DDRB = 0xff; // port B is output port // PTB = 0; // clear port B // PTAPUE = ~0x81; // osc2 pin is PTA4 I/O //ADCLK = 0x40; // ADC clock= fbus/4 initialisation_LCD(); PTAPUE = 0x0f; // enable internal pullup CONFIG2 = 0x18; // external XTAL osc! delay(10); OCSTAT = 0x02; // enable external clock! affiche_chaine(titre); delay(20000); commande_LCD(1); // clear lcd // skip initial load if warm boot == '%' if(warm_boot != '%') { warm_boot = '%'; day = 1; hour = 10; min = 40; sec = 0; } asm cli; // active les irqs for(;;) { COPCTL = 0; // clear COP } } /********************************************************************/