/************************************************************************************************************** * * PIC18F452 * * Lötkoffer (Dispenser) * * Autor : Finger * *************************************************************************************************************/ #include #include #include #include #include #include #include #define Buflen 60 #define TRUE 1 #define FALSE 0 // Konstanten und Bit-Deklarationen static bit LCD_RS @ ((unsigned)&PORTD*8+6); // LCD: Register select static bit LCD_EN @ ((unsigned)&PORTD*8+7); // Enable #define LCD_STROBE ((LCD_EN = 1),(LCD_EN = 1),(LCD_EN=0)) // LCD-Zweizeilen-Display #define XTAL_FREQ 4MHZ // Crystal frequency in MHz, in diesem Projekt völliger Quark. Muß erstmal so bleiben ! #define MHZ *1000 // number of kHz in a MHz #define DelayUs(x) { unsigned int _dcnt; \ _dcnt = (x)/(12MHZ/(XTAL_FREQ))|1; \ while(--_dcnt != 0) \ continue; } // IOs - sind ja wahrlich nicht viele.... #define TasterLinks RB0 #define TasterStop RB1 #define TasterRechts RB2 #define Fusspedal RB4 #define Magnetventil RB3 //-------- // Puffer //-------- char outpbuf [Buflen]; //------------- // Allgemeines //------------- int Oeffnungspause = 300; // Wie lange solls PFFFT machen? volatile unsigned long Timerticks = 0; int Zeitmessung = 0; //--------------------------------- // Konfiguration des Controllers //--------------------------------- __CONFIG(1, OSCEN & HS); // Quarz 20 Mhz __CONFIG(2, BORDIS & WDTDIS); // Kein Watchdog, kein BrownOut __CONFIG(4, LVPDIS & STVREN); // Kein LowVoltageProgramm, Reset bei StackOverflow /*************************************************************************************************************** * * Verzögern im Millisekundebereich * ***************************************************************************************************************/ void DelayMilli (unsigned char cnt) { unsigned char i; do { i = 4; do { DelayUs (1000); } while(--i); } while(--cnt); } /************************************************************************************************************** * * Ein Byte zum LCD schreiben im 4-Bit-Modus. * **************************************************************************************************************/ void lcd_write (unsigned char c) { PORTD = (PORTD & 0xF0) | (c >> 4); DelayUs (100); LCD_STROBE; DelayUs (100); PORTD = (PORTD & 0xF0) | (c & 0x0F); DelayUs (100); LCD_STROBE; DelayUs (100); } /************************************************************************************************************** * * Cursor ein/ausschalten * **************************************************************************************************************/ void lcd_cursor_on (char type) { LCD_RS = 0; // write control bytes if (type) lcd_write (0x0F); else // display on, blink curson on lcd_write (0x0C); // display on, blink curson off DelayMilli (20); } /************************************************************************************************************** * * LCD löschen und Cursor auf Null setzen * **************************************************************************************************************/ void lcd_clear (void) { LCD_RS = 0; lcd_write (0x1); DelayMilli (10); } /************************************************************************************************************** * * String auf LCD ausgeben * **************************************************************************************************************/ void lcd_puts (const char * s) { LCD_RS = 1; // write characters while(*s) lcd_write(*s++); } /************************************************************************************************************** * * Ein Zeichen auf dem Display ausgeben * **************************************************************************************************************/ void lcd_putch (char c) { LCD_RS = 1; // write characters PORTD = (PORTD & 0xF0) | (c >> 4); DelayUs(50); LCD_STROBE; DelayUs(50); PORTD = (PORTD & 0xF0) | (c & 0x0F); DelayUs (50); LCD_STROBE; DelayUs(50); } /************************************************************************************************************** * * Cursor positionieren * **************************************************************************************************************/ void lcd_goto (unsigned char pos) { LCD_RS = 0; lcd_write (0x80+pos); } /*************************** * * Positioniert den Cursor * (0,0) = Links oben * ***************************/ void lcd_cursorpos (char zeile, char spalte) { switch (zeile) { case 0 : { lcd_goto (spalte); break; } case 1 : { lcd_goto (0x40 + spalte); break; } } } /***************************************** * * Text an definierter Position ausgeben * *****************************************/ void lcd_print (char x, char y, const char * s) { lcd_cursorpos (y, x); if (y < 2) lcd_puts (s); } /************************************************************************************************************** * * LCD initialisieren * **************************************************************************************************************/ void lcd_init (void) { LCD_RS = 0; // write control bytes DelayMilli (20); // power on delay PORTD = 0x3; // attention! LCD_STROBE; DelayMilli (10); LCD_STROBE; DelayUs (100); LCD_STROBE; DelayMilli (10); PORTD = 0x2; // set 4 bit mode LCD_STROBE; DelayUs (80); lcd_write (0x28); // 4 bit mode, 1/16 duty, 5x8 font lcd_write (0x08); // display off lcd_write (0x0C); // display on, blink curson off lcd_write (0x06); // entry mode DelayMilli (20); } /************************ * * Systemticker erhöhen * ************************/ void Systemticker (void) { Timerticks++; } /************************ * * Systemticker auslesen * ************************/ unsigned long GetTicker (void) { return (Timerticks); } /************************************* * * Verzögern im Millisekundenbereich * *************************************/ void Delayms (unsigned int time) { volatile unsigned long tickertime; volatile unsigned int Count; Count = time / 5; tickertime = GetTicker (); while ( (tickertime + (unsigned long)Count) > GetTicker () ) CLRWDT (); } /***************** * * Timerroutine * *****************/ void isr_Timer1 (void) { //-------------------- // Timer 1 Überlauf ? //-------------------- if (TMR1IF) { //--------------- // Zeitsteuerung //--------------- Systemticker (); //------------------- // Ablauf alle 5 ms //------------------- TMR1H=0xE7; // n = 2^16 - t [s] * 625000 TMR1L=0x96; // Timer 1 neu vorladen (0xE796 = 5 ms) TMR1IF=0; // Clear Interrupt-Flag } // From Timer 1 Überlauf } /*************** * * Zentrale ISR * ***************/ void interrupt low_priority INTLOW_(void) { isr_Timer1 (); return; // Zurück zum Hauptprogramm } /*************************** * * Initialisierungsroutinen * ***************************/ void sysinit (void) { //-------------------- // IO-Ports klarmachen //-------------------- // Alle Ports initialisieren bzw. auf Null setzen PORTA = 0; PORTB = 0; PORTC = 1; PORTD = 0; PORTE = 0; // Ein- Ausgangsdefinitionen, 0 = Output / 1 Input, siehe Schaltplan TRISA = 0b11111111; // TRISB = 0b11110111; // TRISC = 0b10000000; // TRISD = 0b00000000; // Alle Ausgang TRISE = 0b00000000; // //-------------------------- // AD-Wandler-Einstellungen //-------------------------- ADCON0 = 0x00; ADCON1 = 0x07; //------------ // Timer-Init //------------ TMR1IE=1; // enable Interrupt of TMR1 T1CON=49; TMR1IP = 0; // Niedrige Priorität //-------------------- // Alle Interrupts an //-------------------- IPEN = 1; PEIE=1; // Peripherie Int=on GIE=1; // Define Interupts //----------------------------- // Glotzn uff du Arschkrampe ! //----------------------------- lcd_init (); lcd_clear (); //---------------------- // Begrüßungsbildschirm //---------------------- Delayms (100); strcpy (outpbuf,"Loetmoeller I\0"); lcd_print (0,0, outpbuf); Delayms (100); strcpy (outpbuf,"(C) Finger 2015\0"); lcd_print (0,1, outpbuf); Delayms (1000); lcd_clear (); //------------------------------ // Standard-Bildschirm erzeugen //------------------------------ sprintf (outpbuf, "T:%4d ms", Oeffnungspause); lcd_print (6,0, outpbuf); lcd_print (0,1, " "); } /************* * * Main * *************/ void main (void) { //---------------------- // System initialisieren //---------------------- sysinit (); //--------------- // Hauptschleife //--------------- while (1) { //------------------------- // Dosiervorgang einleiten //------------------------- if ( (!Fusspedal) && (TasterStop) ) { Delayms (20); if ( (!Fusspedal) && (TasterStop) ) { // Delayms (50); // Kurze Pause while (!Fusspedal) { Delayms (50); // Warten, bis wieder losgelassen } Magnetventil = 1; // Aufmachen Delayms ((int)((float)Oeffnungspause * (float)0.457317)); // Geforderte Zeit warten Magnetventil = 0; // Zumachen Delayms (100); // Kurze Pause } } //----------------------------------------------------------------------- // Daueröffnung bei gleichzeitigem Fußpedal und Stop-Taster (Spritz...) //----------------------------------------------------------------------- // if ( (!TasterStop) && (!Fusspedal) ) Magnetventil = 1; else Magnetventil = 0; // Magnetventil = Fusspedal; #define Drueckpause 30 #define PausenMin 50 #define PausenMax 1500 #define Pausenschritt 10 #define PausenAenderungsPause 50 //----------------------- // Zeit verstellen Minus //----------------------- if (!TasterLinks) // Minus gedrückt? { Delayms (50); Zeitmessung = 0; // Messen, ob eine Zeit lang gedrückt wurde... while ( (!TasterLinks) && (Zeitmessung < Drueckpause) ) { Zeitmessung++; Delayms (10); } // Ist die Maximalzeit abgelaufen? if ( (Zeitmessung == Drueckpause) && (!TasterLinks) ) { // Taster wird dauernd gedrückt while (!TasterLinks) { if (Oeffnungspause >= (PausenMin + Pausenschritt)) Oeffnungspause -= Pausenschritt; sprintf (outpbuf, "T:%4d ms ", Oeffnungspause); lcd_print (6,0, outpbuf); Delayms (PausenAenderungsPause); } // Von while (!TasterLinks) } else // Taster wurde innerhalb der Zeit wieder losgelassen, nur um 1 erniedrigen { if (Oeffnungspause >= (PausenMin + Pausenschritt)) Oeffnungspause -= Pausenschritt; sprintf (outpbuf, "T:%4d ms ", Oeffnungspause); lcd_print (6,0, outpbuf); } // von else if ( (Zeitmessung == 50) && (!TasterLinks) ) } // Von if (!TasterLinks) // Minus gedrückt? //----------------------- // Zeit verstellen Plus //----------------------- if (!TasterRechts) // Minus gedrückt? { Delayms (50); Zeitmessung = 0; // Messen, ob eine Zeit lang gedrückt wurde... while ( (!TasterRechts) && (Zeitmessung < Drueckpause) ) { Zeitmessung++; Delayms (10); } // Ist die Maximalzeit abgelaufen? if ( (Zeitmessung == Drueckpause) && (!TasterRechts) ) { // Taster wird dauernd gedrückt while (!TasterRechts) { if (Oeffnungspause <= (PausenMax - Pausenschritt)) Oeffnungspause += Pausenschritt; sprintf (outpbuf, "T:%4d ms ", Oeffnungspause); lcd_print (6,0, outpbuf); Delayms (PausenAenderungsPause); } // Von while (!TasterRechts) } else // Taster wurde innerhalb der Zeit wieder losgelassen, nur um 1 erniedrigen { if (Oeffnungspause <= (PausenMax - Pausenschritt)) Oeffnungspause += Pausenschritt; sprintf (outpbuf, "T:%4d ms ", Oeffnungspause); lcd_print (6,0, outpbuf); } // von else if ( (Zeitmessung == 50) && (!TasterRechts) ) } // Von if (!TasterRechts) // Minus gedrückt? //-------------------------------------------------------------------- // //-------------------------------------------------------------------- } // Von while (1) } // That´s all folks !