Real Time Clock IC an AVR

Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte

Elektronik Forum Nicht eingeloggt       Einloggen       Registrieren




[Registrieren]      --     [FAQ]      --     [ Einen Link auf Ihrer Homepage zum Forum]      --     [ Themen kostenlos per RSS in ihre Homepage einbauen]      --     [Einloggen]

Suchen


Serverzeit: 29 11 2024  14:19:43      TV   VCR Aufnahme   TFT   CRT-Monitor   Netzteile   LED-FAQ   Osziloskop-Schirmbilder            


Elektronik- und Elektroforum Forum Index   >>   Microcontroller        Microcontroller : Hardware - Software - Ideen - Projekte


Autor
Real Time Clock IC an AVR

    







BID = 573361

Tim Taylor

Schriftsteller



Beiträge: 617
Wohnort: Seefeld / Hechendorf
 

  


Ein fröhliches, vorweihnachtliches Hallo an Alle!

Ich versuche , aus reinem Spass an der Freude, AVRs in Assembler zu programmieren. Also deklariere ich generell mich als Anfänger!

Lauflichter, (interne)Timer, LCD Ansteurerung, etc. klappen zwar nicht immer auf Anhieb, aber mit genügend "Hirnschmalz" geht es dann doch!

Nun möchte ich mal die Kommunikaton zwischen zwei Bausteinen austesten und auch verstehen.

Als neues Bastelundverstehprojekt erdachte ich mir eine Uhr.

Es soll ein ATmega16, zweizeiliges Display und eine externe RTC zum Einsatz kommen.

Nun ist meine Frage, welche RTC (von den vielen erhältlichen) auch bei Re.....t oder so günstig zu erwerben ist, und ob Jemand bei evtl. Verständnisproblemen meinerseits, bereit ist, mir unter die Arme zu greifen. Auch Links zu diesem Thema sind willkommen.
Am liebsten wäre mir eine serielle Verbindung zwischen RTC und AVR (an I2C traue ich mich noch nicht heran).
Ralfi


_________________
Echte Männer essen keinen Honig. Sie kauen Bienen.

Geht nicht gibts nicht- es sei denn, es geht nicht!!

[ Diese Nachricht wurde geändert von: Tim Taylor am 19 Dez 2008 18:19 ]

BID = 573384

Her Masters Voice

Inventar


Avatar auf
fremdem Server !
Hochladen oder
per Mail an Admin

Beiträge: 5308
Wohnort: irgendwo südlich von Berlin

 

  

I2C ist aber sowas von seriell...

Guck mal im Mikrocontroller.net vorbei. Da wurde schon viel mit RTCs gemacht.

_________________
Tschüüüüüüüs

Her Masters Voice
aka
Frank

***********************************
Der optimale Arbeitspunkt stellt sich bei minimaler Rauchentwicklung ein...
***********************************

BID = 573385

Ltof

Inventar



Beiträge: 9334
Wohnort: Hommingberg

Hmm - ich musste gerade eine RTC für eine Hardware aussuchen. Eine mit sowas wie RS232 (das meintest Du vermutlich) ist mir nicht begegnet. Die waren alle mit I2C.

Aber mal eine Frage zu den AVRs: gibt es keine, die eine RTC an Bord haben? Bei PICs gibt es das. Manche PICs haben zwei getrennte Oszillatoren. Einen für den µC-Kern und einen für die Uhr, der besonders sparsam ist und auch weiter läuft, wenn der Rest schläft.

Gruß,
Ltof

_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)

[ Diese Nachricht wurde geändert von: Ltof am 19 Dez 2008 20:07 ]

BID = 573388

Ralph

Stammposter


Avatar auf
fremdem Server !
Hochladen oder
per Mail an Admin

Beiträge: 200
Wohnort: Fürth

Servus Ralfi,
naja also ich kenne I2C und auch SPI. Wenn ich grad net völlig verkehrt liege, dann gibts auch welche mit beiden Schnittstellen.
Der Konfigurationsaufwand dürfte für beide Lösungen wohl ähnlich sein. Für SPI brauchste halt mindestens 1 Leitung mehr: Clock (SCK), DataIn (MISO), DataOut (MOSI) und /Enable. Bei I2C haste ja nur CLock und Data. (Masse ist eh klar)
Also denn, viel Erfolg bei Deinen Tests und Aufbauten!

mal wieder, live ist ja schon etwas her...

Viele Grüße,
Ralph

BID = 573536

Tim Taylor

Schriftsteller



Beiträge: 617
Wohnort: Seefeld / Hechendorf

Hallo Ralph,

schön von Dir zu hören.

Habe mir gleich mal ein Fässchen aufgemacht.
Prösterchen HiHi


Ja, mit der seriellen Schnittstelle meinte ich RS232.

So wie es aussieht, werde ich ein paar Sonderschichten einlegen und mir das I2C Protokoll in die Denkmurmel einbrennen.
Wozu so ein Weihnachtsurlaub alles gut ist

Bei Schwierigkeiten hoffe ich auf Eure tatkräftige Untersützung

Ralfi

_________________
Echte Männer essen keinen Honig. Sie kauen Bienen.

Geht nicht gibts nicht- es sei denn, es geht nicht!!

[ Diese Nachricht wurde geändert von: Tim Taylor am 20 Dez 2008 17:09 ]

BID = 573539

Her Masters Voice

Inventar


Avatar auf
fremdem Server !
Hochladen oder
per Mail an Admin

Beiträge: 5308
Wohnort: irgendwo südlich von Berlin

mit RS232 würde mir höchstens ein DCF77 Modul einfallen. ISt aber auch ne hübsche Programmierübung sowas zum rennen zu kriegen.

_________________
Tschüüüüüüüs

Her Masters Voice
aka
Frank

***********************************
Der optimale Arbeitspunkt stellt sich bei minimaler Rauchentwicklung ein...
***********************************

BID = 573881

high_speed

Schreibmaschine



Beiträge: 2073

Hallo Ralfi,

einen Software-I2C-Master zu schreiben ist nicht besonders aufwendig.

Der ATmega16 besitzt auch eine TWI-Schnittstelle, das ist nichts anderes
als I2C. Jetzt musst du nur noch die TWI richtig füttern.

http://www.avrfreaks.net/index.php?.....id=56

Ich hatte mal mit dem PCF8583 experimentiert, ist aber schon länger her.
Als externe Beschaltung braucht der noch einen Uhrenquarz 32,768kHz
und für den Quarz noch eine "Last" von 10pF, die besser als Trimmer
ausgeführt werden sollte, so dass die Frequenz noch justiert werden kann.

