C-Control Beispiele


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

3. Online-Messung an allen Analogeingängen

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.

   

















6. Interface-Emulation CCIO und das Anwenderprogramm TurboCompact2000

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".


7. Speichererweiterung auf 64 KB

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


8. RC5-Steuerung mit C-Control

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)


9. Ansteuerung des DS1820

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)