/***********************************************************************/ /* */ /* FILE :DCF_LCD_UHR.c */ /* DATE :Wed, Jun 21, 2006 */ /* DESCRIPTION :main program file. */ /* CPU GROUP :13(ROM16K) */ /* */ /* This file is generated by Renesas Project Generator (Ver.4.5). */ /* */ /***********************************************************************/ /* Programm zur Decodierung des DCF77-Signals und Anzeige auf SPI-LCD EA DOGM162x-A */ /* für Renesas R8C/13 auf Elektor-Board */ /* DCF77-Signal auf Port 1 Bit 0 */ /* LED für DCF77-Signal auf Port 1 Bit 1 */ /* SI von LCD auf Bit 2 */ /* CLK von LCD auf Bit 3 */ /* RS von LCD auf Bit 6 */ // Aliase für Port-Bits definieren für bessere Lesbarkeit #define DCF77_SIGNAL p1_addr.bit.b0 // Eingangsport für das DCF77-Signal ist Bit 0 von Port 1 #define SIGNAL_LED p1_addr.bit.b1 // Ausgangsport für die DCF77-Signal-LED ist Bit 1 von Port 1 #define SI p1_addr.bit.b2 // Ausgangsport für die Datenleitung zum LCD ist Bit 2 von Port 1 #define CLK p1_addr.bit.b3 // Ausgangsport für die Taktleitung zum LCD ist Bit 3 von Port 1 #define RS p1_addr.bit.b6 // Ausgangsport für die Statusleitung zum LCD ist Bit 6 von Port 1 // Special Function Register einbinden #include "sfr_r813.h" // Deklaration Datentypen _Bool bit[60]; // Zeit und Datum sind in 60 Impulse pro Minute codiert, hierfür 60-Bit Speicher char year = 0, month = 0,day = 0, dayofweek = 0,hour = 0,minute = 0,second = 0; // Deklaration Funktionen void init_externosci(void); // Externen Oszillatorkreis mit Quarz aktivieren, 20 MHz void delay_ms(unsigned int millis); // Programmablauf um angegebene Zahl Millisekunden verzögern void calc_time_and_date(void); // Zeit und Datum aus 60 Bit berechnen void send_byte_to_lcd(char byte); // ein Byte zum LCD senden void int_lcd(void); // LCD initialisieren void display_chars_on_lcd(char* characters, int size); // Mit 'size' anzugebende Anzahl alphanumerischer Zeichen auf LCD ausgeben void display_digits_on_lcd(char digit); // zweistellige Ganzzahl ausgeben void set_lcd_cursor_pos(char column, char row); // Cursorpsotion auf LCD setzen void display_time_and_date_on_lcd(void); // Zeit und Datum auf LCD ausgeben //---------------------------------------------------------------------------------------------------------------------- //Hauptprogramm void main(void) { init_externosci(); // Oszillator mit externem Quarz aktivieren prc1 = 0; // Protection Port 1 ausschalten pd1 = 0b01001110; // I/O-Richtungen festlegen int_lcd(); while(1) // Endlosschleife { int length_impulse = 0; // Zähler für Impulslänge int length_break = 0; // Zähler für Pausenlänge while(!DCF77_SIGNAL) // Zeit messen in der kein DCF77-Impuls anliegt { SIGNAL_LED = 0; delay_ms(1); length_break++; }; if (length_break > 500) // 59. Sekunde wird kein Impuls gesendet: Minutenbeginn, Zeit und Datum berechnen { calc_time_and_date(); second = 0; }; while(DCF77_SIGNAL) // Länge des DCF77-Impulses messen { SIGNAL_LED = 1; delay_ms(1); length_impulse++; }; display_time_and_date_on_lcd(); // Zeit und Datum auf LCD ausgeben if (length_impulse > 40) bit[second] = 1; // wenn DCF77-Impuls länger als 0,1 sec., entsprechendes Bit auf HIGH setzen, sonst LOW else bit[second] = 0; second++; if (second > 59) second = 0; // Sekundenzähler bei Erreichen von 58 sec. zurücksetzen }; }; //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- void init_externosci(void) { asm("FCLR I"); /* Enable interrupt */ prc0 = 1; /* Protect off */ cm13 = 1; /* Xin Xout */ cm15 = 1; /* XCIN-XCOUT drive capacity select bit : HIGH */ cm05 = 0; /* Xin on */ cm16 = 0; /* Main clock = No division mode */ cm17 = 0; cm06 = 0; /* CM16 and CM17 enable */ asm("nop"); /* Waiting for stable of oscillation */ asm("nop"); asm("nop"); asm("nop"); ocd2 = 0; /* Main clock change */ prc0 = 0; /* Protect on */ }; //---------------------------------------------------------------------------------------------------------------------- // Verzögerungsschleife void delay_ms(unsigned int millis) { int k,i; for (i = 0;i < 1000; i++) for (k = 0;k < millis; k++) asm("nop"); } //---------------------------------------------------------------------------------------------------------------------- // aus 60 Bits einer Minute die Zeit- und Datumswerte ermitteln void calc_time_and_date(void) { year = bit[50]*1 + bit[51]*2 + bit[52]*4 + bit[53]*8 + bit[54]*10 + bit[55]*20 + bit[56]*40 + bit[57]*80; month = bit[45]*1 + bit[46]*2 + bit[47]*4 + bit[48]*8 + bit[49]*10; day = bit[36]*1 + bit[37]*2 + bit[38]*4 + bit[39]*8 + bit[40]*10 + bit[41]*20; dayofweek = bit[42]*1 + bit[43]*2 + bit[44]*4; hour = bit[29]*1 + bit[30]*2 + bit[31]*4 + bit[32]*8 + bit[33]*10 + bit[34]*20; minute = bit[21]*1 + bit[22]*2 + bit[23]*4 + bit[24]*8 + bit[25]*10 + bit[26]*20 + bit[27]*40; }; //---------------------------------------------------------------------------------------------------------------------- // 8 Bits eines Bytes hintereinander an das LCD senden (SPI) void send_byte_to_lcd(char byte) { int i; for (i = 0; i < 8; i++) // Schleife für alle 8 Bits des übergebenen Bytes { CLK = 0; // Taktleitung auf LOW setzen SI = ((byte&128) != 0); // most significant bit (also das 8. Bit = 0b10000000 = 128) gesetzt? Wenn ja SI = 1, sonst SI = 0 byte <<= 1; // Alle 8 Bits des Bytes um eine Stelle nach links schieben. Most significant bit ist jetzt also das vormals 7. Bit CLK = 1; // Taktleitung auf HIGH setzen: Damit wird das gesendete Bit gültig }; }; //---------------------------------------------------------------------------------------------------------------------- // LCD nach Vorgaben im Datenblatt initialisieren void int_lcd(void) { RS = 0; // RS = LOW: Es folgen Kommandos send_byte_to_lcd(0x39); send_byte_to_lcd(0x1C); send_byte_to_lcd(0x52); send_byte_to_lcd(0x69); send_byte_to_lcd(0x74); send_byte_to_lcd(0x0C); send_byte_to_lcd(0x01); send_byte_to_lcd(0x06); send_byte_to_lcd(0x7F); delay_ms(5); }; //---------------------------------------------------------------------------------------------------------------------- // Alphanumerische Zeichen auf LCD ausgeben, Anzahl der Zeichen = 'size' // char* ist ein Zeiger auf das erste Element des Buchstaben-Feldes 'characters' // Der integrierte LCD-Kontroller ST7036 rückt den Cursor automatisch nach Empfang eines Bytes um eine Stelle weiter void display_chars_on_lcd(char* characters, int size) { int i; RS = 1; // RS = HIGH: Es folgen Daten for (i = 0; i < size;i++) // Alle Buchstaben 0 bis size-1 des Feldes an LCD senden send_byte_to_lcd(characters[i]); }; //---------------------------------------------------------------------------------------------------------------------- // Zweistellige Ganzzahlen auf LCD ausgeben // Zahlen 0 - 9 sind in Zeichensatztabelle ab Stelle 48, deswegen wird 48 addiert void display_digits_on_lcd(char digit) { RS = 1; // RS = HIGH: Es folgen Daten send_byte_to_lcd(digit / 10 + 48); // Zehnerstelle = Division durch 10 send_byte_to_lcd(digit % 10 + 48); // Einerstelle ('%' = Modulo, Rest einer Divsion durch 10) }; //---------------------------------------------------------------------------------------------------------------------- // Cursor auf bestimmte Spalte (0...15) und Reihe (0 oder 1) setzen // Der eingebaute LCD-Kontroller würde sonst erst beim Erreichen der 40. Spalte automatisch in die 2. Zeile springen void set_lcd_cursor_pos(char column, char row) { char addr; delay_ms(5); RS = 0; // RS = HIGH: Es folgen Kommandos addr = column + (row * 0x40); send_byte_to_lcd(addr | 0x80); delay_ms(5); }; //---------------------------------------------------------------------------------------------------------------------- // Datum in erster Zeile, Zeit in zweiter Zeile ausgeben void display_time_and_date_on_lcd(void) { // Datum AA., XX.XX.20XX set_lcd_cursor_pos(0, 0); switch(dayofweek) { case 1 : {display_chars_on_lcd("Mo., ", 5);break;}; case 2 : {display_chars_on_lcd("Di., ", 5);break;}; case 3 : {display_chars_on_lcd("Mi., ", 5);break;}; case 4 : {display_chars_on_lcd("Do., ", 5);break;}; case 5 : {display_chars_on_lcd("Fr., ", 5);break;}; case 6 : {display_chars_on_lcd("Sa., ", 5);break;}; case 7 : {display_chars_on_lcd("So., ", 5);break;}; default: {display_chars_on_lcd("??., ", 5);break;}; }; display_digits_on_lcd(day); display_chars_on_lcd(".", 1); display_digits_on_lcd(month); display_chars_on_lcd(".", 1); display_digits_on_lcd(20);display_digits_on_lcd(year); // Zeit XX:XX:XX set_lcd_cursor_pos(4, 1); display_digits_on_lcd(hour); display_chars_on_lcd(":", 1); display_digits_on_lcd(minute); display_chars_on_lcd(":", 1); display_digits_on_lcd(second); }; //----------------------------------------------------------------------------------------------------------------------