Ansonsten würde ich mal bei Maxim / Dallas Semiconductor vorbeischauen.
http://datasheets.maxim-ic.com/en/ds/DS3231.pdf

Die haben in dem Bereich interessante Sachen.

Wenn man nett fragt, bekommt man bestimmt auch ein paar Muster.



Hallo Ltof

was wird es denn?
Ist es mehr ein Genauigkeitsproblem oder müssen sie besonders billig
sein? Am besten wohl beides, wie immer.

MfG
Holger

_________________
George Orwell 1984 ist nichts gegen heute.
Der Überwachungsstaat ist schon da!

Leider lernen die Menschen nicht aus der Geschichte,
ansonsten würde sie sich nicht andauernd wiederholen.

BID = 573932

Nukeman

Schriftsteller



Beiträge: 754
Wohnort: bei Kleve

Hi Tim!

z.B. der ATMEGA32 hat schon eine RTC auf Timer2 mit separatem Quarz vorgesehen, wie
Ltof es schon angesprochen hat.
Dann bleibt aber das Problem, dass man die Uhrzeit nach jedem Reset manuell
wieder einstellen muss.

Momentan baue ich einen "Mülltonnen-Rausbring-Warner", wo ein DCF77-Modul eingesetzt
wird. Ich denke, das ist universeller einsetzbar als eine echte RTC und man braucht
eigentlich nur einen ~10-20ms Interrupt, um das DCF-Signal erfolgreich zu dekodieren.

Vielleicht ist das auch ein bisschen am Problem vorbei ( Inter-IC-Kommunikation ),
weil die einfachen DCF77-Module kein I2C oder SPI sprechen. Trotzdem ist das etwas,
was man immer wieder einsetzen kann.

Gruß
Stefan

BID = 573936

Ltof

Inventar



Beiträge: 9334
Wohnort: Hommingberg


Zitat :
high_speed hat am 21 Dez 2008 23:29 geschrieben :

was wird es denn?

Ein Mädchen? Ein Junge?
Nein - ich stricke gerade eine Interfacekarte beim Kunden.

Zitat :

Ist es mehr ein Genauigkeitsproblem oder müssen sie besonders billig
sein? Am besten wohl beides, wie immer.

Genau! Und als dritte Forderung: möglichst wenige neue Bauteile einführen und mit dem vorhandenen Fundus auskommen.

Alle diese Forderungen erfüllte zufällig die DS3231.

_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)

BID = 574695

selfman

Schreibmaschine



Beiträge: 1681
Wohnort: Seekirchen a. W.

Eine Software-I2C-Routine (für Controller die keine eingebaute Hardwareschnittelle haben) könnte ich anbieten. Belegt temporär zwei Portpins, solange die Übertagung läuft. Dazwischen können sie als I/O pins verwendet werden, die anliegenden Schaltung muß aber die kurzen "Störungen" verkraften.

Ist aber für PIC Prozessoren. Der AVR Assembler ist mir nicht geläufig, müsste also einer übersetzten.

Schöne Grüße Selfman

_________________
Traue keinem Ding, das du nicht selber vermurkst hast.

BID = 574699

Ltof

Inventar



Beiträge: 9334
Wohnort: Hommingberg

Moin Selfman,

dann lass mal sehen! Die Routine hätte ich gerne. Nicht für meine aktuelle Arbeit, sondern prinzipiell für meine Basteleien. Angeregt durch die Hardwareentwicklung hat sich ein Interesse für die I2C-Geschichte entwickelt.

Gruß,
Ltof

_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)

BID = 574708

selfman

Schreibmaschine



Beiträge: 1681
Wohnort: Seekirchen a. W.

So hier ist gleich das ganze Programm. Das deswegen, weil ohne die Equates die ganzen Operationen unverständlichen wären. Die I2C Routinen sind nur die zwei kleinen Teile nach der Interruptroutine. Der Rest ist eine kleine Steuerung für eine Gabelstapler an dem ein paar Funktionen gegeneinander verriegelt werden mußten. Außerdem sind noch ein paar Spielereien wir Blinklicht und Stundenzähler mit dabei (der leider aber nur im seriellen EEPROM steht und nicht ausgelesen werden kann ). Das Projekt war leider zu früh zu Ende!

Aber ansonsten kann ein Anfänger viele Sachen darin finden, neben der I2C Kommunikation ist eine einfache Interruptbehandlung für einen Timerinterrupt und die ADC-Abfrage vorhanden, genauso wie die in diesem Thread schon angesprochenene Zeitverzögerungen oder weiter unten dann ganz normale Bitverknüpfungen.


Code :

;*******************************************************************************************************;

; Programm CRAYLER1.asm: Serielle Porterweiterung mit PCF 8574, Erweiterung 1 dient als Eingang, ;
; die Ports der Erweiterung 2 koennen wahlweise einzeln als Ein- oder Ausgaenge verwendet werden. ;
; Port RA0 - RA2 werden als Analogeingaenge initialisiert, mit RA3 als Referenzspannung, ;
; RA4 dient als Eingang (RTCC). Port RB0 - RB7 werden als Ausgaenge initialisiert und bedienen die ;
; Relaisausgaenge, wobei RB6/RB7 gleichzeitig als I2C-Bus verwendet werden. PIC 16C71, f = 4 MHz ;
;*******************************************************************************************************;

; Zuordnungen:
; Register, Seite 0

RTCC equ 001 ; Realtime Clock/Counter Register
STATUS equ 003 ; Statusregister
PORTA equ 005 ; Datenregister Port A
PORTB equ 006 ; Datenregister Port B
ADCON0 equ 008 ; Konfigurationsregister 0 fuer Analogeingaenge
ADRES equ 009 ; Ergebnisregister der Analogeingaenge
INTCON equ 00B ; Interruptkonfigurationsregister

; Register, Seite 1

OPT equ 001 ; Optionregister
TRISA equ 005 ; Tristate-Register A
TRISB equ 006 ; Tristate-Register B
ADCON1 equ 008 ; Konfigurationsregister 1 fuer Analogeingaenge

; Register im allgemeinen RAM

