Zum Inhalt springen

TSIC™ und ZACWIRE™ auslesen

Das Auslesen von Termperatur-Sensor-ICs (TSIC), die mit dem ZACWIRE Protocol arbeiten, kann sehr einfach per Interrupt gelöst werden. Da gibt es allerdings eine Reihe von Stolperfallen und die Tücke liegt, wie so häufig auch hier im Detail.

Einleitung

Beim TSIC™ (Temperature Sensor Integrated Circuit) [1] handelt es sich um ein Sensor IC, zum Messen von Temperaturen. Dieser Sensor ist in verschiedenen Bauformen, Präzisionsklassen und Ausgangs-Datenformaten verfügbar. Dieser Artikel befaßt sich mit den Typen x06, die den Meßwert digital als 11-Bit Wort liefern.

Zacwire™ Protokoll

Das Zacwire™-Protokoll [2] benötigt nur eine Datenleitung und liefert neben den Daten auch den Takt. Die fallenden Flanken des Signals definieren den Takt, der bei ca. 8 kHz liegt. Die Kodierung der Bits erfolgt durch die Pulsweite (Duty Cycle) und beträgt 25% (L) bzw. 75% (H). Da die Signalperiode durch den Takt auf eine feste und konstante Länge definiert ist, kann bei 50% dieser Periode das Bit direkt gelesen werden.

TSIC Signalcodierung
Abbildung 1 – TSIC Signal Kodierung

Abbildung 1 zeigt die Zusammenhänge. Das Signal vom Sensor ist an Channel 1 (gelb) angelegt, während an Channel 2 (blau) der daraus isolierte Takt mit einer Pulsweite von 50% (tSTROBE)dargestellt wird. Man kann gut erkennen, daß tSTROBE die Hälfte eines Taktzyklus (50%) beträgt und das Signal bei der steigenden Flanke der blauen Kurve verfügbar ist. Man kann auch gut die gesamte Signal-Sequenz erkennen, die aus genau 20 TSIC™ Takten besteht. Der TSIC™ sendet das Signal mit einer Frequenz von ca. 8 kHz. Diese Frequenz ist leider nicht stabil und ändert sich geringfügig im laufenden Betrieb. Daher sollte die Frequenz gemessen werden um den Zeitpunkt für das Lesen des Signals möglichst genau in der Mitte einer Taktperiode festzulegen. Im Gegensatz zu einer fest definierten Wartezeit, reduziert das die Störanfälligkeit enorm. Die Frequenz läßt sich mit Hilfe des Start-Bits ermitteln, da der TSIC™ das Startbit mit einem Duty Cycle von genau 50% sendet, das Signal also genau in der Mitte des Taktes auf H wechselt. Im Abschnitt Software wird das genauer beschrieben. Der Sensor sendet das Messergebnis als 11-Bit Daten-Wort. Dazu ist die Übertragung von zwei Bytes notwendig. Jedes Byte beginnt mit einem Startbit und endet mit einem Parity-Bit. Daraus ergibt sich eine Sequenz von insgesamt 20 Bits. Das High-Byte des Datenwortes wird zuerst übertragen (Abbildung 2).

Bit-Sequenz des Datenstroms
Abbildung 2 – Bit-Sequenz des Datenstroms

Das Startbit des ersten Bytes wird also zur Ermittlung der Frequenz und damit zur Errechnung der Wartezeit nachfolgender ISR Aufrufe genutzt. Das Start/Stop-Bit zwischen den Bytes hat die Länge von zwei Takten, wobei das Stop-Bit über die volle Periode High-Pegel besitzt. Das Parity-Bit erweitert das Byte zu einer geraden Anzahl (Even) von gesetzten Bits. Damit wird die Datenintegrität geprüft. Der TSIC™ sendet alle 100 ms einen Messwert. Da der Sensor weniger als 100 µA Strom zieht, kann man den VCC Pin direkt von einem Mikrocontroller-Ausgang treiben und damit die Meßwertübertragung softwareseitig ein- bzw. ausschalten. Dabei sollte jedoch berücksichtigt werden, daß der erste Meßwert nach dem Anlegen der Spannung erst nach etwa 65-85 ms erfolgt.

Beschaltung

