Testprogramm.cpp

 
 
 
 

dESµ Temperaturmodell mit TMB 880

 
 
 

 


 

 
 
 
 
Programm
Das Programm fragt durch Polling das TemperaturModell ab und ermittelt die zurückgegebene Temperatur. Die drei zurückgegebenen BCD-Ziffern und das Vorzeichen werden als ASCII's zur seriellen Schnittstelle des Wirtrechners ausgegeben. Das Komma wird an der entsprechenden Stelle eingefügt.

Abfragestrategie
Das Abfrage-Unterprogramm wartet, bis ein 1-Signal erkannt wird. Ist dieses Signal kürzer als 800µs, wird weiter gewartet. 1-Signale die länger sind, werden als Startsignal der Übertragung gewertet. Da die Geschwindigkeit des MC80535-Rechners bekannt ist, kann bei der Prüfung der Signallänge mit absoluten Werten gearbeitet werden. Um bei der Ermittlung der Signallänge mit einem 8-Bit-Zähler auszukommen, wird das erste 1-Signal alle 5µs abgetastet. Bei einer Länge von 1ms ist damit ein Zählwert von etwa 200 zu erwarten.
 

 

 

 

 
// 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        }
}
 






www..de