DATEIN equ 00C ; Register fuer serielle Byte-Eingabe
INPUT1 equ 00D ; Register 1 Eingaenge
INPUT2 equ 00E ; Register 2 Eingaenge
U_SIGNAL1 equ 00F ; Danfoss Signalspannung heben/senken
U_SIGNAL2 equ 010 ; Danfoss Signalspannung vor/zurueck_links/rechts
U_SIGNAL3 equ 011 ; Danfoss Signalspannung legen/aufstellen
BIT equ 012 ; Bit-Zaehler fuer serielle Ein- und Ausgabe
DELAY equ 013 ; Zaehlregister fuer Verzoegerung Blinkausgang
PRESCAL equ 014 ; Vorteiler fuer Betriebsstundenzaehler
MINUTE equ 015 ; Zaehlregister fuer Minuten
HOUR1 equ 016 ; Zaehlregister Low-Byte fuer Stunden
HOUR2 equ 017 ; Zaehlregister High-Byte fuer Stunden
STACK_W equ 018 ; Stackregister fuer W-Register
STACK_ST equ 019 ; Stackregister fuer Status-Register
ADW_CH equ 01A ; Analogkanal-Auswahl
VKE equ 01B ; Zwischenspeicher fuer Verknuepfungen
MERKER equ 01C ; Merkerbyte fuer Bitmerker
DATAUS equ 01D ; Register fuer serielle Byte-Ausgabe
RELAIS equ 01E ; Ausgangspuffer fuer Relaisausgaenge

; Bits in Registern - Spezialregister
; Statusregister
carry equ 000 ; Carrybit in Statusregister
zero equ 002 ; Zerobit in Statusregister
rp0 equ 005 ; Seitenauswahlbit in Statusregister
; Interruptkontrollregister
t0if equ 02 ; RTCC Interrupt
gie equ 007 ; Freigabe Interrupts
; ADW-Kontrollregister
go_done equ 002 ; AD-Wandler Start/Fertig
chs0 equ 003 ; AD-Wandler Kanalauswahlbit 0
chs1 equ 004 ; AD-Wandler Kanalauswahlbit 1

; Bits in Registern - Allgemeinregister
; I2C-Register
b_out equ 007 ; Ausgangsbit bei Schiebeoparation
b_in equ 007 ; Eingangsbit bei Schiebeoparation
sda equ 007 ; RB,7 Datenleitung SDA
scl equ 006 ; RB,6 Taktleitung SCL
; INPUT1 (Digitaleingaenge)
schub_trsp equ 000 ; Endschalter Mastausschub Transportposition
turm_steht equ 001 ; Endschalter Turm steht
gabel_u equ 002 ; Endschalter Gabel unten
arb_legen equ 003 ; Schalter Arbeiten/Zusammenlegen
slct_stuetze equ 004 ; Auswahl mit/ohne Stuetzen
signal_act equ 005 ; Bewegungsfunktion aktiv
motor_on equ 006 ; Eingang Motor Betrieb
stoerung equ 007 ; Eingang Stoerung
; INPUT2 (Digitaleingaenge)
schub_vrn equ 000 ; Endschalter Mastausschub vorne
s_schub_l equ 001 ; Endschalter Seitenschub links
s_schub_r equ 002 ; Endschalter Seitenschub rechts
m_s_schub equ 003 ; Schalter Mast/Seitenschub
; VKE (Verknuepfungsergebnisse)
vke0 equ 000 ; Verknuepfungsergebnis-Bit 0
vke1 equ 001 ; Verknuepfungsergebnis-Bit 1
vke2 equ 002 ; Verknuepfungsergebnis-Bit 2
; Merker (Bitmerker)
en_m_schub equ 000 ; Bitmerker Mastschub freigegeben
en_s_schub equ 001 ; Bitmerker Seitenschub freigegeben
act_m_schub equ 002 ; Bitmerker Mastschub aktiv
act_s_schub equ 003 ; Bitmerker Seitenschub aktiv
movto_m_schub equ 004 ; Bitmerker Bewegung fuer Position Mastschub freigegeben
movto_s_schub equ 005 ; Bitmerker Bewegung fuer Position Seitenschub freigegeben
i2c_err equ 006 ; Bitmerker Uebertragungsfehler I2C-Bus
; PORTB (Relaisausgaenge)
heben equ 000 ; Ausgang Hebenfunktion
schieben equ 001 ; Ausgang Mastschub/Seitenschubfunktion
legen equ 002 ; Ausgang Legen/Stuetzenfunktion
stuetze equ 003 ; Ausgang Umschaltventil Abstuetzung
s_schub equ 004 ; Ausgang Umschaltventil Seitenschub

; Konstanten
PCF1W equ 040 ; Bauteil-Adresse: 40h fuer Schreiben in PCF1 8574
PCF1R equ 041 ; Bauteil-Adresse: 41h fuer Lesen aus PCF1 8574
PCF2W equ 042 ; Bauteil-Adresse: 42h fuer Schreiben in PCF2 8574
PCF2R equ 043 ; Bauteil-Adresse: 43h fuer Lesen aus PCF2 8574
EEW equ 0A0 ; Bauteil-Adresse: A0h fuer Schreiben in EEPROM 24LC04 (Page 0)
EER equ 0A1 ; Bauteil-Adresse: A1h fuer Lesen aus EEPROM 24LC04 (Page 0)

; Ziele der Registeroperationen
w equ 000
f equ 001

;*******************************************************************************************************;
; Programmbegin ;
;*******************************************************************************************************;

org 000

nop ; Resetadresse bei 00h
nop ;
nop ;
goto init ; Sprung zum Programmanfang

;*******************************************************************************************************;
; Interruptprogramm ;
;*******************************************************************************************************;

movwf STACK_W ; W-Register retten
movf STATUS,w ; Statusregister in W
movwf STACK_ST ; Statusregister retten
btfss INTCON,t0if ; Abfrage ob Timer Interrupt
goto adw_int ; Nein, ADW-Interrupt
bcf INTCON,t0if ; Interruptflag loeschen
movlw 064 ; RTCC neu einstellen
movwf RTCC ; Wert fuer ca. 10 ms
bsf VKE,vke0 ; VKE =1 als Endebedingung setzen
movf STACK_ST,w ; Statusregister laden
movwf STATUS ; Statusregister wiederherstellen
movf STACK_W,w ; W-Register wiederherstellen
retfie ; zurueck zum Hauptprogramm

