#define F_CPU 3686400 #include void lcdWrite(char* pText); void lcdGoto(int row, int col); //--------------------------------------------------------------------------------- // TWI-Funktionssammlung #ifndef TWI_CLOCK #define TWI_CLOCK 100000 // Geschwindigkeit des TWI-Busses #endif // TWCR - Control-Register-Bits #define _TWINT 0b10000000 #define _TWEA 0b01000000 #define _TWSTA 0b00100000 #define _TWSTO 0b00010000 #define _TWWC 0b00001000 #define _TWEN 0b00000100 #define _TWIE 0b00000001 uint8_t twiAdr = 0xD0; void twiInitMaster(uint8_t twiAdr); #include #include //------------------------------------------------------------------------ // twiInitMaster //------------------------------------------------------------------------ void twiInitMaster(uint8_t twiAdr) { // Clock TWBR=((F_CPU/TWI_CLOCK)-16)*2; // TWI-Status-Register (Vorteiler) TWSR=0; // Bus-Addr TWAR=twiAdr; // Enable TWCR=_TWINT|_TWEN; } //------------------------------------------------------------------------ // Start TWI (ohne Interrupt) //------------------------------------------------------------------------ void twiStart() { uint8_t x=TWCR; x&=_TWEN|_TWIE; // nur Beibehalten von Enable und InterruptJ/N TWCR=x|_TWINT|_TWSTA; // warten bis fertig while( !(TWCR & _TWINT)) {} } //------------------------------------------------------------------------ // Stopp TWI (ohne Interrupt) //------------------------------------------------------------------------ void twiStop() { uint8_t x=TWCR; x&=_TWEN|_TWIE; // nur Beibehalten von Enable und InterruptJ/N TWCR=x|_TWINT|_TWSTO; } //------------------------------------------------------------------------ // Write Byte per TWI (ohne Interrupt) // PE: data = zu sendende Daten // ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt //------------------------------------------------------------------------ void twiWriteByte(uint8_t data, uint8_t ackn) { TWDR=data; // Daten bereitlegen // Befehl zusammenstellen uint8_t x=TWCR; x&=_TWEN|_TWIE; //nur Beibehalten von Enable und InterruptJ/N x|=_TWINT; if(ackn) x|=_TWEA; // evt. TWEA setzen, für Datenanforderung TWCR=x; // senden // warten bis fertig while( !(TWCR & _TWINT)) {} } //------------------------------------------------------------------------ // Read Byte per TWI (ohne Interrupt) // PE: ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt // PA: Data //------------------------------------------------------------------------ int twiReadByte(uint8_t ackn) { // Befehl zusammenstellen uint8_t x=TWCR; x&=_TWEN|_TWIE; //nur Beibehalten von Enable und InterruptJ/N x|=_TWINT; if(ackn) x|=_TWEA; // evt. TWEA setzen, für Datenanforderung TWCR=x; // senden // warten bis fertig while( !(TWCR & _TWINT)) {} return TWDR; } //------------------------------------------------------------------------- // rtcGetRtcData //------------------------------------------------------------------------- uint8_t rtcGetRtcData(uint8_t Register) { // Adresse senden twiStart(); twiWriteByte(twiAdr,0); twiWriteByte(Register,1); // Daten lesen twiStart(); twiWriteByte(twiAdr+1,1); uint8_t b = (uint8_t)twiReadByte(0); twiStop(); return b; } //------------------------------------------------------------------------- // rtcGetSeconds //------------------------------------------------------------------------- uint8_t rtcGetSeconds() { return rtcGetRtcData(0) & 0x7F; } //------------------------------------------------------------------------- // rtcGetMinute //------------------------------------------------------------------------- uint8_t rtcGetMinute() { return rtcGetRtcData(1); } //------------------------------------------------------------------------- // rtcGetHour //------------------------------------------------------------------------- uint8_t rtcGetHour() { return rtcGetRtcData(2) & 0x3F; } //------------------------------------------------------------------------- // rtcSendBcdLcd //------------------------------------------------------------------------- void rtcSendBcdLcd(uint8_t zahl) { char buff[3]={0}; buff[0] = '0' + (zahl >> 4); buff[1] = '0' + (zahl & 0x0F); lcdWrite(buff); } //------------------------------------------------------------------------- // rtcWaitMs //------------------------------------------------------------------------- void rtcWaitMs(int miliSec) { _delay_loop_2( 1*(F_CPU/(1000/4)) * miliSec); // 4 Zyklen warteschleife } //------------------------------------------------------------------------- // rtcSendTimeLcd //------------------------------------------------------------------------- void rtcSendTimeLcd() { lcdGoto(1,1); rtcSendBcdLcd(rtcGetHour()); rtcWaitMs(20); lcdWrite(":"); rtcSendBcdLcd(rtcGetMinute()); rtcWaitMs(20); lcdWrite(":"); } //-------------------------------------------------------------------- // myWait_ms - Warte-Routine für x-Millisekunden (0-255) // ein Millisekundenzyklus dauert 1,052 ms // PE: Anzahl der zu wartenden Milisekunden //-------------------------------------------------------------------- void myWait_ms(uint8_t dauer_ms) { __asm__ volatile ( "myWait_ms_0%=:\n" "push %0\n" "ldi %0,1\n" "myWait_ms_3%=:\n" "push %0\n" "ldi %0,5\n" "myWait_ms_2%=:\n" "push %0\n" "ldi %0,255\n" "myWait_ms_1%=:\n" "dec %0 \n" "brne myWait_ms_1%=\n" "pop %0 ; Register wiederherstellen\n" "dec %0 \n" "brne myWait_ms_2%=\n" "pop %0 ; Register wiederherstellen\n" "dec %0 \n" "brne myWait_ms_3%=\n" "pop %0 ; Register wiederherstellen\n" "dec %0 \n" "brne myWait_ms_0%=\n" : :"d" (dauer_ms) ); } //--------------------------------------------------------------------------- void waitMs(int miliSec) { _delay_loop_2( 1*(F_CPU/(1000/4)) * miliSec); // 4 Zyklen warteschleife } ////////////////////////////////////////////////////////////////////////////// // LCD-Funktionen für myAVR-Board + myAVR-LCD // 4-BitModus an PortD Bit 4-7 // PortD Bit 2 = RS, high=Daten, low=Kommando // PortD Bit 3 = E, high-Impuls für gültige Daten //--------------------------------------------------------------------------- // lcdSend(..) - sendet ein Byte an LCD im 4-Bit-Modus // RS muss vorher richtig gesetzt sein // PE: data=zu sendendes Byte //--------------------------------------------------------------------------- void lcdSend(char data) { // aktuelles RS ermitteln char rs=PORTD; rs&=4; // High-Teil senden char tmp=data; tmp&=0xf0; tmp|=rs; PORTD=tmp; // Schreibsignal sbi(PORTD,3); cbi(PORTD,3); // Low-Teil senden tmp=data; tmp&=0x0f; tmp*=16; tmp|=rs; PORTD=tmp; // Schreibsignal sbi(PORTD,3); cbi(PORTD,3); // verarbeiten lassen waitMs(1); } //--------------------------------------------------------------------------- // lcdCmd(..) - sendet ein Kommando an LCD // PE: cmd=Kommando-Byte //--------------------------------------------------------------------------- void lcdCmd(char cmd) { cbi(PORTD,2); // RS löschen = Kommando lcdSend(cmd); // senden } //--------------------------------------------------------------------------- // lcd_write(..) - sendet ein Zeichen (Daten) an LCD // PE: text=Zeichen //--------------------------------------------------------------------------- void lcdWrite(char text) { sbi(PORTD,2); // RS setzen = Daten lcdSend(text); // senden } //--------------------------------------------------------------------------- // lcdWrite(..) - sendet eine Zeichenkette an LCD // Die Zeichenkette muss mit 0x00 abgeschlossen sein // PE: pText=Zeiger auf Zeichenkette //--------------------------------------------------------------------------- void lcdWrite(char* pText) { while(pText[0]!=0) { lcdWrite(pText[0]); pText++; } } //--------------------------------------------------------------------------- // lcdClear(..) - löscht die Anzeige im LCD //--------------------------------------------------------------------------- void lcdClear() { lcdCmd(0x01); waitMs(2); // warten } //--------------------------------------------------------------------------- // lcdOn(..) - schaltet das LCD an //--------------------------------------------------------------------------- void lcdOn() { lcdCmd(0x0E); } //--------------------------------------------------------------------------- void waitUs(int mikroSec) { _delay_loop_2( 1*(F_CPU/(1000000/4)) * mikroSec); // 4 Zyklen warteschleife } //--------------------------------------------------------------------------- // lcdInit(..) - Schaltet die Ports und Initialisiert das LCD //--------------------------------------------------------------------------- void lcdInit() { // Port D = Ausgang DDRD=0xff; PORTD=0; // warten bist LCD-Controller gebootet waitMs(50); // SOFT-RESET PORTD = 0x30; //0b00110000; sbi(PORTD,3); cbi(PORTD,3); waitMs(5); PORTD = 0x30; //0b00110000; sbi(PORTD,3); cbi(PORTD,3); waitUs(100); PORTD = 0x30; //0b00110000; sbi(PORTD,3); cbi(PORTD,3); waitMs(5); // 4-BitModus einschalten PORTD=0x20; // Schreibsignal sbi(PORTD,3); cbi(PORTD,3); waitMs(5); // ab hier im 4-Bit-Modus lcdCmd(0x28); // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit lcdCmd(0x06); // Entry Mode lcdOn(); lcdClear(); } //--------------------------------------------------------------------------- // lcdWrite(..) - sendet eine Zeichenkette an LCD // PE: pText=Zeiger auf Zeichenkette // count=Anzahl der zu sendenden Zeichen //--------------------------------------------------------------------------- void lcdWrite(char* pText, int count) { while(count!=0) { lcdWrite(pText[0]); pText++; count--; } } //---------------------------------------------------------------------- // Titel : C-Funktion Zeichenkette senden. //---------------------------------------------------------------------- // Funktion : ... // IN : char *buffer, Zeichenkette mit NUll abgeschlossen // OUT : ... //---------------------------------------------------------------------- void lcdString(char *buffer) { for (int i=0; buffer[i] !=0;i++) lcdWrite (buffer[i]); } //--------------------------------------------------------------------------- // lcdGoto(..) - setzt die Cursorposition // PE: row = Zeile 1..2 // col = Spalte 1..16 //--------------------------------------------------------------------------- void lcdGoto(int row, int col) { row--; // Null-basierend row&=0x01; // sicherheitshalber row*=0x40; // Zeile nach Bit 6 bringen col--; // Null-basierend col&=0x0f; // sicherheitshalber char tmp=row|col; tmp|=0x80; // Cursor setzen lcdCmd(tmp); // senden } //--------------------------------------------------------------------------- // lcdOff(..) - schaltet das LCD aus //--------------------------------------------------------------------------- void lcdOff() { lcdCmd(0x08); } //------------------------------------------------------------------------ // Initialisierungen //------------------------------------------------------------------------ void init() { lcdInit(); twiInitMaster(twiAdr); } ///////////////////////////////////////////////////////////////////////////// // Main-Funktion ///////////////////////////////////////////////////////////////////////////// main() { DDRB = 0xFF; // Ausgang PORTB = 0x00; // int alrm = 0; // 0 = kein Alarm | 1 = Alarm init(); // while (true) // Mainloop-Begin { if (alarm == 1) { sbi (PORTB,0);//Licht an / Ton an } else { rtcSendTimeLcd(); } } // Mainloop-Ende } //---------------------------------------------------------------------------