Hier sollen einige typische Beispielprogramme in CC-Basic vorgestellt werden, die sich z.T. aus Anfragen von Lesern ergeben haben. Die Listings sind hier einfach in den Text eingefügt. Man kann sie markieren und über die Zwischenablage direkt in CC-Basic kopieren.
1. Eine Funk-Uhr mit paralleler Ausgabe der Ziffern an Siebensegment-Decoder
Nach einer Idee von Hubert Eichler.
'************************************** ' C-Control/BASIC Parallel3.BAS ' ' Aufgabe: ' ' Ausgabe Minuten und Stunden ' im Parallelmodus, 4 Digits ''************************************** ' --- Definitionen -------------------- define Daten1 byteport[1] define Daten2 byteport[2] define Einer byte define Zehner byte ' --- Programmoperationen ------------- #Loop Einer = Hour mod 10 Zehner = Hour / 10 Daten1 = Zehner * 16 + Einer Einer = Minute mod 10 Zehner = Minute / 10 Daten2 = Zehner * 16 + Einer goto Loop end
Mit diesem Programm können über insgesamt 16 Leitungen nur vier Ziffern angesteuert werden. Wenn mehr gebraucht werden, kann man Zwischenspeicher 74HC573 (vgl. MSR mit CC-Basic S.148) verwenden. Das Verfahren ist hier für die ersten vier Ziffern gezeigt:
'************************************** ' C-Control/BASIC Parallel2.BAS ' ' Aufgabe: ' ' Ausgabe der Sekunden ' im Parallelmodus mit vier Latches ''************************************** ' --- Definitionen -------------------- define Datenbus byteport[1] define Latch1 port[9] define Latch2 port[10] define Latch3 port[11] define Latch4 port[12] define Ausgabe byte define Einer byte define Zehner byte ' --- Programmoperationen ------------- #Loop Einer = SECOND mod 10 Datenbus = Einer Pulse Latch1 Zehner = Second / 10 Datenbus = Zehner Pulse Latch2 Einer = Minute mod 10 Datenbus = Einer Pulse Latch3 Zehner = Minute / 10 Datenbus = Zehner Pulse Latch4 goto Loop
2. Motorsteuerung mit Stromüberwachung
Nach einer Idee von Norbert Götte
Zwei Motoren sollen mit vier Schaltern in zwei Richungen gesteuert werden. In der verwendeten Mechanik sollen Endschalter eingespart werden. Die Bewegung wird durch Anschläge begrenzt. Durch eine Stromüberwachung soll die Grenze erkannt und der Motor angehalten werden.
Als Basis dient das C-Control Experimenterboard von Modul-Bus (vgl. CC-Anwendungen). Motor 1 liegt zwischen den Leistungsausgängen 1 und 2, Motor 2 zwischen 3 und 4. Die Ausgänge sind gleichzeitig an die (im Board nícht verwendeten) Analogeingänge 5 bis 8 angeschlossen. Es wurde gemessen, dass die erhöhte Eingangsspannung von 12 V problemlos ist. Die Eingänge sind nicht durch Begrenzerdioden geschützt und können eine höhere Spannung vertragen. Außedem sind auf der Unit Schutzwiderstände von 10 k, die eine Überlastung sicher verhindern.
Ein Motor wird eingesschaltet, indem die eine Seite hochgelegt wird, die andere aber tief bleibt. Wegen des endlichen Innenwiderstands der Ausgangstreiber L272 ergibt sich an der Low-Seite eine Spannung von ca. 0,5 V. Bei steigender Belastung, also z.B. wenn der Motor gewaltsam angehalten wird, steigt die Soannung bis über 0, 8 V an. Man kann also hier indirekt den Strom durch den Motor messen und einen Grenzwert festlegen. Das Programm schaltet dann ab. Die Sperre soll bestehen bleiben, bis die entsprechende Taste freigegeben wird.
'************************************** ' ' C-Control/BASIC Motoren.BAS ' ' Aufgabe: ' ' - Zweikanal-Motorschalter mit Endabschaltung ' - bei Überstrom ' '************************************** ' --- Definitionen -------------------- define Motor1l port[1] define Motor1r port[2] define Motor2l port[3] define Motor2r port[4] define Motoren Byteport[1] define S1 port[9] define S2 port[10] define S3 port[11] define S4 port[12] define Last1l AD[5] define Last1r AD[6] define Last2l AD[7] define Last2r AD[8] define DA1 DA[1] define M1l bit[1] define M1r bit[2] define Ende1 bit[3] define Ende2 bit[4] ' --- Programmoperationen ------------- #Loop ' Motor1l = 1 'Einschalten ' pause 25 '0,5 s warten ' Motor1L = 0 'Ausschalten ' pause 25 '0,5 s warten gosub Tasten goto Loop 'Endlosschleife #Tasten if not (S1 or S2 or S3 or S4) then goto Ende if S1 then goto Taste1 if S2 then goto Taste2 if S3 then goto Taste3 if S4 then goto Taste4 #Ende Motoren = 0 Ende1=0 Ende2=0 goto Fertig #Taste1 if Ende1 then goto Fertig Ende1 = (Last1r > 75) if Ende1 then Motor1l=0 else Motor1l = 1 goto Fertig #Taste2 if Ende1 then goto Fertig Ende1 = (Last1l > 75) if Ende1 then Motor1r=0 else Motor1r = 1 goto Fertig #Taste3 if Ende2 then goto Fertig Ende2 = (Last2r > 75) if Ende1 then Motor2l=0 else Motor2l = 1 goto Fertig #Taste4 if Ende2 then goto Fertig Ende2 = (Last2l > 75) if Ende2 then Motor2r=0 else Motor2r = 1 goto Fertig #Fertig Pause 2 return end
Dieses Programm wurde zur Überprüfung eines speziellen Geräts an der Uni Hamburg benötigt. Außer den acht analogen Eingängen wird auch noch der Frequenzeingang und ein Zähler am IRQ-Eingang gezeigt. Zurm Ansehen der Ergebnisse braucht man ein Terminalprogramm mit 9600 Baud.
'************************************** ' ' C-Control/BASIC Analogtest.BAS ' ' Aufgabe: ' ' - Test aller Analogkanäle ' - Hintergrund-Zaehler mit ' - IRQ-Eingang ' - Gleichzeitige Frequenzmessung ' '************************************** ' --- Definitionen -------------------- define U1 AD[1] define U2 AD[2] define U3 AD[3] define U4 AD[4] define U5 AD[5] define U6 AD[6] define U7 AD[7] define U8 AD[8] define Zaehler Word ' --- Programmoperationen ------------- interrupt Impuls Zaehler = 0 #Loop print "K1", U1 Pause 10 print "K2", U2 Pause 10 print "K3", U3 Pause 10 print "K4", U4 Pause 10 print "K5", U5 Pause 10 print "K6", U6 Pause 10 print "K7", U7 Pause 10 print "K8", U8 Pause 10 print "Freq", Freq Pause 10 print "Interrupt", Zaehler Pause 200 goto Loop 'Endlosschleife #Impuls Zaehler = Zaehler + 1 print Zaehler return interrupt end
4. Messung der Genauigkeit der CC-Uhr und 2-MHz Taktsignal
Wie kann man auf die Schnelle mit einem Oszilloskop herausfinden, um wieviel zwei CC-Units in der Geschwindigkeit abweichen? Ganz einfach mit dem 25-Hz-Ausgang TCMP2 am Pin 1 des Prozessors. Die 25-Hz-Signale beider Systeme werden mit einem Zweikanal-Oszi verglichen. Dabei sieht man sehr schnell, wie stark sie aweichen.
Ein Beispiel: Es wurde eine Verscheibung von 2 ms in 35 s gemessen. Umgerechnet ergibt das einen Unterschied von 230 Hz bei 4 MHz oder 57 ppm oder 5 Sekunden am Tag. Zum Vergleich: Normale Quarze werden mit einer Abweichung von +/-50 ppm angegeben, also 200 Hz bei 4 MHz oder 4,3 s am Tag.
Ziel der Untersuchung war hauptsächlich herauszufinden, ob es Situationen gibt, in denen Timer-Interrupts nicht rechtzeitig bedient werden können, in denen also die Uhr Zeit verliert. Das 25-Hz-Signal wird ja in der Interruptroutine per Software gebildet. Daher kann man Abweichungen am Oszi gut sehen. Und in der Tat, zwei solche Situationen wurden gefunden:
Der letzte Punkt war der gesuchte Auslöser des Problems. Zum Stromsparen wurde der Sclowmode gewählt, zum Messen und zum Senden über die RS232 aber der normale Modus. Dadurch ging die Uhr nach.
Wenn man die Genauigkeit absolut messen will, kann man die Quarzfrequenz über einen Frequenzzähler messen. Aber Vorsicht, das Kabel zum Messgerät hat ja auch Kapazität und verstimmt den Oszillator. Ohne Fehler geht es, wenn man 2 MHz an einem Portpin misst. Der Prozessor hat eine spezielle Funktion, die halbe Quarzfrequenz am Port 11 auszugeben. Dazu braucht man nur ein kleines Programm:
'**************************************
'
' C-Control/BASIC ECLK.BAS
'
' Aufgabe:
'
' - Assemblercode im Varablenspeicher
' - Ausgabe von 2 MHz an Port 11
'
'**************************************
' --- Definitionen --------------------
define Data1 Byte '&A1
define Data2 Byte '$A2
define A3 Byte 'Platzhalter
define A4 Byte
define A5 Byte
define n Byte
' --- Programmoperationen -------------
A3 = &H16 'bset 3,7 ; ECLK
A4 = &H07
A5 = &H81 'rts
A3= &H16: sys &HA3 'Takt an
#Loop
goto Loop
end
Das Programm schaltet über ein kleines Maschinenprogramm das Bit ECLK
ein (siehe Datenblatt des Prozessors). Das besondere hier: Das Maschinenprogramm
befindet sich im RAM, und zwar im Variablenbereich! Diese Möglichkeit
habe ich in der CD "CC-Hardware-Erweiterungen"
verwendet, um Portzugriffe auf zusätzliche Anschlüsse zu realisieren.
Man kann auch selbst-modifizierende Programme schreiben, was im EEPROM
nicht geht. Dort wird damit das 2-MHz-Signal moduliert und als Testsender
verwendet.
5. Ein Codeschloss mit CC-Basic
Dieses Programm wurde von meinem Sohn Fabian (12 J.) benötigt, um sein Zimmer vor unberechtigten Gästen zu sichern. Es gab schon eine Lösung mit einer Relais-Schaltung, die aber noch verbessert werden musste. Jetzt hat die Anlage neben dem Tastenblock außen noch einen Freigabetaster innen und enen Magnetkontakt an der Tür.
Der Besucher muss einen Zugangscode eingeben, der aus drei Ziffern besteht. Nur mit der richtigen Kombination wird der Zugang freigegeben. Da ein elektrischer Türöffner nur schwer zu installieren ist, wird nur eine Alarmsirene gesteuert. Der Alarm ertönt, wenn entweder die Tür ohne Berechtigung geöffnet wird oder der falsche Code eingegeben wird.
Die Lösung mit C-Control verwendet neben dem Ziffernblock einen Magnetschalter, der an der Tür angebracht ist. Der Kontakt ist geschlossen, wenn die Tür zu ist. Zusätzlich ist an der Innenseite ein Tastschalter angebracht, mit dem von innen der Zugang freigegeben werden kann. Jemand könnte also von außen um Einlass bitten und ihn ohne Kenntnis des Zugangscodes erhalten. Außen am Ziffernblock gibt es noch zwei LEDs. Die rote LED signalisiert Stopp, die grüne den erlaubten Zugang.
Das Programm muss alle Kontakte überwachen. Es soll automatisch aktiv werden, wenn die Tür geschlossen ist. Falls jemand eine Ziffer drückt, wird die richtige Reihenfolge überwacht. Der Einfachheit halber wird hier mit Port 9 begonnen, danach folgt Port 10 usw. Die eigentliche Codierung wird durch den Anschluss der Tasten erreicht. Gleichzeitig muss das Programm zu jeder Zeit den Freigabetaster und den Türkontakt überwachen.
'************************************** ' ' C-Control/BASIC FabiALARM.BAS ' ' Aufgabe: ' ' - Alarmanlage fuer Tastenblock ' - LED rot: verboten, LED grün: erlaubt ' - Master-Freigabekontakt im Zimmer ' - Magnetschalter als Türkontakt ' '************************************** ' --- Definitionen -------------------- define E1 port [9] define E2 port [10] define E3 port [11] define E4 port [12] define E5 port [13] define E6 port [14] define E7 port [15] define E8 port [16] define Tasten byteport[2] define Sirene port [1] define Master port [2] 'Innenschalter: Master-Freigabe define Magnet port [3] 'Türkontakt, geschlossen, wenn Tür zu define Offen port [4] 'grüne LED: kannst reinkommen define Zu port [5] 'rote LED: bleib draußen! ' --- Programmoperationen ------------- Offen = 0 Zu = 1 'rote LED an Sirene = 0 #Loop 'warten, bis keine Taste gedrückt if Master = 0 then goto Auf if Tasten < 255 then goto Loop 'warten, bis eine Taste gerdrückt #T1 if Master = 0 then goto Auf if Magnet then goto Alarm if Tasten = 255 then goto T1 'Alarm wenn Taste 1 NICHT gedrückt if E1 then goto Alarm #N1 'warten, bis keine Taste gedrückt if Magnet then goto Alarm if Master = 0 then goto Auf if Tasten < 255 then goto N1 'warten, bis eine Taste gerdrückt #T2 if Master = 0 then goto Auf if Magnet then goto Alarm if Tasten = 255 then goto T2 'Alarm wenn Taste 1 NICHT gedrückt if E2 then goto Alarm #N2 'warten, bis keine Taste gedrückt if Magnet then goto Alarm if Master = 0 then goto Auf if Tasten < 255 then goto N2 'warten, bis eine Taste gerdrückt #T3 if Master = 0 then goto Auf if Magnet then goto Alarm if Tasten = 255 then goto T3 'Alarm wenn Taste 1 NICHT gedrückt if E3 then goto Alarm #N3 if Master = 0 then goto Auf 'warten, bis keine Taste gedrückt if Magnet then goto Alarm if Tasten < 255 then goto N3 #Auf Offen = 1 Zu = 0 #Tauf 'warten bis Tür geöffnet wird if Not (Magnet) then goto Tauf #Tzu 'warten bis Tür geschlossen wird if Magnet then goto Tzu Offen = 0 Zu = 1 goto Loop #Alarm Sirene = 1 pause 200 Sirene = 0 goto Loop
Das universelle Mess-und Steuerungsprogramm Compact wurde von Hans-Joachim Berndt verbessert und auch für das C-Control angepasst. Das Programm kann in der jeweils neuesten Version auf der Homepage des Autors geladen werden. Eine ausführliche Dokumentation, das Programm und das C-Control Experimentierboard findet man bei Modul-Bus.
Damit das Programm mit C-Control funktioniert, muss die Interface-Emulation CCIO geladen und gestartet werden. Das Programm CCIO.BAS ruft eigentlich nur das Maschinenprogramm CCIOS.S19 auf. Dieses stellt ein eigenes Betriebssystem für die CC-Unit als Interface dar. Damit kann eine PC-Software wie TurboCompact2000 direkt auf die Ports und die Analogeingänge zugreifen. Das Programm CCIO kann hier geladen werden (CCIO.ZIP, 1k). Es ist den Lesern des Buchs "C-Control-Anwendungen" bereits bekannt. Dort findet man nähere Hinweise zum Aufbau des Assemblerprogramms.
Das Basicprogramm CCIO.BAS legt vor dem Start des Interface-Betriebssystems den BytePort 1 als Ausgangsport fest und setzt alle Ausgänge auf Null. Das System ist nun festgelegt auf acht digitale Ausgänge, acht digitale Eingänge, zwei analoge Eingänge und zwei analoge Ausgänge. Eine Erweiterung des Programms mit mehr Eingängen und einer flexiblen Zuordnung der Ports findet man auf der CD "C-Control Hardware-Erweiterungen".
'**************************************
'
' C-Control/BASIC CCIO.BAS
'
' Aufgabe:
'
' - Interface-Emulation
' - Start des
' - Assembler-Unterprogramms
'
'**************************************
' --- Definitionen --------------------
define Ausgang Byteport[1]
' --- Programmoperationen -------------
Ausgang = 0
sys &H0101 'Aufruf bei $0101
end
syscode "CCIO.S19" 'Code laden
Bisher gab es schon den AT24C256 mit 32 KB für die CC-Unit. Inzwischen ist auch der doppelt so große AT24C512 zu bekommen (Lieferung z.B. über Modul-Bus). Diesen Baustein habe ich mit dem folgenden Programm in der CC-Unit getestet. Es wurden 60 K Daten in den Speicher geschrieben und wieder ausgelesen.. Das Ergebnis: Alles funktioniert problemlos. Von anderer Seite habe ich gehört, dass auch größere Programme (Spezielle DLL für den Compiler erforderlich) mit dem IC klarkommen.
'**************************************
'
' C-Control/BASIC EEPROM64.BAS
'
' Aufgabe:
'
' - Test eines EEPROM 24C512
' - 30000 Worte = 60 K schreiben/lesen
'
'**************************************
' --- Definitionen --------------------
define Ausgang port[1]
define n word
define data word
' --- Programmoperationen -------------
#Loop
Ausgang = 1 'Einschalten
pause 25 '0,5 s warten
Ausgang = 0 'Ausschalten
pause 25 '0,5 s warten
open# for write
for n= 1 to 30000
print# (100+n)
print (100+n)
next n
close#
Ausgang = 1 'Einschalten
pause 25 '0,5 s warten
Ausgang = 0 'Ausschalten
pause 25 '0,5 s warten
open# for read
for n=1 to 30000
input# data
print data
if data = 30000 then Ausgang = 1
next n
close#
end
Nachrag: Lange Programme in C-Control
Im Beispiel werden nur Daten, nicht aber Programme im neu hinzugekommenen Speicher abgelegt. Wenn man Programme mit einer Länge von mehr als 5900 Bytes schreiben will, erzeugt der CC-Basic Compiler eine Fehlermeldung. Man kann dies jedoch verhindern, indem man dem Compiler eine neue DLL unterschiebt, die das Verhalten in diesem Punkt verändert. Die DLL findet man z.B. hier:
http://www.idel-online.de/download.htm
RC5-Fernbedienungen für Fernseher und Videorecorder sind weit verbreitet. Deshalb liegt es nahe, sie auch für andere Zwecke einzusetzen. Aus der CD "C-Control Anwendungen" stammt das folgende Programm zur Steuerung von zwei Relais über die Tasten der Fernbedienung. Die Empfangssignale von einem SFH506 werden über Port 9 gelesen.
'************************************** ' ' C-Control/BASIC RC5_2.BAS ' ' Aufgabe: ' ' - RC5-Relaissteuerung, Adresse 0 ' - 2 Relais, 1,2 AN, 4,5 AUS ' '************************************** ' --- Definitionen -------------------- define Ctr byte 'Bytevar $0A1 define Kon byte 'Bytevar $0A2 define Adr byte 'Bytevar $0A3 define Tas byte 'Bytevar $0A4 Define Relais1 Port[1] Define Relais2 Port[2] ' --- Programmoperationen ------------- #loop sys &H0101 if Ctr < 100 then goto loop 'Lesefehler if Adr <> 0 then goto loop 'Nur Adr 5 if Tas = 1 then Relais1 = 1 if Tas = 2 then Relais2 = 1 if Tas = 4 then Relais1 = 0 if Tas = 5 then Relais2 = 0 if rxd then end goto loop end syscode "RC5.OBJ" 'Code laden
Das zugehörige Maschinenprogramm RC5.Obj findet man hier: CCRC5.Zip (4k)
Bernard Weiler schickte die folgende Berichtigung zum Assemblerprogramm DS1820.ASM aus der CD "C-Control Hardware-Erweiterungen":
; this code was fetched from the "C-control Hardware-Erweiterungen" book CDROM. ;I fixed some few bugs in assembler. port .equ $02 ; Port C portdir .equ $06 ; Datenrichtungsregister ds18s .equ 7 ; bit 7 ds18smask .equ $80 bas_1 .equ $b7 ; erste Basic Variable => Fehlerrückgabe bas_2 .equ $b8 ; zweite Basic Variable => Daten Rein&Raus .ORG $101 reset sei ;mask any intr, as they inject heavy jitter bclr ds18s,port ; port low bset ds18s,portdir; Port als Ausgang lda #$4b ; 4b 75 * 10 5sec => ~750 5sec jsr delay ; in Warteschleife springen bclr ds18s,portdir; Port high Z lda #$08 ; 8 * 10 5sec => ~80 5sec jsr delay ; warten auf PRESENCE-PULSE-DS1820 lda port and #ds18smask ; nur bit1, alle anderen maskieren bne error ; Fehler-Flag setzen lda #$2d ; erneut 45 * ~10 5sec => ~450 5sec jsr delay byte_send lda #$08 ; 08 Bits sta bas_1 bset ds18s,port bset ds18s,portdir byte_send_b bclr ds18s,port; Write 1 Slot ~5 5sec Port 1 Low clc ; clear Carry bit ror bas_2 ; in Carry schieben bcc write0 bcs write1 write0 bclr ds18s,port bra weiter write1 bset ds18s,port weiter lda #$07 ; 7 * ~10 => 70 5sec delay jsr delay bset ds18s,port dec bas_1 bne byte_send_b cli ;vor jedem rts ein cli nicht vergessen rts byte_read lda #$08 ; 08 Bits sta bas_1 lda #$00 sta bas_2 byte_read_b bset ds18s,port; first set value, then drive, not vice versa bset ds18s,portdir bclr ds18s,port bclr ds18s,portdir nop ; 14 5sec abwarten nop ; wenn ein hochkapazitives oder langes Kabel verwendet wird, haben die Dallas Probleme nop ; von 0 auf highZ in 14us zu kommen. Event muessesn dann mehr nops eingebaut werden. nop nop nop nop nop brset ds18s,port,rot ; Bit in C lesen rot ror bas_2 lda #$07 ; Gesamtzykluszeit abwarten (~60 5sec) jsr delay dec bas_1 bne byte_read_b bset ds18s,port bset ds18s,portdir cli rts delay ldx #$02 ; ca. 10 5sec delay inloop decx bne inloop deca bne delay rts error lda #$ff ; Ein Fehler => 255 speichern sta bas_1 cli rts .end
Und hier die passenden Basic-Programme dazu: Kapitel 7 des Handbuchs (ds1820cc.pdf, 38 KB)