adw_int movf ADW_CH,w ; naechsten Analogkanal laden
movwf ADCON0 ; und zuweisen
addlw 008 ; naechsten Kanal selektieren
movwf ADW_CH ; und speichern
andlw 018 ; ueberpruefen ob
xorlw 018 ; letzter Kanal
movlw 0FF ; Vorbereiten fuer ruecksetzen
btfsc STATUS,zero ; gleich wissen wir's
movlw 0E7 ; Ja, dann
andwf ADW_CH,f ; Kanalzaehler ruecksetzen
btfsc ADW_CH,chs0 ; wenn jetzt Kanal 2 selektiert
goto signal_3 ; dann das Ergebnis 3 speichern
btfsc ADW_CH,chs1 ; Kanal 3 selektiert
goto signal_1 ; Ergebnis 1 speichern
movf ADRES,w ; Ergebnis 3 laden
movwf U_SIGNAL2 ; und speichern
goto start_adw ; naechste Wandlung
signal_1 movf ADRES,w ; Ergebnis 1 laden
movwf U_SIGNAL1 ; und speichern
goto start_adw ; naechste Wandlung
signal_3 movf ADRES,w ; Ergebnis 2 laden
movwf U_SIGNAL3 ; und speichern
start_adw bsf ADCON0,go_done ; Start der Wandlung
movf STACK_ST,w ; Statusregister laden
movwf STATUS ; Statusregister wiederherstellen
movf STACK_W,w ; W-Register wiederherstellen
retfie ; zurueck zum Hauptprogramm

;*******************************************************************************************************;
; Unterprogramme ;
;*******************************************************************************************************;
;*******************************************************************************************************;
; Erzeugen der Startbedingung, SDA/SCL als Ausgaenge vorausgesetzt. Uebertragen des Adressbytes aus ;
; DATAUS in PCF 8574. Test des Bestaetigungsbits vom PCF, als Fehlermeldung das Carry-Bit setzen. ;
; Mit einem Einsprung auf dem Label "write" kann die Routine auch fuer schreiben von weiteren ;
; Datenbytes verwendet werden. ;
;*******************************************************************************************************;

start bsf PORTB,sda ; SDA = 1
bsf PORTB,scl ; SCL = 1
nop ; Bus ist frei
movlw 008 ; damit wir die Zeit t_BUF,tSU:STA nicht nur verplempern
movwf BIT ; bereiten wir uns fuer 8 Datenbits vor
bcf PORTB,sda ; SDA = 0 während SCL = 1; Startbedingung
write bsf STATUS,rp0 ; RAM Seite 1 selektieren
clrw ; die Zeit fuer t_HD:STA nuetzen wir um bei PORTB
movwf TRISB ; um wieder den gleichen Zustand herzustellen
bcf STATUS,rp0 ; RAM Seite 0 selektieren
out_next bcf PORTB,scl ; SCL = 0; Taktleitung low
btfss DATAUS,b_out ; jetzt dürfen wir SDA aendern
goto clr_do ; wir testen DATAUS,b_out
bsf PORTB,sda ; DATAUS,msb = 0: SDA = 0 setzen
goto takt_do ; DATAUS,msb = 1: SDA = 1 setzen
clr_do bcf PORTB,sda ; Daten sind bereit
takt_do bsf PORTB,scl ; SCL = 1; Taktimpuls
rlf DATAUS,f ; inzwischen DATAUS links rotieren
decfsz BIT,f ; und kontrollieren ob Schleife 8 mal durchlaufen
goto out_next ; nein, nochmal
rlf DATAUS,f ; wir haben etwas Zeit, daher stellen DATAUS wieder her
bcf PORTB,scl ; SCL = 0; Taktleitung auf low
bcf PORTB,sda ; SDA = 0; damit wir keinen Kurzschluss haben
bsf STATUS,rp0 ; RAM Seite 1 selektieren
movlw 080 ; damit wir die Antwort erfahren
movwf TRISB ; muss SDA als Eingang geschalten werden
bcf STATUS,rp0 ; RAM Seite 0 selektieren
bsf PORTB,scl ; SCL = 1; neunter Taktimpuls
movlw 008 ; wir sind noch etwas zu schnell, daher bereiten wir das
movwf BIT ; Zählregister vorsorglich wieder fuer 8 bit vor; t_high
bcf STATUS,carry ; wir muessen auch noch das Carry-Bit loeschen
btfsc PORTB,sda ; jetzt aber das Bestaetigungsbit testen
bsf STATUS,carry ; Fehlermeldung, w. Bestaetigungsbit = 1 (no Acknowledge)
bcf PORTB,scl ; SCL = 0; Taktleitung low
return ; das war's, nichts wie zurueck

;*******************************************************************************************************;
; Lesen eines Datenbytes aus PCF 8574 nach DATEIN, und Bestaetigungsbit = 0, als Bestaetigung fuer eine ;
; korrekte Uebertragung, bei Carry = 0 ausgeben (Routine zum sequentiellen Lesen mehrerer Datenbytes). ;
; Oder Lesen eines Datenbytes aus PCF 8574 nach DATEIN, und bei Carry = 1 Bestaetigungsbit = 1 ausgeben,;
; um Stoppbedingung zu ermöglichen (Lesen eines oder des letzten Datenbytes) Der Uebertragung folgt die ;
; Stoppbedingung um den Bus wieder freizugeben. Mit Einsprung auf dem Label "Stop" kann die Stopproutine;
; auch einzeln verwendet werden. ;
;*******************************************************************************************************;

read clrf DATEIN ; Datenregister loeschen
next_in bsf PORTB,scl ; SCL = 1; Taktimpuls
btfss PORTB,sda ; Daten sind jetzt gueltig
goto clr_di ; wir testen den SDA-Pin
bsf DATEIN,b_in ; SDA = 0: DATEIN,b_in = 0 setzen
goto takt_di ; SDA = 1: DATEIN,b_in = 1 setzen
clr_di bcf DATEIN,b_in ; Datenbyte komplett
takt_di bcf PORTB,scl ; SCL = 0; Taktleitung low
rlf DATEIN,f ; DATEIN links rotieren
decfsz BIT,f ; Schleife 8 mal durchlaufen
goto next_in ; nein, nochmal
rlf DATEIN,f ; Byte in DATEIN richtigstellen
btfsc STATUS,carry ; Carrybit git an ob letzte Readoparation
goto readlast ; Stoppbedingungen einleiten
bcf PORTB,sda ; Bestaetigungsbit = 0 setzen (Acknowledge)
bsf STATUS,rp0 ; RAM Seite 1 selektieren
clrf TRISB ; Bestaetigungsbit ausgeben, SDA als Ausgang schalten
bcf STATUS,rp0 ; RAM Seite 0 selektieren
bsf PORTB,scl ; SCL = 1; neunter Taktimpuls
movlw 008 ; um einen zweitmaligen Aufruf zu ermoeglichen
movwf BIT ; bereiten wir das Zählregister wieder fuer 8 bit vor
nop ; was soll ich tun, wir sind zu schnell
bcf PORTB,scl ; SCL = 0; Taktleitung low
bsf STATUS,rp0 ; RAM Seite 1 selektieren
movlw 080 ; ebenfalls müssen wir SDA
movwf TRISB ; wieder als Eingang schalten
bcf STATUS,rp0 ; RAM Seite 0 selektieren
return ; fertig, und tschuess
readlast bsf PORTB,sda ; Bestaetigungsbit = 1 gesetzt (no Acknowledge)
bsf STATUS,rp0 ; RAM Seite 1 selektieren
clrf TRISB ; Bestaetigungsbit ausgeben, SDA als Ausgang schalten
bcf STATUS,rp0 ; RAM Seite 0 selektieren
bsf PORTB,scl ; SCL = 1; neunter Taktimpuls
stop bsf STATUS,rp0 ; RAM Seite 1 selektieren
clrf TRISB ; fuer die Stopproutine, beide Leitungen als Ausgaenge
bcf STATUS,rp0 ; RAM Seite 0 selektieren
bcf PORTB,scl ; SCL = 0; Taktleitung low
bcf PORTB,sda ; SDA = 0, Vorbereiten fuer Stoppbedingung
movlw 008 ; da wir wieder zu schnell sind, bereiten wir das
movwf BIT ; Zählregister vorsorglich wieder fuer 8 bit vor; t_high
bsf PORTB,scl ; SCL = 1; Taktleitung high
nop ; mir faellt nichts mehr ein
nop ; was wir hier noch sinnvolles tun koennten
nop ; wir warten noch ein bisschen
bsf PORTB,sda ; SDA = 1; Stoppbedingung
return ; fertig, endlich