Der Temperatur-Sensor ist einfach zu beschalten. Das Datenblatt [2] empfiehlt möglichst dicht am IC ein RC-Glied anzuschalten um Störungen durch das Controller-Netzteil zu reduzieren.

Beschaltung des Sensors
Abbildung 3 – TSIC™ Beschaltung

Temperatur-Auflösung

Der TSIC™ hat einen Meßbereich von -50° C bis 150° C, umfaßt also insgesamt 200°. Der Meßwert wird in einem 11-Bit langem Wort geliefert. Das entspricht einem linearen Wertebereich von 0-2048. Daher muß das Ergebnis nach folgender Formel umgerechnet werden, um die Temperatur zu erhalten:

T=Messwert* 200°2048 50°

bzw.

T=Messwert* 0.09765 50°

Für die Umrechnung des Meßwertes wird also eine Multiplikation und eine Division bzw. eine Multiplikation mit Gleitkommazahl benötigt. Beides ist für einen Mikrocontroller mit begrenztem Speicher eine große Herausforderung. Um das mit vertretbarem Aufwand umsetzen zu können, muß die Formel etwas umgestellt werden. Zuerst wird der Bruch gekürzt:

T=Messwert* 25°256 50°

Häufig genügt es, Temperaturen über 0° C zu messen, dann kann der Wertebereich des Meßwertes verkleinert werden indem der Offset (50° = 512) vor der Berechnung abgezogen wird. Weiterhin soll die Temperaturauflösung von 0,1° erhalten bleiben, was eine Erweiterung um den Faktor 10 erfordert. Es ergibt sich dann folgende Berechnungsformel:

T= (Messwert511)*125° 128

In Software ist das schon sehr viel leichter handhabbar. Die Subtraktion besteht nur aus zwei Befehlen. Dann erfolgt eine 16-Bit-Multiplikation. Die anschließende Division durch eine Potenz von 2 kann leicht durch eine Rechtsverschiebung realisiert werden. Bei dieser Vorgehensweise wird keine Genauigkeit durch überflüssige Rundungen der Zwischenergebnisse eingebüßt. Lediglich bei der finalen Division gehen ein paar Nachkommastellen verloren, was aber tolerierbar ist.

Software

Es gibt zwei grundsätzliche Möglichkeiten, die Messwerte eines TSIC™ zu erfassen:

On-Demand
diese Methode hält den TSIC™ abgeschaltet und stößt eine Messung manuell an, indem der TSIC™ über einen Ausgangs-Pin per Software mit Spannung versorgt und dann in einer Polling-Schleife auf den Meßwert gewartet wird. Dies hat den Vorteil, daß der Mikrocontroller nicht durch eine Messung unterbrochen wird. Nachteilig ist jedoch, daß eine solche Messung etwa 90 ms in Anspruch nimmt, da der TSIC™ die erste Messung erst nach etwa 65-85 ms liefert und eine Messung ca. 2 ms dauert. Der Controller ist während dieser Zeit beschäftigt und kann keine anderen Dinge tun. Interrupts sollten während der Bearbeitung abgeschaltet werden. Da der Sensor bei der ersten Messung seine Betriebstemperatur noch nicht erreicht hat, sollte man mehrere Messungen durchführen und dann den Mittelwert bilden, was zusammen einige 100 ms in Anspruch nehmen kann.
Interrupt-gesteuert
diese Methode ist die bessere Wahl, da der Controller hier im Slave-Modus die Daten empfangen kann, wenn sie gesendet werden. Es muß nicht gewartet werden und die einzelnen Bits kommen genau „getimed“ am Controller an und können direkt verarbeitet werden. Allerdings ist die Verarbeitung etwas aufwändiger und der Controller muß mindestens mit 4 MHz getaktet werden.

Im Folgenden wird auf die erste Methode nicht weiter eingegangen. Der Controller wird so konfiguriert, daß er einen externen INT0- oder INT1-Interrupt auf der fallenden Flanke des TSIC™-Signals auslöst. Damit bekommen wir jedes Bit des Sensors frei Haus geliefert, wenn es verfügbar ist. Um den Verarbeitungsstatus über die einzelnen ISR Aufrufe zu persistieren, ist ein Status-Byte definiert und in einem General-Purpose IO Register abgelegt, was ein Byte im SRAM spart und einen schnelleren Zugriff ermöglicht. In der ISR wissen wir also immer, welches der 20 Bits gerade verarbeitet werden soll. Abbildung 4 zeigt den Aufbau des Status-Bytes.

