'Zutrittskontrolle 'Dupont Mike '2009-2010 ' **************************************************** ' *********** Konfigurationsteil ********************* ' ' Schnelligkeit, Prozessortyp und Baud Rate $regfile = "m32def.dat" $crystal = 3686400 $hwstack = 256 $swstack = 256 $framesize = 256 $baud = 9600 'Baudrate der UART: 9600 Baud ' Leider kann man diese Konstanten bei BASCOM nicht in die ' Config LCD aufnehmen, daher muss der Displaytyp zweimal eingestellt werden. Const Lcdrows = 2 Const Lcdcols = 16 ' Dies sind die Werte, die für die Tasten oben, unten, links und rechts ' in die Variable ' "Keypressed" geschrieben werden. Weitere Angaben zur Tastaturabfrage sind ganz ' unten. Const Keyup = 1 Const Keydown = 9 Const Keyright = 6 Const Keyleft = 4 ' Für die Texte des Menüs wird Speicherplatz verwendet, daher muss hier die ' maximale Anzahl Menüeinträge angegeben werden. Const Mnumaxlines = 10 ' Einstellungen zum Timer 1 'Timer wird gebraucht um eine Zeit von 15 Sekunden zu generieren, die dann 'durch eine Varable weiter gezählt wird und somit eine 5 Minuten Dauer erzeugt, 'die dazu dient einen Schlüssel nach einer mehrfachen falschen Passworteingabe 'für diese Zeit dauer zu blockieren Config Timer1 = Timer , Prescale = 256 'Kbd Befehl muss Konfiguriert werden Config Kbd = Porta , Debounce = 200 , Delay = 10 ' Erweiterte Einstellungen Config Portb.2 = Output Config Portb.3 = Input ' Einstellungen zum LCD Config Portc = Output Config Portd.7 = Output Config Portd.6 = Output Config Portd.5 = Output Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.3 , Rs = Portc.2 Config Lcd = 16 * 2 Cursor Off Noblink ' Einstellungen zum I2C_Bus (TWI) und der Echtzeituhr Ddrd = &HFE Ddrb.1 = 1 Config Sda = Portc.1 ' I2C Bus konfigurieren Config Scl = Portc.0 Const Ds1307w = &HD0 ' Addresse der Ds1307 Uhr Const Ds1307r = &HD1 Config Clock = User '' Interne Time/Date Routinen für Bascom konfigurieren Config Date = Dmy , Separator = . ' *********** Konfiguration Ende ********************* ' *********** Variablendeklarationen ***************** 'Diese Variable dient dazu !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Dim Zahl As Byte 'Diese Variable dient dazu sicher zu gehen,dass die Person nur einmal begrüsst 'wird und dass Fehlfunktionen aus kompensieret werden. Dim Only_one As Byte 'In dieser Textreihe wird zu Begrüsende Person gespeichert.Sie darf wegen 'Platzmangel jedoch maximal nur 10 Zeichen beanspruchen. Dim Person As String * 11 'In dieser Textreihe wird die Anrede gespeichert, d.h. Herr oder Frau, sollte 'jedoch ein nicht identifizierbarer Transpondercode erfasst werden dient die 'Textreihe zum Anzeigen eines Fehlers in Form von "ERROR". Dim Anrede As String * 5 ' Diese Textreihe beinhaltet den Text, der bei einem erkannten Schlüssel 'in der ersten Zeile stehen soll Dim Zeile1 As String * 16 'In dieser Textreihe befindet sich nach einer Datenverpackung der Komplette 'gelesene Transpondercode. Dim S As String * 11 'In dieser Variablen wird ein Wert gespeichert der Angibt ob der gelesene 'Tranpondercode identifiziert wurde oder ob es sich um einen Unbekannten Code 'handelt. Dim Exist As Byte ' In dieser Variable wird gespeichert, welcher Menüeintrag bzw. ' welcher Programmteil aktuell aktiv ist. Dieser Wert muss einmal ' gesetzt werden und kann zur Laufzeit zum Wechsel der Funktion ' beliebig verändert werden. Dim Mnuselect As Integer ' In dieser Variablen wird die aktuelle Anzahl der Menüeinträge ' gespeichert, damit man nicht unten aus dem Menü "herausscrollen" kann ' Diese Variable muss manuell gesetzt werden! Dim Mnuselectscount As Integer ' In dieser Variablen wird der mnuselect-Eintrag gespeichert, der ' angesprungen wird, wenn die "BACK"-Taste innerhalb eines Menüs gedrückt ' wurde. Dim Mnuselectback As Integer ' In dieser Variable wird gespeichert, auf welchem Menüeintrag der ' Cursor gerade steht. Dim Mnuselectpointer As Integer ' In diesen Variablen werden die Menuestrukturen hin und hergeschoben. ' Wenn ein Menü erstellt werden soll, wird der Text des Menüs in das ' Array Mnutext(x) geschrieben. Dim Mnutext(mnumaxlines) As String * Lcdcols ' In diesen Variablen wird die Programmnummer des Teils gespeichert, ' der angesprungen werden soll, wenn der Menüeintrag bestätigt wird. ' Beispeil folgt weiter unten. Dim Mnuselects(mnumaxlines) As Integer ' Einfach nur Variablen, die zum Anzeigen des Menüs gebraucht werden. ' Außerhalb des Menüs stehen diese Variablen zur freien Verfügung, werden ' allerdings von einer Menü-Erzeugung dann überschrieben. Wenn allerdings ' "nur kurz" ein Zähler gebraucht wird, können diese verwendet werden. Dim I As Integer Dim N As Integer Dim M As Integer ' In dieser Variablen wird der alte Menüwert gespeichert, um ' abzufragen, wann das Menue verlassen werden muss. Dim Mnuselectold As Integer ' In dieser Variablen wird die gedrückte Taste gespeichert. Dim Keycode As Integer ' Variable gibt die Zahl an die in den Timergeladen wird. Const Preset = 11536 'Zeit von 15 Sekunden ' Variable dient zum Hochzählen der 15 Sekunden Abstände Dim Zeitvariable As Word ' Diese Variabeln dienen dazu die verschiedenen Keycode auszuwerten Dim Asciichars As String * 16 Dim Taste As String * 1 ' Variable die das zu vergleichende Passwort angibt Dim Passwort As String * 4 ' Variable gibt die länge des eingegebenen Strings an. Dim Anzahl As Byte ' Variable gibt an , wieviele Fehlversuche bereits gemacht wurden Passwort Dim Versuche As Byte ' Variable gibt an ob das Passwort rischtig eingegeben wurde. Dim Passwort_stimmt As Byte ' String die die eingegebene Textreihe beinhaltet Dim Eingabe As String * 4 'Variable die den Keycode in einer Arabischen Ziffer angibt Dim Asciicode As Byte 'Diese Variabeln dienen zur Vorgabe der verschiedenen Passwörter Dim Passwortdupont As String * 4 Dim Passwortwillems As String * 4 Dim Passwortkrause As String * 4 'Variable gibt an ob ein Schlüssel gesperrt ist. Dim Schluessel_sperren As Byte 'Variable gibt an um welcher Schlüssel gelesen wurde. Dim Schluessel_nummer As Byte 'Variable die angibt wann ein schlüssel entsperrt wird. Dim Entsperren As Word '******************* Ende der Variablendeklarationen ********************** Passwort_stimmt = 0 ' Definition der verschiedenen Passwörter Passwortdupont = "1111" Passwortwillems = "2222" Passwortkrause = "3333" 'Displayzeit zum Initialisieren und Curser Optionen Waitms 300 Cursor Noblink Cursor Off ' Vielleicht ist die Vorgehensweise jetzt noch nicht ganz klar, wird es ' aber sicherlich gleich werden. Da das Hauptmenü üblicherweise zuerst ' angezeigt werden soll, wird der Wert mnuselect auf 0 (oder den Wert ' der Hauptmenüs) gesetzt Mnuselect = 0 'Zu beginn wird der Inhalt der Textreihe gelöscht somit können keine 'Fehlfunktionen auftreten. S = "" 'Zu beginn steht die Zeitvariable noch auf 0 Zeitvariable = 0 'der string erhält den gegebenen Wert, er dient nur zum herausfinden des 'Keycodes Asciichars = "123 456 789 *0# " 'Der PortB.2 (Ausgang) wird auf Low gesetzt. Dies dient zum erkennen des 'ersten Interrupts (da Softwearmässig immer Probleme) Portb.2 = 0 'Hier wird die Subroutine angegeben die im Falle eines Urxc (Serial recive) 'Interrupts angesprungen wird. On Urxc On_urxc 'Der USART,Rx complete Interrupt wird Freigeschaltet Enable Urxc 'Hier wird die Subroutine angegeben, die im Falle eines Timer 1 Interrupts 'angesprungen werden soll. On Timer1 Blockierung 'der Timer 1 interrupt wird erst gesperrt Disable Timer1 'Interrupts global einschalten. Enable Interrupts ' LCD Löschen Cls ' Nach diesen Einstellungen folgt nun der eigentliche Programmaufbau. ' ' Es soll nun folgendes Programm mit dieser Menüstruktur realisiert werden: ' In den Klammern steht der jeweilige Select-Case-Wert, der im Hauptprogramm ' benutzt wird ' ' Hauptmenü (0) ' | ' -- Settings (1)------- Backlight (11) --- ON (111) ' | | | ' | | - OFF (112) ' | - Delete Key (12) ' | ' | ' | ' -- Key + (2)----------- Key + (21) ' | | ' | - Reserve (22)---- Reserve1 (221) ' | | ' | - Reserve2 (222) ' | ' | ' -- Last IN (3) Do 'Endlosschleife Locate 1 , 8 : Lcd Date$ Locate 2 , 8 : Lcd Time$ Loop Do Only_one = 0 Select Case Mnuselect Case 0: ' Hauptmenü ' Die Variable gibt an, welche Funktion eine Ebene ' darüber liegt, das ist natürlich beim Hauptmenü ' ebenfalls das Hauptmenü Mnuselectback = 0 ' Dies sind die Texte und die entsprechenden ' mnuselect-Variable, die dann in der ' select-Case ausgeführt werden. Mnutext(1) = "Settings" Mnuselects(1) = 1 Mnutext(2) = "Key +" Mnuselects(2) = 2 Mnutext(3) = "Last IN" Mnuselects(3) = 3 ' Die Anzahl der Menüeinträge Mnuselectscount = 3 ' Aufruf des Menüs Gosub Mnushow Case 1: ' Untermenü "Einstellungen" ' Die Variable gibt an, welche Funktion eine Ebene ' darüber liegt. Mnuselectback = 0 ' Dies sind die Texte und die entsprechenden ' mnuselect-Variable, die dann in der ' select-Case ausgeführt werden. Mnutext(1) = "Backlight" Mnuselects(1) = 11 Mnutext(2) = "Delete Key" Mnuselects(2) = 12 ' Die Anzahl der Menüeinträge Mnuselectscount = 2 ' Aufruf des Menüs Gosub Mnushow Case 11: Mnutext(1) = "ON" Mnuselects(1) = 111 Mnutext(2) = "OFF" Mnuselects(2) = 112 ' Die Anzahl der Menüeinträge Mnuselectscount = 2 ' Aufruf des Menüs Gosub Mnushow Case 12: ' Programmteil "Delete Key" und Rücksprung Waitms 500 ' Danach wird wieder ins Menü gesprungen Mnuselect = 1 Case 111: 'Programmteil "ON" und Rücksprung Portd.6 = 1 Mnuselect = 11 Case 112: 'Programmteil "OFF" und Rücksprung Portd.6 = 0 Mnuselect = 11 Case 2: ' Menü "Key +" Mnuselectback = 0 Mnutext(1) = "Key +" Mnuselects(1) = 21 Mnutext(2) = "Reserve" Mnuselects(2) = 22 Mnuselectscount = 2 Gosub Mnushow Case 21: ' Programmteil "Key +" Waitms 500 ' Danach wird wieder ins Menü gesprungen Mnuselect = 2 Case 22: ' Menü "Reserve" Mnuselectback = 2 Mnutext(1) = "Reserve1" Mnuselects(1) = 221 Mnutext(2) = "Reserve2" Mnuselects(2) = 222 Mnuselectscount = 2 Gosub Mnushow Case 221: ' Programmteil "Reserve1" Waitms 500 Mnutext(1) = "Pussy" ' Danach wird wieder ins Menü gesprungen Mnuselect = 22 Case 222: ' Programmteil "Reserve2" Waitms 500 ' Danach wird wieder ins Menü gesprungen Mnuselect = 22 Case 3: ' Programmteil "Last IN" For Zahl = 1 To 10 Portd.7 = 1 Waitms 200 Portd.7 = 0 Waitms 200 Next Zahl ' Danach wird wieder ins Menü gesprungen Mnuselect = 0 Case Else: ' Falls der Mnuselec mal querläuft, wird wieder ins Waitms 500 ' Hauptmenü gesprungen. Mnuselect = 0 End Select Loop ' hier startet nun die anzeigeroutine fuer das Display Mnushow: ' Wenn dieser Punkt angesprungen wird, verlangt das System eine Eingabe. ' Alle weiteren Aktionen, sofern nicht durch Interrupts erzeugt, werden ' nicht weiter verarbeitet. ' Das alte Mnuselect wird gesichert Mnuselectold = Mnuselect ' Der Zeiger wird auf den ersten Menüeintrag gestellt. Mnuselectpointer = 1 ' So lange das Menue nicht geaendert wurde, wird dies immer fortgesetzt. While Mnuselectold = Mnuselect ' Zuerst einmal muss nun auf dem Display etwas angezeigt werden. ' Dies ist der Zaehler für die anzuzeigende Zeile M = 1 Cls ' Displayzeilen minus 1 N = Mnuselectpointer + Lcdrows Decr N ' Mehr als die verfuegbaren Menuepunkte können nicht angezeigt werden. If N > Mnuselectscount Then N = Mnuselectscount End If ' Anzeige der Zeilen For I = Mnuselectpointer To N Locate M , 1 If I = Mnuselectpointer Then Lcd ">" Else Lcd " " End If Lcd Mnutext(i) Incr M Next ' Solange keine Tastatureingabe erfolgt, wird die Tastatur gepollt Do Gosub Tstq Loop Until Keycode <> 16 ' hier werden nun die Menuetasten ausgewertet. ' Aktion Taste nach oben If Keycode = Keyup Then ' Nur wenn das Menü noch nicht oben ist. If Mnuselectpointer > 1 Then Decr Mnuselectpointer End If End If ' Aktion Taste nach unten If Keycode = Keydown Then ' Nur wenn das Menü noch nicht unten ist If Mnuselectpointer < Mnuselectscount Then Incr Mnuselectpointer End If End If ' Aktion Taste vor If Keycode = Keyright Then Mnuselect = Mnuselects(mnuselectpointer) End If ' Aktion Taste zurueck If Keycode = Keyleft Then Mnuselect = Mnuselectback End If Wend Cls ' Es wird wieder ins Hauptprogramm zurueck gesprungen. Return Tstq: '* Taste "1" = Keycode 0 '* Taste "2" = Keycode 1 '* Taste "3" = Keycode 2 '* Taste "4" = Keycode 4 '* Taste "5" = Keycode 5 '* Taste "6" = Keycode 6 '* Taste "7" = Keycode 8 '* Taste "8" = Keycode 9 '* Taste "9" = Keycode 10 '* Taste "*" = Keycode 12 '* Taste "0" = Keycode 13 '* Taste "#" = Keycode 14 '* keine Taste = Keycode 16 '**************************************** Keycode = Getkbd() If Keycode <> 16 Then Print Keycode Waitms 50 End If Return '************************************** '|--------------------Interrupt der seriellen Schnittstelle-------------------|' On_urxc: 'ASCII-Code einlesen Zahl = Inkey() If Zahl = 2 Then Else Return While Zahl <> 4 'While schleife so lange wie Zahl verschieden von 4 ist Zahl = Inkey() ' If Zahl <> 4 Then S = S + Chr(zahl) 'Nachkontrolle <> 4,wenn ja dann erhält S ein weiteres Zeichen Wend 'Ende der While schleife (endet wenn Zahl = 4) Only_one = Only_one + 1 'Gosub Anzeige '************************************** 'Anzeige: If Only_one <> 1 Then Return Schluessel_sperren = Schluessel_nummer Exist = 0 If S = "R029980AD46" Then 'Wenn die Zahlenreihe gleich "R029980AD46" ist, dann... Exist = 1 'wird eine Variable gesetzt, die angibt das der schlüsel existiert If Schluessel_sperren <> 1 Then 'schlüssel darf nicht gesperrt sein If Portd.5 = 0 Then 'nur zum test, da das mit den variabeln nicht geht Schluessel_nummer = 1 'schlüsselnummer angeben Zeile1 = "Willkommen " 'verschiedene Anzeigetexte Anrede = "Herr " Person = "Dupont " Passwort = Passwortdupont 'das passwort angeben Else Locate 1 , 1 Lcd "Gesperrt " 'noch was rein schreiben... während gewisser zeit gesperrt oder so !!!!!!!!!!!!!!!!!!!!!!!!!!! Wait 2 Return End If End If End If If S = "R83D9A08DD5" Then 'Wenn die Zahlenreihe gleich "R83D9A08DD5" ist, dann... Exist = 1 If Schluessel_sperren <> 2 Then Schluessel_nummer = 2 Zeile1 = "Willkommen " Anrede = "Frau " Person = "Willems " Passwort = Passwortwillems Else Locate 1 , 1 Lcd "Gesperrt " Wait 2 Return 'noch was rein schreiben... während gewisser zeit gesperrt oder so !!!!!!!!!!!!!!!!!!!!!!!!!!! End If End If If S = "R0A88A02DDB" Then 'Wenn Die Zahlenreihe gleich "R0A88A02DDB" ist, dann... Exist = 1 If Schluessel_sperren <> 3 Then Schluessel_nummer = 3 Zeile1 = "Willkommen " Anrede = "Herr " Person = "Krause " Passwort = Passwortkrause Else Locate 1 , 1 Lcd "Gesperrt " 'noch was rein schreiben... während gewisser zeit gesperrt oder so !!!!!!!!!!!!!!!!!!!!!!!!!!! Wait 2 Return End If End If If Exist = 0 Then If Portb.3 = 1 Then Zeile1 = "Fehler versuchen" Anrede = " Sie " Person = "erneut " Else Zeile1 = "Willkommen" Anrede = " Im " Person = "TI-ST.Vith " End If End If Cls 'Lösche LCD Anzeige Locate 1 , 1 'Setze LCD Cursor auf Position 1,1 Lcd Zeile1 'Schreibe den textinhalt von "Zeile1" auf die LCD Anzeige Locate 2 , 1 'Setze LCD Cursor auf Position 2,1 Lcd Anrede ; Person 'Schreibe die Jeweilige Anrede und den Name auf die Lcd-Anzeige Wait 3 'Warte 3 Sekunden Cls S = "" 'Inhalt der Textreihe (S) ist leer Portb.3 = 1 If Exist = 0 Then Return Locate 1 , 1 Lcd "Passwort Eingabe" Locate 2 , 7 Lcd "x=# / v=*" ' noch was einfallen lassen !!!!!!!!!!!!!!!!!!!!!!!! '_______________________________________________________________________________ Do Keycode = Getkbd() If Keycode <> 16 Then 'wenn eine Taste gedrückt wird geschieht folgendes Keycode = Keycode + 1 'könnte aich incr KEYCODE sein Taste = Mid(asciichars , Keycode , 1) ')somit wird der Keycode umgewandelt Asciicode = Inkey() ') If Taste = "#" Then 'wird die taste "#" gedrückt werden soll eine Ziffer im Passwort gelöscht werden Anzahl = Len(eingabe) If Anzahl < 2 Then ' ist die Anzahl kleiner als 2 , also 1 oder 0 Anzahl = 0 ' wird sie 0 Eingabe = "" 'Der string "Eingabe" wird gelöscht Else 'sollte die Zahl grösser oder gleich 2 sein, Anzahl = Anzahl - 1 'wird Anzahl um eins minimiert Eingabe = Left(eingabe , Anzahl) 'auch der string wird um ein Zichen minimiert End If Else 'sollte eine andere Taste gedrücht werden: If Len(eingabe) < 4 Then 'muss die gesamt länge unter 4 zeichen sein Eingabe = Eingabe + Chr(taste) 'dann wird eine Ziffer dran gehangen End If End If End If Locate 2 , 1 'der gesamte String wird angezeigt "zur Kontrolle" Lcd Eingabe ; " " Waitms 100 ' durch den Getadc Befehl müssen 100ms gewachtet werden If Len(eingabe) = 4 Then 'sollte der eingegebene Code dem vorgegebenen Password nicht entsprechen, dann If Taste = "*" Then Incr Versuche If Eingabe <> Passwort Then Passwort_stimmt = 0 Locate 2 , 10 'wird ein Nicht OK angezeigt Lcd "NOK" Wait 1 If Versuche >= 3 Then Schluessel_sperren = Schluessel_nummer Locate 2 , 1 Lcd "3 Versuche " '!!!!!!!!!!!!!!! 'nur zum Test hier kommt später ein Zeitvergleich und schlässel wird für eine gewisse Zeit gesperrt Wait 1 '!!!!!!!!!!!!!!!!!!!!!!!!!nur zur Anzeige... Enable Timer1 '???ovf1 Entsperren = Zeitvariable + 15 ' Variable die Minuten hochzählt + 15 !!!!!!!!! End If If Versuche >= 3 Then Versuche = 0 'somit erhält die erste if Versuche schleige ein end IF <<<<<< 1/0,125 = 8000 Überläufe pro Sekunde '--> 14745600 / Prescaler8 = 1843200 '--> 1/1843200 = 0,5425µs pro Takt '--> 125 / 0,5425µs = 230 !!!!!!!!!!!!!!!!!!!!!!!!!!! '--> Der Timer muss 230 mal Ticken für einen Überlauf '--> Timer0 = 255-230 = 25 Blockierung: Timer1 = Preset Zeitvariable = Zeitvariable + 1 If Zeitvariable = Entsperren Then Locate 1 , 1 : Lcd Zeitvariable ; "open" Wait 1 End If Toggle Portd.5 Return '********************************************************************** ' Unterprogramme für die Bascom Date/Time-Funktionen Dim Weekday As Byte Getdatetime: I2cstart I2cwbyte Ds1307w I2cwbyte 0 I2cstart I2cwbyte Ds1307r I2crbyte _sec , Ack I2crbyte _min , Ack I2crbyte _hour , Ack I2crbyte Weekday , Ack I2crbyte _day , Ack I2crbyte _month , Ack I2crbyte _year , Nack I2cstop _sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour) _day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year) Return Setdate: _day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year) I2cstart I2cwbyte Ds1307w I2cwbyte 4 I2cwbyte _day I2cwbyte _month I2cwbyte _year I2cstop Return Settime: _sec = Makebcd(_sec) : _min = Makebcd(_min) : _hour = Makebcd(_hour) I2cstart I2cwbyte Ds1307w I2cwbyte 0 I2cwbyte _sec I2cwbyte _min I2cwbyte _hour I2cstop Return