;*******************************************************************************************************;
; Unterprogramm fuer Verzoegerungszeit 10ms ;
;*******************************************************************************************************;

pause clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
bsf INTCON,gie ; Interrupt aktiv
time btfss VKE,vke0 ; Warten ca 10 ms
goto time ; Zeit laeuft noch
bcf INTCON,gie ; Interrupt sperren
return

;*******************************************************************************************************;
; Blinkausgang fuer Betriebs- und Stoerungsblinker, Betriebsstundenzaehler ;
;*******************************************************************************************************;

flash decfsz DELAY,f ; Zaehlregister decrementieren
goto flash_end ; Zaehlwert nicht 0, Zeit laeuft
movlw 032 ; Zeit abgelaufen
movwf DELAY ; Zaehlwert fuer 0,5 s neu laden
movlw 0BF ; Bitmaske fuer Ausgang Stoerungsblinker
btfss INPUT1,stoerung ; Abfrage ob Stoerung
movlw 0DF ; Bitmaske fuer Ausgang Betriebsblinker
andwf RELAIS,f ; inaktiven Ausgang loeschen
movlw 020 ; Bitmaske fuer Ausgang Betriebsblinker
btfss INPUT1,stoerung ; Abfrage ob Stoerung
movlw 040 ; Bitmaske fuer Ausgang Stoerungsblinker
xorwf RELAIS,f ; Ausgang umschalten
btfss MERKER,motor_on ; Abfrage ob Motor laeuft
goto flash_end ; Nein, Stundenzaehler aus
decfsz PRESCAL,f ; Vorteiler fuer Stundenzaehler decrementieren
goto flash_end ; Zaehlwert nicht 0, Zeit laeuft
movlw 0F0 ; Zeit abgelaufen
movwf PRESCAL ; Zaehlwert fuer 2 m neu laden
movf MINUTE,w ; nach 2 Minuten
addlw 002 ; Minutenzaehler um 2 erhoehen
movwf MINUTE ; und speichern
sublw 03B ; Abfrage ob 60 m
btfsc STATUS,carry ; abgelaufen
goto wr_memory ; Nein! weiter im Hauptprogramm
clrf MINUTE ; sonst Minutenregister zureucksetzen
movf HOUR1,w ; dann Stundenregister 1 laden
addlw 001 ; incrementieren
movwf HOUR1 ; und speichern
btfsc STATUS,carry ; Ueberlauf?
incf HOUR2,f ; dann auch noch Stundenregister 2 incrementieren
wr_memory movlw EEW ; Bauteiladresse f. Schreiben in EPROM (A0h) laden
movwf DATAUS ; und zuweisen
call start ; Startbedingung und Bauteiladresse uebertragen
movlw 000 ; Speicheradresse (00h) laden
movwf DATAUS ; und zuweisen
call write ; Speicheradresse uebertragen
movf MINUTE,w ; Minutenregister laden
movwf DATAUS ; und zuweisen
call write ; Minutenregister uebertragen
movf HOUR1,w ; Stundenregister 1 laden
movwf DATAUS ; und zuweisen
call write ; Stundenregister 1 uebertragen
movf HOUR2,w ; Stundenregister 2 laden
movwf DATAUS ; und zuweisen
call write ; Stundenregister 2 uebertragen
call stop ; Stoppbedingung uebertragen
flash_end return ; zurueck zum Hauptprogramm

;*******************************************************************************************************;
; Initialisierung des Betriebsstundenzaehlers gespeicherte Werte werden aus demm EEPROM gelesen. ;
;*******************************************************************************************************;

init_h_count movlw EEW ; Bauteiladresse f. Schreiben in EPROM (A0h) laden
movwf DATAUS ; und zuweisen
call start ; Startbedingung und Bauteiladresse uebertragen
btfsc STATUS,carry ; Uebertragungsfehler ?
goto init_h_count ; was schon wieder, nochmal!
movlw 000 ; Speicheradresse (00h) laden
movwf DATAUS ; und zuweisen
call write ; Speicheradresse uebertragen
btfsc STATUS,carry ; Uebertragungsfehler ?
goto init_h_count ; was schon wieder, nochmal!
movlw EER ; Bauteiladresse f. Lesen aus EPROM (A1h) laden
movwf DATAUS ; und zuweisen
call start ; Startbedingung und Bauteiladresse uebertragen
btfsc STATUS,carry ; Uebertragungsfehler ?
goto init_h_count ; was schon wieder, nochmal!
bcf STATUS,carry ; Carrybit loeschen, als Bedingung f. weitere Leseop.
call read ; Minuten vom EEPROM nach DATEIN einlesen
movf DATEIN,w ; eingelesenen Daten in W
movwf MINUTE ; speichern in MINUTE
bcf STATUS,carry ; Carrybit loeschen, als Bedingung f. weitere Leseop.
call read ; Stunden Low-Byte vom EEPROM nach DATEIN einlesen
movf DATEIN,w ; eingelesenen Daten in W
movwf HOUR1 ; speichern in HOUR1
bsf STATUS,carry ; Carrybit setzen, als Bedingung f. letzte Leseop.
call read ; Stunden High-Byte vom EEPROM nach DATEIN einlesen
movf DATEIN,w ; eingelesenen Daten in W
movwf HOUR2 ; speichern in HOUR2
return ; zurueck zum Hauptprogramm