Status Byte Aufbau
Abbildung 4 – Control Status Register

Die einzelnen Bitpositionen bedeuten:

A – Active Flag
Wird beim ersten Start Bit gesetzt und zeigt eine laufende Verarbeitung an. Es ist während der gesamten Verarbeitung gesetzt und wird erst mit dem letzten Bit zurück gesetzt
V – Valid Measurement
wird gesetzt, wenn die Verarbeitung fehlerfrei durchgelaufen ist und ein gültiger Meßwert verfügbar ist. Dieses Bit muß vom Programm abgefragt werden, bevor auf den Meßwert zugegriffen wird
H – High-Byte Flag
Da der Aufbau beider Bytes identisch ist, muß die ISR wissen, welches Byte gerade decodiert wird.
P – Process-Step
In diesen beiden Bits wird der nächste Schritt aus der Verarbeitungs-Sequenz gespeichert. Die Sequenz ist für jedes Byte durch das Format festgelegt (START-DATA-PARITY). Zusammen mit dem High-Byte Flag und dem Bitzähler, ist das zu verarbeitende Bit eindeutig identifiziert.
B – Bitcounter
die letzten drei Bits dienen als Zähler für das Bit, daß gerade verarbeitet wird (7..0)

Die sequentielle Abfolge der Verarbeitung ist simpel. Jeder Schritt weiß, welcher der nächste ist und aktualisiert das Control-Status Register entsprechend.

Daten Verarbeitungs-Sequenz
Abbildung 5 – Verarbeitungs Sequenz

Im ersten Schritt (START) erfolgt die Initialisierung des Prozesses. Dazu wird die Frequenz des Sensors mit einer Zählschleife ermittelt. Dieser Wert wird zur Initialisierung der Warteschleife für folgende ISR Aufrufe genutzt. Er wird in einem weiteren GPIOR persistent abgelegt.

Sensor Initialisierungsbyte

Dann wird das Control-Status Register initialisiert und der Messwert gelöscht. Die DATA-Phase wird für jedes Byte genau acht mal durchlaufen. Der Bitzähler im Control-Status Register wird dazu von 7 bis 0 herabgezählt und identifiziert damit gleichzeitig das Bit und dessen Position im Ergebnis-Byte. Nur wenn das gelesene Signal-Bit = 1 ist, wird das Bit an der entsprechenden Position im Ergebnis gesetzt. Nicht gesetzte Bits werden nicht verarbeitet.

Ist der Zähler auf 0 zurück gezählt worden, wird das Control-Status Register aktualisiert und auf den nächsten Schritt gesetzt. Nun erfolgt die Verarbeitung des Parity-Bits für das decodierte Ergebnis-Byte. Das Parity-Bit erweitert das gelesene Datenbyte und es wird geprüft, ob zusammen eine gerade Anzahl gesetzter Bits vorhanden ist.

Ist dies der Fall, dann wird das Control-Status Register beim High-Byte auf den nächsten Schritt (START/STOP) gestellt und das High-Byte Flag gelöscht. Schlägt der Parity-Check fehl, dann wird die Messung verworfen und die Verarbeitung abgebrochen. Das geschieht durch die Löschung des Control-Status Registers und einer Warteschleife von 2 ms. Schließlich werden noch alle wartenden Interrupts gelöscht. Bis zur nächsten Messung steht dann kein gültiger Meßwert zur Verfügung.

Als nächstes folgt das START/STOP Bit, welches lediglich eine Aktualisierung des Control-Status Registers bewirkt. Es wird auf den nächsten Prozess-Schritt (DATA) gesetzt.

Die Verarbeitung des Low-Datenbytes des Meßwertes erfolgt analog dem High-Byte, außer daß die Bits nun in das Low-Byte geschoben werden. Nach dem letzten Bit wird der Prozess-Schritt wieder auf PARITY gesetzt. Auch für das Low-Byte wird nun wieder ein Parity-Check durchgeführt, der im Falle eines Fehlschlags wieder zur Verwerfung des Messwertes und der Beendigung der Verarbeitung führt. Ist die Prüfung in Ordnung, wird nun aus dem empfangenen Messwert der Temperaturwert errechnet.

