|
|
// tmb880.CPP
// ---------- Version 07.08.2009
// Borland IDE C++ 5.02 od. Paradigm
// bearbeitet: www.GoBlack.de, D.Schwarzer
// ---------------------------------------
// Ziel-Hardware: dESµ IPC-Rechner
// PIO-Anschlüsse
// Temperatur-Modell TMB880
// Das Programm fragt die SPI-Signalfolge des TMB880 Modells durch
// Polling ab und liefert dessen Temperaturwert
// Das Programm endet durch [ESC]
// Vor der Compilierung des Programms sollten nachfolgende
// Variablen gesetzt werden ..
// 1. An welchen PIO.bits sind das Takt- und das Datensignal ange-
// schlossen
#define takt 0x00 // Bit: PIO.0 (#INT5)
#define datum 0x09 // Bit: PIO.9
// 2. In welchen Zeitabständen soll der Sensor abgefragt
// werden? .. Angabe in Millisekunden
#define aktion 100
// ========================================================
// Headerdateien der statischen Bibliothek
#include <stdio.h> // für printf()
#include <bios.h> // für bioskey()
// Deklaration eigener Funktionen zum Betrieb des IPC@CHIP, seiner
// PIO.Bits und der IO-Verfahren.
unsigned init_pio (char pioNr, char mode);
unsigned read_pio (char pioNr);
void rtx_sleep(int ms);
void setStdio (char kanal);
// tmb880()
// Dieser C Programmteil liest die SPI-Schnittstelle des tmb880-
// Temperaturmodells über zwei PIO-Torbits und durch Polling aus.
// Er ermittelt den 13-stelligen BCD Temperaturwert.
// Beim SC23 dauert ein PIO-Abfragezyklus etwa 8,4µs ==>
// 0-Signal TMB880 mit 0,125ms entspricht ~14 Zyklen
// 1-Signal TMB880 mit 1,000ms entspricht ~119 Zyklen
// Da eine TMB880 Abfrage 18ms andauert und jede Sekunde eine
// Messung von ihm bereitgestellt wird, ergibt sich der längste
// 1-Wartezyklus durch 1000ms-18ms mit ~116905 Zyklen
// Fehlerrückgaben:
// -1 (0xFFFF) TimeOut, kein Sensor angeschlossen?
// -2 (0xFFFE) Start der Abfrage in einer laufenden Übertragung
int tmb880 (void)
{
const char nr=13; // Anzahl der zu lesenden Datum-Bits
int bcdval=0; // Schieberegister der Temperatur
unsigned long lop1=0, lop0=0;
for(char n=0; n<nr; n++){
// 1-Taktsignale abwarten und Anzahl der Wartezyklen zählen
for(lop1=0; (read_pio(takt)>>takt)==1; lop1++){
if(lop1>0x20000L) return(0xFFFE); // TimeOut (keinSensor?)
}
if(n==0 && lop1<0xFFL) return(0xFFFF); // Start in ein. Messung
// 0-Taktsignale abwarten und Anzahl der Wartezyklen zählen
for(lop0=0; (read_pio(takt)>>takt)==0; lop0++){
if(lop0>0xFFF0L) return(0xFFFE); // TimeOut (keinSensor?)
}
// Datumbit abfragen und in eine 16 Bit-Variable mit dem
// BCD-Wert ---v ZZZZ EEEE zzzz schieben.
bcdval=(bcdval<<1) | (read_pio(datum)>>datum);
}
return(bcdval);
}
// tmb880asc()
// Die Funktion erhält den BCD-codierten Temperaturwert des TMB880
// Sensors übergeben, der die Form ---V ZZZZ EEEE zzzz
// (Vorzeichen, Zehner,Einer,zehntel)
// besitzt und wandelt ihn in einen nullterminierten ASCII-String
// der Form +oder -ZE,z Grd C um. Ein Zeiger auf diesen String wird
// zurückgegeben und kann zum Ausdrucken des Temperaturwertes
// benutzt werden.
char* tmb880asc(int bcdval)
{
static char asc[]={"+00,0 Grd C"};
asc[4]=(char)(bcdval& 0x000F)+0x30;
asc[3]=',';
asc[2]=(char)((bcdval>>4)& 0x000F)+0x30;
asc[1]=(char)((bcdval>>8)& 0x000F)+0x30;
asc[0]='+';
if(bcdval& 0x1000) asc[0]='-';
return(asc);
}
// main()
// Sie ruft in zeitlichen Abständen von 'aktion' ms die Abfrage-
// funktion des TMB880-Temperatursensors auf und gibt den empfan-
// genen Wert in seiner BCD und seiner ASCII-Form zum Terminal-
// Programm aus. Abbruch durch [ESC]
#define ESC 0x1B
void main (void)
{
int bcdval= 0;
char key= 0;
setStdio(2); // Fokus dieses Programm
init_pio (takt, 1); // PIO.0 Taktbit, Eingang
init_pio (datum, 1); // PIO.9 Datumbit, Eingang
printf("\r\n[tmb880] Start");
printf("\r\n-----------------\r\n");
while (key!=ESC){
if(bioskey(1))key= bioskey(0); // Tastaturabfr. ohne warten
bcdval =tmb880(); // TMB880 abfragen
// wenn bcdval<0 ist, dann liegt ein Einlesefehler vor.
// bcdval ist auch bei negativen Temperaturen >=0
// mögliche Fehler:
// -1 (0xFFFF) kein Sensor angeschlossen
// -2 (0xFFFE) Abfragestart in laufender Übertragung
if(bcdval<0){
printf("\r\nBCD: %0.4X - Fehler", bcdval); continue;}
printf("\r\nBCD: %0.4X - ASCII: %s", bcdval, tmb880asc(bcdval));
rtx_sleep(aktion);
}
// Programmende
printf("\r\n[tmb880] Ende\r\n");
setStdio(3); // Fokus Betriebssystem
}
// ================================================================
// Funktionen zum Betrieb des IPC@CHIP, seiner PIO.Bits und seiner
// Terminalsteuerung
// init_pio()
// Die Funktion initialisiert einen der in pioNr angegebenen Pio-
// Pin 0-31, auf den in mode angegeben Zustand. Die Modi lauten für
// die ..
// Pios 0-15, mode= .. 0| 1, 2, 3| 4| 5
// Pios 15-31, mode= .. 10|11,12,13|14|15
// mode= 0,10 -Status
// mode= 1,2,3,11,12,13, Eingang (siehe Derivat)
// mode= 4,14 -Ausgang, Startwert HIGH
// mode= 5,15 -Ausgang, Startwert LOW
// Die Anzahl tatsächlich verfügbarer Pio-Pins ist dem Hardware-
// manual des jeweiligen IPC@CHIP zu entnehmen.
// Die Status-Rückgaben der Funktion, die durch den Modus 0 ohne
// Wirkung auf die Pio-Pins angewiesen werden können, werden in den
// globalen Variablen PioIN, PioOUT und PioSTAT abgelegt. Die
// Funktion selber gibt den Wert 0 zurück, wenn der angewiesene
// Vorgang nicht bearbeitet werden konnte.(Beispielsweise wenn der
// PIO-Pin am Derivat nicht verfügbar ist).
unsigned PioIN, PioOUT, PioSTAT; // globale Variable (siehe unten)
unsigned init_pio (char pioNr, char mode)
{
asm{ mov AL, mode
and AL, 0Fh // max.mode= 15
mov CL, pioNr // pionr laden
cmp CL, 16 // auf wert>15 prüfen
jb piok // pioNr 0-15
sub CL, 16 } // PioNr 15-31
piok:
asm{ mov DX, 01h
rol DX, CL // Pio-Maske erstellen
mov AH, 082h // Fkt: 82h
int 0A2h // SofINT: A2h
mov PioSTAT, AX // ist bzw. ist nicht PIO
mov PioIN, DX // ist Input
mov PioOUT, CX } // ist Output
return(_AX |_DX |_CX); // 0 bei einem Fehler
}
// read_pio()
// Die Funktion liest den in 'pioNr' angegebenen PIO-Pin und gibt
// dessen log Wert zurück. Ist die Rückgabevariable 0, so gilt
// log0, bei AX!=0 gilt log1
unsigned read_pio (char pioNr)
{
asm{ mov AL, pioNr // pionr: 0-31
mov AH, 08Ch // SoftINT: A1h, Fkt: 8Ch
int 0A1h }
return(_AX); // AX=0 => log 0
}
// rtx_sleep()
// unterbricht die Ausführung des Programms für eine in Milli-
// sekunden anzugebende Zeit. Parallel arbeitende Programm des
// RTOS-Multitasksystems werden hiervon nicht betroffen, sondern
// erhalten die Arbeitsleistung der CPU. Diese Funktion sollte
// zwingend anstelle der C-Funktion delay() benutzt werden.
// Letztere behindert das Betriebssystem des IPC.
// (siehe RTOS-API)
void rtx_sleep(int ms)
{
asm{ mov bx, ms
mov ah, 00h // SoftINT: ADh, Fkt: 00h
int 0ADh }
}
// setStdio()
// bestimmt, ob das Betriebssystem oder das Anwenderprogramm auf
// dem IPC die Eingaben des Terminalprogramms erhält, bzw. seine
// Ausgaben zum Terminalprogramm senden kann.
// kanal=1 -nur das Betriebssystem bestimmt Ein/Ausgabe
// kanal=2 -nur das Anwenderprogramm bestimmt Ein/Ausgabe
// kanal=3 -Eingaben richten sich an das Betriebssystem,
// Ausgaben können von beiden kommen.
// (siehe BIOS-API)
void setStdio (char kanal)
{
asm{ mov al, kanal
mov ah, 11h // SoftINT: ADh, Fkt: 11h
int 0A0h }
}
|
|