;*******************************************************************************************************;
; *********************************** Hauptprogramm *********************************************** ;
; Initialisierung der Ports, der verwendeten Register, aktivieren von Interrupt, AD-Wandler und RTCC. ;
;*******************************************************************************************************;

org 100 ; Hauptprogramm bei 100h

init clrf PORTA ; Port A loeschen
clrf PORTB ; Port B loeschen
clrf MERKER ; Bitmerker loeschen
clrf RELAIS ; Ausgangspuffer loeschen
bsf STATUS,rp0 ; RAM Seite 1 selektieren
movlw 085 ; RTCC vorbereiten (Intern, Vorteiler 64)
movwf OPT ; ergibt bei f = 4 MHz einen Takt von 64 us
movlw 1F ; RA0-4 hochohmig
movwf TRISA ; Port initialisieren
clrf TRISB ; RB0-7 Ausgaenge
movlw 001 ; RA0-2 Analogeingang, RA4 U-Ref
movwf ADCON1 ; AD-Wandlereingaenge selektieren
bcf STATUS,rp0 ; RAM Seite 0 selektieren
movlw 081 ; Taktfrequenz/32, RA0 aktiv, ADW ein
movwf ADCON0 ; AD-WAndler initialisieren
addlw 008 ; naechsten Kanal selektieren
movwf ADW_CH ; Analogkanal speichern
movlw 0E1 ; RTCC Wert laden fuer
movwf RTCC ; vorerst fuer eine Verzoegerung von 1 ms
movlw 060 ; ADW- und Timer-Interrupt aktiv, Interrupt gesperrt
movwf INTCON ; INTCON Register zuweisen
movlw 032 ; Zaehlwert 50 * 10 ms = 500 ms
movwf DELAY ; Zaehlregister fuer Blinker initialisieren
movlw 078 ; Zaehlwert 120 * 500 ms = 1 m
movwf PRESCAL ; Zaehlregister fuer Stundenzaehler initialisieren
bsf ADCON0,go_done ; AD-Wandler starten
call init_h_count ; Stundenzaehler initialisieren

;*******************************************************************************************************;
; Einlesen der Digitaleingaenge ueber den I2C Bus vom Port des PCF 8574 und speichern in INPUT1/2. ;
; Einlesen der Analogeingaenge waehrend der 10 ms Warteschleife und speichern in U_SIGNAL1/2/3. ;
;*******************************************************************************************************;

loop call pause ; Zeit 10 ms, um die AD-Werte einzulesen
call flash ; Warnblinker, Betriebsstundenzaehler
bcf MERKER,i2c_err ; Errorbit loeschen, ein neuer Versuch
movlw PCF1R ; Bauteiladresse fuer Lesen aus PCF1 (41h) laden
movwf DATAUS ; und zuweisen
call start ; Startbedingung und Bauteiladresse uebertragen
btfsc STATUS,carry ; Uebertragungsfehler ?
bsf MERKER,i2c_err ; was schon wieder, Errorbit setzen!
bsf STATUS,carry ; Carrybit setzen, als Bedingung f. eine Leseoperation
call read ; Byte vom PCF1 DATEIN nach einlesen
movf DATEIN,w ; eingelesenen Daten in W
movwf INPUT1 ; speichern in INPUT1
movlw PCF2R ; Bauteiladresse fuer Lesen aus PCF2 (43h) laden
movwf DATAUS ; und zuweisen
call start ; Startbedingung und Bauteiladresse uebertragen
btfsc STATUS,carry ; Uebertragungsfehler ?
bsf MERKER,i2c_err ; was schon wieder, Errorbit setzen!
bsf STATUS,carry ; Carrybit setzen, als Bedingung f. eine Leseoperation
call read ; Byte vom PCF2 nach DATEIN einlesen
movf DATEIN,w ; eingelesenen Daten in W
movwf INPUT2 ; speichern in INPUT2

;*******************************************************************************************************;
; Verknuepfung fuer die Bewegung Gabel heben/senken. Gabel heben ist nur erlaubt, wenn Turm steht und ;
; Turm umlegen ausgeschalten; Gabel senken zwischen die Vorderwangen ist nur in Mittelpositon erlaubt. ;
;*******************************************************************************************************;

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
movf U_SIGNAL1,w ; Signalspannung heben/senken laden
addlw 07C ; Ueberpruefe ob heben
btfss STATUS,carry ; wenn senken dann VKE = 0
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,turm_steht ; Abfrage ob Turm steht
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss INPUT1,arb_legen ; Abfrage ob Turm legen ausgeschalten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
btfsc INPUT2,s_schub_l ; Abfrage ob Seitenschub links
bsf VKE,vke0 ; Nein! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc INPUT2,s_schub_r ; Abfrage ob Seitenschub rechts
movlw 001 ; Nein! VKE = 1
xorwf VKE,f ; VKE = VKE exclusiv oder letztes VKE
movlw 001 ; Vorbereiten fuer VKE invertieren
xorwf VKE,f ; VKE invertieren
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc INPUT2,schub_vrn ; Abfrage ob Mastschub ganz vorne
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movf U_SIGNAL1,w ; Signalspannung heben/senken laden
sublw 07C ; Ueberpruefe ob senken
movlw 0FE ; vorbereiten fuer naechste UND-Verknuepfung
btfss STATUS,carry ; wenn heben dann VKE = 0
movlw 0FF ; VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc VKE,vke1 ; VKE aus Stack1 ueberpruefen
movlw 001 ; VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,signal_act ; Abfrage ob Bewegungsfunktion aktiv
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf RELAIS,heben ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Relais heben/senken ausschalten
bsf RELAIS,heben ; wenn VKE = 1, Relais heben/senken einschalten