Abschließend wird noch das Aktiv-Flag gelöscht um zu signalisieren, daß die Verarbeitung abgeschlossen ist und das Valid Flag gesetzt, sodaß die gemessene Temperatur weiter verarbeitet werden kann. In Abbildung 6 ist die gesamte ISR als Ablauf-Flußdiagramm dargestellt. Es zeigt den detaillierten Aufbau und zeigt, wie die Daten in den einzelnen Schritten verarbeitet werden.

Timings

TSIC™ Frequenz8000Hz
Pulslänge125µs
tSTROBE62µs
CPU-Clock4MHz
Delay Counter58
Delay247clks
Delay62µs
Tabelle 1 – TSIC Timings
Pfadclksµs
Start< 301< 75
Data< 355< 89
Parity (High)< 384< 96
Parity (Low)< 657< 164
Parity (invalid)84082102
Start/Stop30075
Tabelle 2 – Laufzeiten

Der Beispiel-Code ist in AVR-Assembler geschrieben. Es ist sinnvoll, daß zumindest die ISR ein kontrolliertes Laufzeitverhalten aufweist, was nur mit Assembler realisierbar ist, damit sichergestellt ist, daß ein Durchlauf abgeschlossen ist, bevor der TSIC™ das nächste Bit schickt.

Da die Verarbeitung eines Bits immer mit einer Warteschleife von ca. 60 µs beginnt (tSTROBE), bleiben für die Verarbeitung eines Prozess-Schrittes maximal nur weitere 60 µs. Das setzt selbst in Assembler einen Prozessortakt von mindestens 4 MHz voraus. Wird der Code in C geschrieben, wird der Code trotz Optimierung nicht effizient genug sein. Auf Grund der kritischen Anforderungen sollte in diesem Fall eine Optimierungs-Option gewählt werden, die auf schnelle Ausführung optimiert. Zur Sicherheit ist dann auch ein Prozessortakt von mindestens 8 MHz zu wählen.

Tabelle 1 zeigt die Ausführungszeiten der einzelnen ISR-Durchläufe des hier vorgestellten Beispiel-Codes bei einem CPU-Takt von 4 MHz. Die Zeiten enthalten die Warteschleife und liegen alle unter 100 µs. Die beiden Ausreißer in der Parity-Phase sind unkritisch, da dies jeweils das letzte Bit der Sequenz ist (Ausgang). Die langen Zeiten sind entweder so gewollt (invalidate) oder resultieren aus der Messwert/Temperatur Umrechnung, die am Ende der Verarbeitung durchgeführt wird. Bei den Warteschleifen soll noch darauf hingewiesen werden, daß der Aufruf einer ISR ebenso wie der Rücksprung jeweils 4 Prozessor-Takte benötigen. Zusammen mit der Sicherung der Register sind das nach dem Auftreten der fallenden Flanke 13 Takte, bis die ISR produktiven Code ausführen kann. Für die Laufzeit der ISR sind also insgesamt 26 Takte für den Startup/Cleanup Code zu berücksichtigen.

Die Zählschleife der Frequenzmessung verbraucht für jeden Durchlauf 4 Takte, hat also eine Auflösung von 1 µs. Damit der gezählte Wert für die Warteschleife verwendet werden kann, verbraucht auch diese pro Durchlauf 4 Takte. Da sowohl bei Zählen als auch beim Warten der Startup-Code der ISR durchlaufen ist, kann der Zählerwert direkt für die Initialisierung der Warteschleife verwendet werden. Er liegt je nach Frequenz des Sensors bei ca. 58.

Ablaufdiagramm der Signalverarbeitung
Abbildung 6 – Ablaufdiagramm der ISR

Listings

Listing 1 – Interrupt Service Routine (isr.S)
; ============================================================================
;	Temperature Controller with TSIC (INT1 ISR) (AS)
;
;	MCU 	ATtiny2313
;	Clock	4.0 MHz
;
;	Copyright (c) by Juergen Werner, Koeln 2012
; ============================================================================
#include <avr/io.h>
#include "common.h"

signal  =       17
tmp	= 	16
cnt	=	18
mwl	=	17
mwh	=	18
pck	=	17

; global definition of measurement value (uint16)
.comm measurement, 2

        .section .text

;== ---------------------------------------------------------------------------
;== 	ISR INT1 (serves falling edges on PD2)
;== ---------------------------------------------------------------------------
        .global INT1_vect
INT1_vect:
	push	signal
	push	tmp
	push	cnt
	in 	tmp,_SFR_IO_ADDR(SREG)
	push	tmp

	; check if this is the start edge (active flag is low)
	sbis	_SFR_IO_ADDR(ZACWIRE_CONTROL), ZW_ACTIVE_FLAG
	rjmp	init				; not active, goto initializing block
		
	; tstrobe delay (preloop 15 clocks, one cycle 4 clocks)
	in	signal, _SFR_IO_ADDR(DELAY_PRESET)
dloop:	dec	signal				; decrement (1 clk)
	nop					; we need 4 clocks per loop
	brne	dloop				; loop until 0 (2 clks)

	; get bit from signal pin and save it in signal register
        sbic    _SFR_IO_ADDR(ZACWIRE_PIN), ZW_SIGNAL_PIN
        ldi	signal, 1			; if skipped signal is 0
	
	; processing is already active, check processing steps
	; check DATA
	in	tmp, _SFR_IO_ADDR(ZACWIRE_CONTROL)	; get control structure
	andi	tmp, PROCMSK			; isolate processing step
	cpi	tmp, DATA			; check DATA
	brne	party				; isn't, goto next check
		
	; DATA (bit processing)
	; get bitcounter decrement and save into control structure
	in	tmp, _SFR_IO_ADDR(ZACWIRE_CONTROL)
	mov	cnt, tmp			; save bitcounter in cnt
	andi	cnt, BITMASK			; isolate
	dec	cnt				; counting from 7...0 (init 0)
	andi	cnt, BITMASK			; isolate (because of overflow)
	andi	tmp, ~(BITMASK)			; clear cnt area in control struct
	or	tmp, cnt			; insert new bit counter value
	out	_SFR_IO_ADDR(ZACWIRE_CONTROL), tmp	; update control structure
		
	; check if actual bit is set, then skip bit processing
	tst	signal
	breq	ckcnt				; continue with bit counter check
		
	; signal is set, update measurement value
	mov	tmp, cnt			; copy bit counter
	tst	tmp				; check if 0 (last bit - LSB)
bloop:	breq	ckhbt				; last bit
	lsl	signal				; otherwise left shift to bit pos
	dec	tmp				; shift counter
	rjmp	bloop				; shift loop
		
ckhbt:	; select actual processing byte
	sbis	_SFR_IO_ADDR(ZACWIRE_CONTROL), ZW_HIGH_BYTE
	rjmp	lowbt
		
highbt:	; actual processing high byte
	lds	tmp, (measurement + 1)		; get high byte from memory
	or	tmp, signal			; set bit
	sts	(measurement + 1), tmp		; save high byte
	rjmp	ckcnt
		
lowbt:	; actual processing low byte
	lds	tmp, (measurement + 0)		; get low byte from memory
	or	tmp, signal			; set bit
	sts	(measurement + 0), tmp		; update low byte
	; falling through

ckcnt:	; finalize bit processing with check of bit counter
	tst	cnt
	brne	exit				; not null, end here, wait for next bit
		
	; bitcounter is 0 - byte complete, init next step (parity)
	in	tmp, _SFR_IO_ADDR(ZACWIRE_CONTROL)	; get control structure
	andi	tmp, ~(PROCMSK)			; isolate processing step
	ori	tmp, PARITY			; set next step to parity
	out	_SFR_IO_ADDR(ZACWIRE_CONTROL), tmp	; update
	rjmp	exit				; finish data bit processing
		
party:	; check process step is PARITY ?
	cpi	tmp, PARITY			; check if actual step is parity
	brne	start				; no data, no parity, goto start block
		
	; start parity bit processing here
	rcall	check_parity			; check parity
	brcc	par0
	rcall	invalidate			; reset and ignore the rest
	rjmp	exit

par0:	; parity check was ok ...		
	sbis	_SFR_IO_ADDR(ZACWIRE_CONTROL), ZW_HIGH_BYTE	; check highbyte
	rjmp	par2				; no, check low byte