;*******************************************************************************************************;
; Verknuepfung fuer die Bewegung Mast vor/zurueck - Gabeltraeger links/rechts. Die Umschaltung zwischen ;
; Mastschub und Seitenschub erfolgt per Digitaleingang. Das Ventil schaltet nach erfolgter Freigabe fuer;
; die jeweilig vorgewaehlte Funktion um, wenn der Hebel sich in Nullstellung befindet. Verliert man die ;
; Freigabe fuer die jeweilige Funktion, so wird in der Nullstellung des Hebels das zwangsweise Anfahren ;
; der Freigabe eingeleitet. Die Funktion Turm in Transportpositon fahren hat Vorrang vor den beiden ;
; Schubfunktionen. Wenn der Turm nicht vollstaendig steht ist die Schiebefunktion generell gesperrt. ;
;*******************************************************************************************************;

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfsc INPUT2,s_schub_l ; Abfrage ob Seitenschub links
bsf VKE,vke0 ; Nein! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc INPUT2,s_schub_r ; Abfrage ob Seitenschub rechts
movlw 001 ; Nein! VKE = 1
xorwf VKE,f ; VKE = VKE exclusiv oder letztes VKE
movlw 001 ; Vorbereiten fuer VKE invertieren
xorwf VKE,f ; VKE invertieren
bcf MERKER,en_m_schub ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Freigabe Mastschub ruecksetzen
bsf MERKER,en_m_schub ; wenn VKE = 1, Freigabe Mastschub setzen

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfss INPUT2,s_schub_l ; Abfrage ob Seitenschub links
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss INPUT2,s_schub_r ; Abfrage ob Seitenschub rechts
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc INPUT2,schub_vrn ; Abfrage ob Mastschub ganz vorne
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
bcf MERKER,en_s_schub ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Freigabe Seitenschub ruecksetzen
bsf MERKER,en_s_schub ; wenn VKE = 1, Freigabe Seitenschub setzen

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfss INPUT1,signal_act ; Abfrage ob Bewegungsfunktionen nicht aktiv
bsf VKE,vke0 ; Ja! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc MERKER,act_m_schub ; Selbsthaltung wenn Signalspannung 0 war
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
btfss INPUT2,m_s_schub ; Abfrage ob Vorwahl Mastschub
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss INPUT1,arb_legen ; Abfrage ob Turm legen ausgeschalten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
btfsc INPUT1,arb_legen ; Abfrage ob Turm legen eingeschalten
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss INPUT1,schub_trsp ; Abfrage ob Transportposition
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc VKE,vke1 ; VKE aus Stack1 ueberpruefen
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc MERKER,en_m_schub ; Abfrage ob Freigabe Mastschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc VKE,vke2 ; VKE aus Stack2 ueberpruefen
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf MERKER,act_m_schub ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Mastschub aktiv ruecksetzen
bsf MERKER,act_m_schub ; wenn VKE = 1, Mastschub aktiv setzen

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfss INPUT1,signal_act ; Abfrage ob Bewegunsfunktion nicht aktiv
bsf VKE,vke0 ; Ja! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc MERKER,act_s_schub ; Selbsthaltung wenn Signalspannung 0 war
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT2,m_s_schub ; Abfrage ob Vorwahl Seitenschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss INPUT1,arb_legen ; Abfrage ob Turm legen ausgeschalten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc MERKER,en_s_schub ; Abfrage ob Freigabe Seitenschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf MERKER,act_s_schub ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Seitenschub aktiv ruecksetzen
bsf MERKER,act_s_schub ; wenn VKE = 1, Seitenschub aktiv setzen

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfss INPUT1,signal_act ; Abfrage ob Bewegungsfunktion nicht aktiv
bsf VKE,vke0 ; Ja! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc MERKER,movto_m_schub ; Selbsthaltung wenn Signalspannung 0 war
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
btfss INPUT2,m_s_schub ; Abfrage ob Vorwahl Mastschub
bsf VKE,vke0 ; Ja! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc INPUT1,arb_legen ; Abfrage ob Turm legen eingeschalten
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss MERKER,en_m_schub ; Abfrage ob keine Freigabe Mastschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
btfsc INPUT2,s_schub_l ; Abfrage ob Seitenschub links
bsf VKE,vke0 ; Nein! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc INPUT2,s_schub_r ; Abfrage ob Seitenschub rechts
movlw 001 ; Nein! VKE = 1
xorwf VKE,f ; VKE = VKE exclusiv oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT2,m_s_schub ; Abfrage ob Vorwahl Seitenschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss MERKER,en_s_schub ; Abfrage ob keine Freigabe Seitenschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc VKE,vke1 ; VKE aus Stack1 ueberpruefen
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc VKE,vke2 ; VKE aus Stack2 ueberpruefen
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf MERKER,movto_m_schub ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Mastschub-Position anfahren inaktiv
bsf MERKER,movto_m_schub ; wenn VKE = 1, Mastschub-Position anfahren aktiv

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfss INPUT1,signal_act ; Abfrage ob Bewegungsfunktion nicht aktiv
bsf VKE,vke0 ; Ja! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc MERKER,movto_s_schub ; Selbsthaltung wenn Signalspannung 0 war
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT2,m_s_schub ; Abfrage ob Vorwahl Seitenschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss INPUT1,arb_legen ; Abfrage ob Turm legen ausgeschalten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss MERKER,en_s_schub ; Abfrage ob keine Freigabe Seitenschub
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT2,s_schub_l ; Abfrage ob Seitenschub links
movlw 0FF ; Nein! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT2,s_schub_r ; Abfrage ob Seitenschub rechts
movlw 0FF ; Nein! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf MERKER,movto_s_schub ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Seitenschub-Position anfahren inaktiv
bsf MERKER,movto_s_schub ; wenn VKE = 1, Seitenschub-Position anfahren aktiv

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfss INPUT2,s_schub_l ; Abfrage ob Seitenschub links
bsf VKE,vke0 ; Ja! VKE = 1
movf U_SIGNAL2,w ; Signalspannung links/rechts laden
addlw 07C ; Ueberpruefe ob links
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss STATUS,carry ; wenn links dann VKE = 0
movlw 0FF ; Nein! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
btfss INPUT2,s_schub_r ; Abfrage ob Seitenschub rechts
bsf VKE,vke0 ; Ja! VKE = 1
movf U_SIGNAL2,w ; Signalspannung links/rechts laden
sublw 07C ; Ueberpruefe ob rechts
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss STATUS,carry ; wenn rechts dann VKE = 0
movlw 0FF ; Nein! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc VKE,vke1 ; VKE aus Stack1 ueberpruefen
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc MERKER,movto_m_schub ; Abfrage ob Mastschub-Position anfahren aktiv
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
movf U_SIGNAL2,w ; Signalspannung vor/zurueck laden
addlw 07C ; Ueberpruefe ob zurueck
btfss STATUS,carry ; wenn zurueck dann VKE = 0
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc MERKER,movto_s_schub ; Abfrage ob Seitenschub-Position anfahren aktiv
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc VKE,vke1 ; VKE aus Stack1 ueberpruefen
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc MERKER,act_m_schub ; Abfrage ob Mastschub aktiv
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc MERKER,act_s_schub ; Abfrage ob Seitenschub aktiv
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,turm_steht ; Abfrage ob Turm steht
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,signal_act ; Abfrage ob Bewegungsfunktion aktiv
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf RELAIS,schieben ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Relais schieben ausschalten
bsf RELAIS,schieben ; wenn VKE = 1, Relais schieben einschalten

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfsc MERKER,act_s_schub ; Abfrage ob Seitenschub aktiv
bsf VKE,vke0 ; Ja! VKE = 1
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc MERKER,movto_m_schub ; Abfrage ob Seitenschub-Position anfahren aktiv
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
bcf RELAIS,s_schub ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Relais Seitenschub ausschalten
bsf RELAIS,s_schub ; wenn VKE = 1, Relais Seitenschub einschalten