par1:	; processing high byte parity
	in	tmp, _SFR_IO_ADDR(ZACWIRE_CONTROL)	; get control structure
	andi	tmp, ~(PROCMSK | (1<<ZW_HIGH_BYTE))	; clear step an highbyte
	out	_SFR_IO_ADDR(ZACWIRE_CONTROL), tmp	; save control structure
	rjmp	exit	
	
par2:	; processing low byte prarity, finish tsic processing here (last step)
	rcall	calculate			; calculate measurement value (adjust)
	cbi	_SFR_IO_ADDR(ZACWIRE_CONTROL), ZW_ACTIVE_FLAG	; reset activ
	sbi	_SFR_IO_ADDR(ZACWIRE_CONTROL), ZW_VALID_FLAG	; set valid flag
	rjmp	exit
		
start:	; start bit received - only between high- and low-byte
	; initizing processing of second byte
	in	tmp, _SFR_IO_ADDR(ZACWIRE_CONTROL)	; get control structure
	andi	tmp, ~(PROCMSK)			; clear processing step area
	ori	tmp, DATA			; set next step to data
	out	_SFR_IO_ADDR(ZACWIRE_CONTROL), tmp	; save structure
	rjmp	exit
		
init:	; init waiting for rising edge and save for later delay loops
	clr	cnt				; clear counter
init0:	; loop for counting needs 4 clocks
	inc	cnt				; increment delay counter
	sbis	_SFR_IO_ADDR(ZACWIRE_PIN), ZW_SIGNAL_PIN	; check signal
	rjmp	init0				; jump loop if cleared

	dec	cnt				; adjust
	out	_SFR_IO_ADDR(DELAY_PRESET), cnt		; save preset

	; first edge control inactive, initialize tsic processing sequence
	; set active flag, reset valid flag, set highbyte flag and first step
	ldi	tmp, (1<<ZW_ACTIVE_FLAG) | (1<<ZW_HIGH_BYTE) | (PROCMSK & DATA)
	out	_SFR_IO_ADDR(ZACWIRE_CONTROL), tmp	; update structure
	eor	tmp, tmp				
	sts	(measurement + 0), tmp		; clear measurement value (low)
	sts	(measurement + 1), tmp		; clear measurement value (high)
	; falling through
		
exit:	; exit isr
	pop	tmp
	out 	_SFR_IO_ADDR(SREG), tmp
	pop	cnt
	pop	tmp
	pop	signal
        reti
		
;== ---------------------------------------------------------------------------
;==		void calculate(void) - local function
;==
;== 	calculation of measurement value from TSIC
;== 		T = ((MW - 511) * 1000) / 1024
;==
;==		@return modifies measurement value in memory
;==		@destroys mwh, mwl, tmp
;== ---------------------------------------------------------------------------
calculate:
	push	r0
	push	r1
	push	r2
	push	r3
	lds	mwh, (measurement + 1)		; get row measurementment (high part)
	lds	mwl, (measurement)		; get row measurementment (low part)
		
	subi	mwl, 0xFF			; first expression (MW - 511)
	sbci	mwh, 0x01

	clr	r3				; prepare product destination (r3:r2:r1:r0)
	clr	r2
	ldi	tmp, 125			; 
	mov	r0, tmp
	clr	r1	
	ldi	tmp, 16				; load bit counter (will shift 16 times)

	lsr	r1				; first shift right (product low word)
	ror	r0
cmulxa:
	brcc	cmulxb				; if right byte was 1 (carry set)
	add	r2, mwl				; add measurementment value to product
	adc	r3, mwh
cmulxb:						; otherwise just shift whole product right
	ror	r3
	ror	r2
	ror	r1
	ror	r0
	dec	tmp				; decrement bit counter to process next bit
	brne	cmulxa				; repeat 16 times

	ldi	tmp, 7				; div / 128 equal to right shift 7 times (log2(128))

cdivxa:		
	ror	r2				; shift whole product ( /2 )
	ror	r1
	ror	r0
	dec	tmp				; 7 times => / 128
	brne	cdivxa

	sts	(measurement + 1), mwh		; save calculated temperature (high part)
	sts	(measurement), mwl		; save calculated temperature (low part)
		
	pop	r3
	pop	r2
	pop	r1
	pop	r0
	ret
		