;*******************************************************************************************************;
; Verknuepfung fuer die Bewegung Turm umlegen/aufstellen - Stuetzen ausfahren/einfahren. Turm umlegen ;
; ist nur erlaubt wenn sich der Mastschub in Transportposition befindet, der Gabeltraeger ganz abgesenkt;
; und Turm umlegen eingeschaltet ist. Turm aufstellen ist nur bei Vorwahl Turm legen/aufstellen aktiv. ;
; Das Ventil fuer die Abstuetzung wird bei Vorwahl mit Stuetzen und Turm legen Aus aktiviert. ;
;*******************************************************************************************************;

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
movf U_SIGNAL3,w ; Signalspannung legen/aufstellen laden
sublw 07C ; Ueberpruefe ob legen
btfss STATUS,carry ; wenn aufstellen dann VKE = 0
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,gabel_u ; Abfrage ob Gabeltraeger unten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,schub_trsp ; Abfrage ob Transportposition
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movf U_SIGNAL3,w ; Signalspannung legen/aufstellen laden
addlw 07C ; Ueberpruefe ob aufstellen
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfss STATUS,carry ; wenn legen dann VKE = 0
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,arb_legen ; Abfrage ob Turm legen eingeschalten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf STATUS,carry ; Carrybit loeschen fuer Rotationsbefehl
rlf VKE,f ; VKE in den Stack schieben
btfsc INPUT1,slct_stuetze ; Abfrage ob mit Stuetzen
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfss INPUT1,arb_legen ; Abfrage ob Turm legen ausgeschalten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
movlw 000 ; Vorbereiten fuer naechste ODER-Verknuepfung
btfsc VKE,vke1 ; VKE aus Stack1 ueberpruefen
movlw 001 ; Ja! VKE = 1
iorwf VKE,f ; VKE = VKE oder letztes VKE
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,signal_act ; Abfrage ob Bewegungsfunktion aktiv
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf RELAIS,legen ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Relais Turm legen ausschalten
bsf RELAIS,legen ; wenn VKE = 1, Relais Turm legen einschalten

clrf VKE ; Register fuer Verknuepfungsergebnisse loeschen
btfsc INPUT1,slct_stuetze ; Abfrage ob mit Stuetzen
bsf VKE,vke0 ; Ja! VKE = 1
movlw 0FE ; Vorbereiten fuer naechste UND-Verknuepfung
btfsc INPUT1,arb_legen ; Abfrage ob Turm legen eingeschalten
movlw 0FF ; Ja! VKE = 1
andwf VKE,f ; VKE = VKE und letztes VKE
bcf RELAIS,stuetze ; Vorbereiten fuer Asugabe VKE
btfsc VKE,vke0 ; wenn VKE = 0, Relais Stuetze ausschalten
bsf RELAIS,stuetze ; wenn VKE = 1, Relais Stuetze einschalten

;*******************************************************************************************************;
; Resultate ausgeben und Sprung zum Programmanfang ;
;*******************************************************************************************************;

next movf RELAIS,w ; was wir mit viel Muehe ausgerechnet haben
btfsc MERKER,i2c_err ; und kein Uebertragungsfehler am I2C-Bus ist
clrw ; sonst sind die Ausgaenge 0
movwf PORTB ; wird hier ausgegeben
goto loop ; wir sind fertig, von vorn

;*******************************************************************************************************;
; Programmende ;
;*******************************************************************************************************;

end ; Programmende
;=======================================================================================================;


Ihr müßt mir aber den in diesem Programm viel zu üppigen und meist völlig sinnlosen und kitschigen Komentar verzeihen. Das ist eben noch eine Jugendünde in den Anfängen meiner Assembleprogrammiererei. Wenn allerdings jemand noch genaueres wissen möchte, kann er ruhig frangen. Vielleicht erinnere in mich noch was ich damals gedacht habe.
Auch Anregungen höre ich gerne.

Schöne Grüße Selfman

_________________
Traue keinem Ding, das du nicht selber vermurkst hast.

BID = 574742

selfman

Schreibmaschine



Beiträge: 1681
Wohnort: Seekirchen a. W.

Noch eine kleine Draufgabe!
Habe noch so ein Programm aus der Staplerära gefunden, es ist noch ein bißchen weiterentwickelt (aber der Stundenzähler geht immer noch nicht zum auslesen ). Die Beschreibungen der einzelnen Module sind hier etwas treffender, die Kommentare genauso blöd.

Füge es diesmal in Dateiform an, da es ansonsten so verstümmelt aussieht.

Schöne Grüße Selfman


_________________
Traue keinem Ding, das du nicht selber vermurkst hast.

BID = 574779

Ltof

Inventar



Beiträge: 9334
Wohnort: Hommingberg

Danke!

Hab jetzt beide Listings abgespeichert und werde mir die zu gegebenem Anlass genauer ansehen.

edit:
Blöde Kommentare gibt es nicht. Keine Kommentare zu haben ist blöd!

Gruß,
Ltof

_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)

[ Diese Nachricht wurde geändert von: Ltof am 26 Dez 2008  9:51 ]


Zurück zur Seite 1 im Unterforum          Vorheriges Thema Nächstes Thema 


Zum Ersatzteileshop


Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum       Datenschutz       Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland       

gerechnet auf die letzten 30 Tage haben wir 19 Beiträge im Durchschnitt pro Tag       heute wurden bisher 17 Beiträge verfasst
© x sparkkelsputz        Besucher : 182423493   Heute : 2535    Gestern : 5459    Online : 270        29.11.2024    14:19
2 Besucher in den letzten 60 Sekunden        alle 30.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
xcvb ycvb
0.055634021759