;== -------------------------------------------------------------------------
;==		uint8 check_parity(uint8 pck) - local function
;==
;== 	this method checks the parity of the decoded byte
;==
;==		@param	parity bit in pck (signal)
;== 	@return 0 if ok, otherwise 1 in pck
;==		@destroys tmp
;== -------------------------------------------------------------------------
check_parity:
	; pck = signal contains the received parity bit (initial value)
	sbis	_SFR_IO_ADDR(ZACWIRE_CONTROL), ZW_HIGH_BYTE	; check highbyte
	lds	tmp, (measurement + 0)		; get low byte
	sbic	_SFR_IO_ADDR(ZACWIRE_CONTROL), ZW_HIGH_BYTE	; check highbyte
	lds	tmp, (measurement + 1)		; get low byte
		
ploop:	tst	tmp				; check if bits are set
	breq	pexit				; no, break here
	lsr	tmp				; get next bit in carry
	brcc	ploop				; carry set, add bit
	inc	pck				; add 1 to result
	rjmp	ploop				; next bit
		
pexit:	; parity check completed, finalize result (even parity)
	lsr	pck				; result to carry
	ret

;== ---------------------------------------------------------------------------
;==		void invalidate(void) - local function
;==
;== 	if wrong result, stop processing here and synchonize by waiting 2ms
;==		will reset active flag and valid flag
;==
;==		@destroys tmp, cnt
;== ---------------------------------------------------------------------------
invalidate:
	; delay 2 ms
	; inner loop will need exactly 1002 clocks
	ldi	cnt, INVALIDATE_DELAY		; init outer loop
outlp:	ldi	tmp, 250			; init inner loop
innlp:	dec	tmp				; count back
	nop					; one clock
	brne	innlp				; loop
	dec	cnt				; count back outer loop
	brne	outlp				; outer loop
		
	; reset processing control structure
	clr	tmp				; clear control structure
	out	_SFR_IO_ADDR(ZACWIRE_CONTROL), tmp	; save structure
		
	; clear all waiting interrupt requests
	ldi	tmp, (1<<INTF1)			; (re)set INT1 Flag
	out	_SFR_IO_ADDR(EIFR), tmp		; by writing 1 to GIFR

	ret

	.end

Listing 2 – Include Definitions-File (common.h)
/******************************************************************************/
/* Common Header File contains definitions used in all Files   		      */
/*                                                                            */
/* Author:	Juergen Werner                                                */
/* Created:	14.03.2010                                                    */
/* Last modified: 25.08.2012						      */
/* Version:	1.1                                                           */
/* Copyright (c) by Trimension, Cologne                                       */
/******************************************************************************/
#ifndef COMMON_H_
#define COMMON_H_
#include <avr/io.h>

// === MCU Speed Definition ===
#ifndef F_CPU
#define F_CPU	4000000         	// processor clock frequency
#warning F_CPU not set - redefined
#endif

// ----- TSIC ISR definitions
#define INVALIDATE_DELAY (2 * (F_CPU / 1000000))

#define ZACWIRE_CONTROL	GPIOR0		// processing control structure register
#define ZW_ACTIVE_FLAG	GPIOR07		// processing active mark
#define ZW_VALID_FLAG	GPIOR06		// processing inactiv and valid measurement value
#define ZW_HIGH_BYTE	GPIOR05		// internal, processing highbyte
#define DELAY_PRESET	GPIOR1		// contains calculated TSTROBE preset

#define BITMASK	0x07		// internal, bitcounter in processing control structure
#define PROCMSK 0x18		// internal, step marker in processing contr. structure
#define DATA 	0x08		// next step data bit decoding
#define PARITY	0x10		// next step parity bit processing

// TSIC Port definitions
#define ZACWIRE_PIN	PIND
#define ZW_SIGNAL_PIN	PD3	// IN - sensor input signal

#endif /* COMMON_H_ */

Quellverweise

  1. IST AG, Schweiz – Produktbeschreibung – TSIC™ Produktbeschreibung und Datenblatt
  2. IST AG, Schweiz – ZACWIRE™ Protokoll – ZACWIRE™ Digital Output – Application Notes

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Wählen Sie die Flagge *

DSGVO Cookie Consent mit Real Cookie Banner