/* Ansteuerung des A/D-Wandlerchips ADS1210, 1211, 1212, 1213
* mit dem PC am Parallelport
* h#s 07/05 Nur Win32!
*/
#include "wutils.h"
#include "../inpout32/inpout32.h"
#include <stdio.h>
#include <math.h> // floor
#include <shlwapi.h>
UINT LptBase;
FILE*f; // Log-Datei
TCHAR LogName[MAX_PATH];
UINT LogZaehler; // Anzahl zu schreibender Messwerte, dann Schluss
DWORD CommandReg=0x43002000L+1952; // Abbild des Kommando-Registers im ADS121x
UINT KanalMaske=0xF; // Welche Kanäle benutzt werden, Default: alle vier
void outbyte(DWORD a, BYTE b) {
Out32((short)(LptBase+a),b);
}
BYTE inbyte(DWORD a) {
return Inp32((short)(LptBase+a));
}
/**************************************************************************
Die Hardware:
SubD Bit
D0..D7 2..9 +0:0..7 Stromversorgung für Optokoppler (alle High setzen!)
ACK 10 +1:6 -DRDY Fertigmeldung ADU (ADU -> PC)
BSY 11 +1:/7 SDOUT Serielle Ausgabe (ADU -> PC)
STB 1 +2:/0 SCLK Serieller Takt (PC -> ADU)
DSL 17 +2:/3 SDIO Serielle Eingabe (PC -> ADU)
/**************************************************************************/
void SendBits(unsigned x, unsigned bits) { // <bits> Bits aus <x> zum ADU senden
bits=1<<(bits-1); // nun Maske, MSB zuerst
while (bits) {
BYTE b=(BYTE)(x&bits ? 0x00 : 0x08); // Takt HIGH, Daten je nach Bit
outbyte(2,b);
b|=0x01; // Takt LOW, Daten werden vom ADU übernommen
outbyte(2,b);
bits>>=1;
}
}
unsigned RecvBits(int bits) {
unsigned r=0;
while (bits) {
r<<=1;
outbyte(2,0x08); // Daten LOW, Takt HIGH
if (!(inbyte(1)&0x80)) r|=1; // Wenn SDOUT=HIGH, ein Datenbit in <r> setzen
outbyte(2,0x09); // Takt und Daten auf LOW
bits--;
}
return r;
}
bool WaitDRDY(void) { // Wartet High-Low-Flanke von /DRDY ab
DWORD tic=GetTickCount();
while (!(inbyte(1)&0x40)) { // abfragen bis High
if (GetTickCount()-tic>200) return false;
}
while (inbyte(1)&0x40) { // abfragen bis Low
if (GetTickCount()-tic>200) return false;
}
return true;
}
bool InitADU(void) {
outbyte(0,0xFF); // Optokoppler mit Betriebsspannung versorgen
outbyte(2,0x09); // Takt und Daten auf LOW
if (!WaitDRDY()) return false;
SendBits(0x64,8); SendBits(CommandReg|0x00200000L,32); // SDL=1 - SDOUT aktivieren
// Zugleich 10 Hz Abtastrate wählen und Self-Calibration
SendBits(0x84,8); // Prüfen, ob der gleiche Wert rückgelesen werden kann
return (RecvBits(8)>>1)==(CommandReg>>25);
}
HINSTANCE HInstance;
HANDLE hPorttalk=INVALID_HANDLE_VALUE; // PORTTALK.SYS-Handle (nur NT)
HWND MainWnd; // Hauptfenster
HFONT LargeFont;
HBRUSH BlueBrush;
HBRUSH YellowBrush; // für DDE-Advise-Variablen
ATOM AtomBack;
TCHAR sDecimal[2];
TCHAR IniFileName[MAX_PATH];
TCHAR HelpFileName[]=T("ADS121x.HLP");
DWORD DdeInst;
HSZ hszService;
#define hszTopic hszService
#define WM_CONTINUEINIT (WM_USER+100)
typedef struct {
long wert; // Wert vom ADU
float anz; // Anzeigewert
float skale; // Faktor für <wert>
float offset; // dimensionsbehaftet!
int ziffern; // Kommastellen
TCHAR einheit[8]; // Einheit (zur Anzeige)
HSZ hsz; // DDE-String-Handle
UINT idx; // (Rückwärtiger) Index
}TADWert;
TADWert ADWert[4];
UINT Millisek; // Default: 500
HSZ CreateStringHandle(PCTSTR Str) {
return DdeCreateStringHandle(DdeInst,Str,CP_WINNEUTRAL);
}
void FreeStringHandle(HSZ hsz) {
if (hsz) DdeFreeStringHandle(DdeInst,hsz);
}
int CheckHsz(HSZ hsz) {
int i;
for (i=0; i<4; i++) {
if (!DdeCmpStringHandles(hsz,ADWert[i].hsz)) return 108+8*i;
}
return 0; // alles andere ist Fehler
}
#ifdef __BORLANDC__
# pragma argsused
#endif
HDDEDATA CALLBACK DdeCallback(UINT type, UINT fmt, HCONV conv,
HSZ hsz1, HSZ hsz2, HDDEDATA data, DWORD data1, DWORD data2) {
switch (type) {
case XTYP_CONNECT: {
if (hsz1==hszTopic) {
SetDlgItemText(MainWnd,111,T("DDE-Verbindung gestartet"));
return (HDDEDATA)TRUE;
}
}break;
case XTYP_DISCONNECT: {
SetDlgItemText(MainWnd,111,T("DDE-Verbindung beendet"));
}break;
case XTYP_REQUEST:
case XTYP_ADVREQ: {
int id=CheckHsz(hsz2);
char s[16];
if (fmt!=CF_TEXT) break;
if (!id) break;
return DdeCreateDataHandle(DdeInst,(LPBYTE)s,
GetDlgItemTextA(MainWnd,id,s,elemof(s))+1,
0,hsz2,fmt,0);
}
case XTYP_ADVSTART:
case XTYP_ADVSTOP: {
int id=CheckHsz(hsz2);
HWND w;
if (!id) break;
w=GetDlgItem(MainWnd,id);
id=(int)GetProp(w,(LPTSTR)AtomBack);
id+=type==XTYP_ADVSTART?+1:-1;
if (id) SetProp(w,(LPTSTR)AtomBack,(HANDLE)id);
else RemoveProp(w,(LPTSTR)AtomBack);
InvalidateRect(w,NULL,TRUE);
return (HDDEDATA)TRUE;
}
}
return (HDDEDATA)FALSE;
}
void Float2String(PTSTR s, float z) {
_stprintf(s,T("%.6G"),z);
s=_tcschr(s,T('.'));
if (s) *s=sDecimal[0];
}
bool String2Float(PTSTR s, float*z) {
PTSTR p;
p=_tcschr(s,sDecimal[0]);
if (!p) p=_tcschr(s,T(','));
if (p) *p=T('.');
if (_stscanf(s,T("%G"),z)!=1) return false;
return true;
}
void LoadADWert(TADWert*w) {
TCHAR s[32];
TCHAR sektion[2];
_stprintf(sektion,T("%u"),w->idx+1);
GetPrivateProfileString(sektion,T("Skalierung"),T("1"),s,elemof(s),IniFileName);
String2Float(s,&w->skale);
GetPrivateProfileString(sektion,T("Offset"),T("0"),s,elemof(s),IniFileName);
String2Float(s,&w->offset);
w->ziffern=GetPrivateProfileInt(sektion,T("Kommastellen"),0,IniFileName);
GetPrivateProfileString(sektion,T("Einheit"),T(""),w->einheit,elemof(w->einheit),IniFileName);
}
void SetLptBase(UINT a) {
LptBase=a;
}
void LoadConfig(void) {
TCHAR s[32];
UINT i=0;
if (GetPrivateProfileString(T("ADS121x"),T("PortBase"),T(""),s,elemof(s),IniFileName))
_stscanf(s,T("%X"),&i);
if (i<0x100) i=0x378;
SetLptBase(i);
Millisek=GetPrivateProfileInt(T("ADS121x"),T("Millisek"),500,IniFileName);
if (GetPrivateProfileString(T("ADS121x"),T("CommandReg"),T(""),s,elemof(s),IniFileName))
_stscanf(s,T("%lX"),&CommandReg);
if (GetPrivateProfileString(T("ADS121x"),T("KanalMaske"),T(""),s,elemof(s),IniFileName))
_stscanf(s,T("%X"),&KanalMaske);
GetPrivateProfileString(T("ADS121x"),T("LogName"),T("ADS121x.log"),
LogName,elemof(LogName),IniFileName);
for (i=0; i<elemof(ADWert); i++) LoadADWert(ADWert+i);
InitADU();
}
void SaveADWert(TADWert*w) {
TCHAR s[32];
TCHAR sektion[2];
_stprintf(sektion,T("%u"),w->idx+1);
Float2String(s,w->skale);
WritePrivateProfileString(sektion,T("Skalierung"),s,IniFileName);
Float2String(s,w->offset);
WritePrivateProfileString(sektion,T("Offset"),s,IniFileName);
_stprintf(s,T("%i"),w->ziffern);
WritePrivateProfileString(sektion,T("Kommastellen"),s,IniFileName);
WritePrivateProfileString(sektion,T("Einheit"),w->einheit,IniFileName);
}
void SaveConfig(void) {
TCHAR s[32];
UINT i;
_stprintf(s,T("0x%X"),LptBase);
WritePrivateProfileString(T("ADS121x"),T("PortBase"),s,IniFileName);
_stprintf(s,T("%i"),Millisek);
WritePrivateProfileString(T("ADS121x"),T("Millisek"),s,IniFileName);
_stprintf(s,T("0x%lX"),CommandReg);
WritePrivateProfileString(T("ADS121x"),T("CommandReg"),s,IniFileName);
_stprintf(s,T("0x%X"),KanalMaske);
WritePrivateProfileString(T("ADS121x"),T("KanalMaske"),s,IniFileName);
WritePrivateProfileString(T("ADS121x"),T("LogName"),LogName,IniFileName);
for (i=0; i<elemof(ADWert); i++) SaveADWert(ADWert+i);
WritePrivateProfileString(NULL,NULL,NULL,IniFileName);
}
void DdeStart(void) {
DdeInitialize(&DdeInst,DdeCallback,
CBF_FAIL_POKES|CBF_FAIL_EXECUTES|
CBF_SKIP_REGISTRATIONS|CBF_SKIP_UNREGISTRATIONS,0);
hszService=CreateStringHandle(T("ADS121x"));
ADWert[0].hsz=CreateStringHandle(T("1"));
ADWert[1].hsz=CreateStringHandle(T("2"));
ADWert[2].hsz=CreateStringHandle(T("3"));
ADWert[3].hsz=CreateStringHandle(T("4"));
AtomBack=AddAtom(T("DdeAdvises"));
YellowBrush=CreateSolidBrush(0xC0FFFFL);
DdeNameService(DdeInst,hszService,0,DNS_REGISTER);
}
void DdeStop(void) {
DdeUninitialize(DdeInst);
DeleteObject(YellowBrush);
}
void PorttalkStart(void) {}
void PorttalkStop(void) {}
void SetWert(TADWert *w,long wert) {
TCHAR buf[32];
PTSTR p;
if (w->wert==wert) return;
w->wert=wert;
w->anz=w->wert*w->skale-w->offset;
_stprintf(buf,T("%.*f %s"),
w->ziffern,
w->anz,
w->einheit);
p=_tcschr(buf,T('.'));
if (p) *p=sDecimal[0];
SetDlgItemText(MainWnd,108+2*w->idx,buf);
DdePostAdvise(DdeInst,hszTopic,w->hsz);
}
bool GetMesswert(TADWert*w,long*v) { // Messwert vom A/D-Wandler holen
if (!WaitDRDY()) return false; // Warten bis fertig
SendBits(0xC0,8); // 3 Bytes von Adresse 0 lesen wollen
*v=(long)(RecvBits(24)<<8)>>8; // 3 Bytes lesen und Vorzeichen "aufblasen"
return true;
}
bool GetMesswert3x(TADWert*w,long*v) { // dito, mehrfach probieren
int i=3;
do if (GetMesswert(w,v) /*&& *v>-0x7FFFF0 && *v<0x7FFFF0*/) return true; while(--i);
return false;
}
void StartMessung(TADWert*w) { // Messung auf Kanal anstoßen
CommandReg=(CommandReg&~0x30000)|(w->idx<<16);
SendBits(0x24,8);
SendBits(CommandReg>>16,16); // Kanal setzen, ADU starten
}
#ifdef __BORLANDC__
# pragma argsused
#endif
UINT CALLBACK OfnHook(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
switch (Msg) {
case WM_INITDIALOG: {
SetWindowLong(Wnd,DWL_USER,lParam);
}break;
case WM_COMMAND: switch (LOWORD(wParam)) {
case 101: EnableDlgItem(Wnd,102,IsDlgButtonChecked(Wnd,101)); break;
case 103: { // Je nach Schalter Überschreibwarnung aktivieren
LPDWORD f=&(((LPOPENFILENAME)GetWindowLong(Wnd,DWL_USER))->Flags);
if (IsDlgButtonChecked(Wnd,103)) *f&=~OFN_OVERWRITEPROMPT;
else *f|=OFN_OVERWRITEPROMPT;
}break;
}break;
case WM_NOTIFY: switch (((LPOFNOTIFY)lParam)->hdr.code) {
case CDN_FILEOK: {
if (IsDlgButtonChecked(Wnd,101)) // Wenn EIN dann Rückgabewert setzen (?)
((LPOFNOTIFY)lParam)->lpOFN->lCustData=GetDlgItemInt(Wnd,102,NULL,FALSE);
}break;
}break;
}
return 0;
}
void SwitchLog(void) { // Schalte Log-Funktion ein/aus
if (f) {
fclose(f); f=NULL;
}else{
OPENFILENAME ofn;
TCHAR sFilter[128];
sFilter[LoadString(HInstance,104,sFilter,elemof(sFilter))+1]=0;
InitStruct(&ofn,sizeof(ofn));
ofn.hwndOwner=MainWnd;
ofn.hInstance=HInstance;
ofn.lpstrFilter=sFilter;
ofn.lpstrFile=LogName;
ofn.nMaxFile=elemof(LogName);
ofn.Flags=OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY
|OFN_EXPLORER|OFN_ENABLEHOOK|OFN_ENABLESIZING|OFN_ENABLETEMPLATE;
ofn.lpfnHook=OfnHook;
ofn.lpTemplateName=MAKEINTRESOURCE(0x11); // enthält Zusatz-Dialogelemente
if (GetSaveFileName(&ofn)) {
LogZaehler=ofn.lCustData; // Null wenn ohne Begrenzung
f=_tfopen(LogName,ofn.Flags&OFN_OVERWRITEPROMPT?T("wt"):T("at"));
if (!f) MBox(MainWnd,106,MB_ICONSTOP,LogName);
}
}
CheckMenuItem(GetMenu(MainWnd),0x11,f?MF_CHECKED:MF_UNCHECKED);
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL CALLBACK PortDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
const static unsigned Portadressen[]={0x378,0x278,0x3BC};
switch (Msg) {
case WM_INITDIALOG: {
int i;
for (i=0; i<elemof(Portadressen); i++) {
TCHAR s[16];
_stprintf(s,T("LPT%i (0x%X)"),i+1,Portadressen[i]);
SendDlgItemMessage(Wnd,101,CB_ADDSTRING,0,(LPARAM)(LPSTR)s);
if (LptBase==Portadressen[i]) SendDlgItemMessage(Wnd,101,CB_SETCURSEL,i,0);
} // unter Win32 ist kein Rankommen an die wahren Portadressen, oder??
}return TRUE;
case WM_COMMAND: switch (LOWORD(wParam)) {
case IDHELP: WinHelp(Wnd,HelpFileName,HELP_CONTEXT,0x21); break;
case IDOK: {
UINT pa;
pa=(UINT)SendDlgItemMessage(Wnd,101,CB_GETCURSEL,0,0);
if (pa>=elemof(Portadressen)) {
MBox(Wnd,101,MB_ICONEXCLAMATION|MB_OK);
SetFocus(GetDlgItem(Wnd,101));
break;
}
SetLptBase(Portadressen[pa]);
if (!InitADU() && MBox(Wnd,103,MB_ICONEXCLAMATION|MB_OKCANCEL)!=IDOK) break;
}nobreak;
case IDCANCEL: EndDialog(Wnd,wParam);
}
}
return FALSE;
}
void SetEdits(TADWert*w, HWND wnd) {
TCHAR s[32];
UINT idbase=100+4*w->idx;
Float2String(s,w->skale); SetDlgItemText(wnd, idbase,s);
Float2String(s,w->offset);SetDlgItemText(wnd,++idbase,s);
SetDlgItemInt (wnd,++idbase,w->ziffern,FALSE);
SetDlgItemText(wnd,++idbase,w->einheit);
}
bool GetEdits(TADWert*w, HWND wnd) {
TCHAR s[32];
BOOL b;
UINT idbase=100+4*w->idx;
GetDlgItemText(wnd,idbase,s,elemof(s));
if (!String2Float(s,&w->skale)) goto err;
GetDlgItemText(wnd,++idbase,s,elemof(s));
if (!String2Float(s,&w->offset)) goto err;
w->ziffern=GetDlgItemInt(wnd,++idbase,&b,FALSE);
if (!b || w->ziffern>6) goto err;
if ((unsigned)SendDlgItemMessage(wnd,++idbase,WM_GETTEXTLENGTH,0,0)
>=elemof(w->einheit)) goto err; // zu viele Zeichen
GetDlgItemText(wnd,idbase,w->einheit,elemof(w->einheit));
return true;
err:
MBox(wnd,102,MB_ICONEXCLAMATION|MB_OK);
SetEditFocus(wnd,idbase);
return false;
}
bool iWaitDRDY(HWND w) { // interaktive Version von WaitDRDY()
do{
if (WaitDRDY()) return true;
}while (MBox(w,103,MB_RETRYCANCEL)==IDRETRY);
return false;
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL CALLBACK KoeffDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
switch (Msg) {
case WM_INITDIALOG: {
int i;
for (i=0; i<4; i++) SetEdits(ADWert+i,Wnd);
}return TRUE;
case WM_COMMAND: switch (LOWORD(wParam)) {
case 120: EnableDlgItem(Wnd,121,IsDlgButtonChecked(Wnd,120)); break;
case IDHELP: WinHelp(Wnd,HelpFileName,HELP_CONTEXT,0x22); break;
case IDOK: {
if (!GetEdits(ADWert+0,Wnd)) break;
if (!GetEdits(ADWert+1,Wnd)) break;
if (!GetEdits(ADWert+2,Wnd)) break;
if (!GetEdits(ADWert+3,Wnd)) break;
}nobreak;
case IDCANCEL: EndDialog(Wnd,wParam);
}
}
return FALSE;
}
void SetKanalMaske(UINT km) { // macht Hauptfenster-Rähmchen grau
if (KanalMaske!=km) {
int i;
for (i=0; i<elemof(ADWert); i++) {
BOOL e=(1<<i)&km;
HWND w=GetDlgItem(MainWnd,108+2*i);
EnableWindow(w,e); // Static (de)aktivieren
EnableWindow(GetPrevSibling(w),e); // Rahmen (de)aktivieren
if (!e) SetWindowText(w,T("--"));
}
KanalMaske=km;
}
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL CALLBACK KonfDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
switch (Msg) {
case WM_INITDIALOG: {
unsigned i;
HWND w;
TCHAR s[256],*p;
for (i=0,w=GetDlgItem(Wnd,101); i<5; i++) { // Verstärkung
_stprintf(s,T("%ux"),1<<i);
ComboBox_AddString(w,s);
if (i==((CommandReg>>18)&7)) ComboBox_SetCurSel(w,i);
}
for (i=0,w=GetDlgItem(Wnd,102); i<5; i++) { // Turbo
_stprintf(s,T("%ux"),1<<i);
ComboBox_AddString(w,s);
if (i==((CommandReg>>13)&7)) ComboBox_SetCurSel(w,i);
}
Float2String(s,(float)(1E7*(1<<((CommandReg>>13)&7))/(((CommandReg&0x1FFF)+1)<<9)));
SetDlgItemText(Wnd,103,s);
KillTimer(Wnd,103);
SetDlgItemInt(Wnd,104,CommandReg&0x1FFF,FALSE);
SetDlgItemText(Wnd,105,s);
s[LoadString(HInstance,211,s,elemof(s))+1]=0;
for (p=s,w=GetDlgItem(Wnd,106),i=0; *p; p+=lstrlen(p)+1,i++) {
ComboBox_AddString(w,p);
if (i==((CommandReg>>21)&7)) ComboBox_SetCurSel(w,i);
}
CheckDlgButton(Wnd,107,(CommandReg>>30)&1);
SetCheckboxGroup(Wnd,110,113,KanalMaske);
SetDlgItemInt(Wnd,114,Millisek,FALSE);
}return TRUE;
case WM_TIMER: switch (wParam) {
case 103: {
float z;
TCHAR s[32];
int dr,tr;
SetDlgItemText(Wnd,104,T(""));
SetDlgItemText(Wnd,105,T(""));
GetDlgItemText(Wnd,103,s,elemof(s));
if (!String2Float(s,&z)) break;
if (z<=0) break; // Notbremse
tr=1<<SendDlgItemMessage(Wnd,102,CB_GETCURSEL,0,0); //Turbo-Rate
dr=(int)floor(1E7*tr/512/z-0.5); // Dezimierungsverhältnis
SetDlgItemInt(Wnd,104,dr,FALSE);
Float2String(s,(float)(1E7*tr/(dr<<9)));
SetDlgItemText(Wnd,105,s);
}break;
}break;
case WM_COMMAND: switch (LOWORD(wParam)) {
case 102: if (GET_WM_COMMAND_CMD(wParam,lParam)==CBN_SELCHANGE)
SetTimer(Wnd,103,200,NULL); break;
case 103: if (GET_WM_COMMAND_CMD(wParam,lParam)==EN_CHANGE)
SetTimer(Wnd,103,200,NULL); break;
case IDHELP: WinHelp(Wnd,HelpFileName,HELP_CONTEXT,0x23); break;
case 3: // Knopf "Übernehmen"
case IDOK: {
UINT km,ms,dr,vv,tr;
km=GetCheckboxGroup(Wnd,110,113);
if (!km) {
MBox(Wnd,107,MB_ICONEXCLAMATION|MB_OK); // Mindestens 1 Kanal!
SetFocus(GetDlgItem(Wnd,110));
break;
}
ms=GetDlgItemInt(Wnd,114,NULL,FALSE);
if (!ms) {
MBox(Wnd,102,MB_ICONEXCLAMATION|MB_OK); // Eingabefehler!
SetEditFocus(Wnd,114);
break;
}
dr=GetDlgItemInt(Wnd,104,NULL,FALSE);
if (dr<19 || dr>8000) {
MBox(Wnd,108,MB_ICONEXCLAMATION|MB_OK,dr); // Ungültiges Dezimierunsverhältnis!
SetEditFocus(Wnd,103);
break;
}
vv=SendDlgItemMessage(Wnd,101,CB_GETCURSEL,0,0);
tr=SendDlgItemMessage(Wnd,102,CB_GETCURSEL,0,0);
if (vv+tr>4) {
MBox(Wnd,109,MB_ICONEXCLAMATION|MB_OK,1<<(vv+tr)); // Produkt max. 16!
SetFocus(GetDlgItem(Wnd,101));
break;
}
CommandReg=(CommandReg&0xBF030000)
|((DWORD)vv<<18)
|(tr<<13)
|dr
|(SendDlgItemMessage(Wnd,106,CB_GETCURSEL,0,0)<<21)
|(IsDlgButtonChecked(Wnd,107)<<30);
if (!iWaitDRDY(Wnd)) break;
SendBits(0x64,8); SendBits(CommandReg,32);
SetKanalMaske(km);
Millisek=ms;
SetTimer(MainWnd,1,ms,NULL);
}if (wParam!=IDOK) break; // (nur) bei OK Dialog schließen
case IDCANCEL: EndDialog(Wnd,wParam);
}
}
return FALSE;
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL CALLBACK AboutDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
switch (Msg) {
case WM_INITDIALOG: return TRUE;
case WM_COMMAND: EndDialog(Wnd,wParam);
}
return FALSE;
}
int KanalNext(int k) { // Ermittelt nächsten Kanal-Index
if (!KanalMaske) KanalMaske=1; // Gefahr einer Endlosschleife abwehren
do{
k=(k+1)&3;
}while (!((1<<k)&KanalMaske)); // Suche bis Bit gesetzt ist
return k;
}
float U2R(float U) {
// U wird normiert übergeben, als ob der Spannungsteiler mit 1 V gespeist würde
// Liefert Widerstandswert in Ohm
return (float)(2*620E3*U/(1-U)); // Thermistor-Widerstand, mit 2 x 620k Vorwiderstand
}
float R2T(float R) {
// R (Widerstand) in Ohm wird übergeben
// Liefert Temperatur in °C (hoffentlich!)
static long RT[]={ //°C
/*
274590,208350,159390,122910, //-20..-5
95490,74730,58890,46710, //0..15
37320,30000,24250,19720, //20..35
16120,13250,10950,9090, //40..55
7581,6354,5349,4524, //60..75
3840,3273,2799,2405,2073}; //80..100
*/
274590L,261050L,247250L,233600L,220500L,208350L,197250L,186900L,177250L,168500L, // -20..-11
159390L,151150L,144200L,136250L,129800L,122910L,116750L,110950L,105550L,100400L, // -10.. -1
95490L,90850L,86540L,82350L,78450L,74730L,71200L,67850L,64700L,61750L,
58890L,56175L,53625L,51200L,48900L,46710L,44620L,42650L,40800L,39025L,
37320L,35700L,34170L,32715L,31330L,30000L,28730L,27530L,26390L,25360L,
24250L,23250L,22305L,21490L,20545L,19720L,18925L,18175L,17463L,16800L,
16120L,15492L,14892L,14322L,13776L,13250L,12746L,12268L,11810L,11372L,
10950L,10544L,10157L,9788L,9432L,9090L,8762L,8448L,8147L,7859L,
7581L,7314L,7059L,6815L,6580L,6354L,6136L,5927L,5727L,5535L,5349L}; // 60.. 70
// Widerstände von -20°C bis 100°C in 5-K-Schritten
float T;
int i;
for (i=1; i<elemof(RT)-1; i++) {
if (R>=RT[i]) break;
}
T=1/*K/Schritt*/*((R-RT[i-1])/(RT[i]-RT[i-1])/*Teilschritt*/+i/*ganzer Schritt*/-1)-20/*K*/; // Lineare Approximation
return T;
}
float Q2T(float Q) {
// Quotient (dimensionslos) wird übergeben
// Liefert Temperatur des Strahlers in °C (theoretisch)
static float QT[]={
0.50554061F,0.50789839F,
//100 110
0.5364199F,0.56267237F, // 260
0.59180434F,0.59976594F,0.605F,0.60985294F,0.61592107F,0.63174045F,0.65456072F,0.66221956F,0.67252484F,0.67965979F, //270..360
0.7185702F,0.73512444F,0.74871173F,0.77667818F,0.80532793F,0.80115051F,0.812F,0.81503029F,0.83436849F,0.85061072F, //370..460
0.8824144F,0.90055857F,0.92755385F,0.94768855F,0.9655249F,0.9833883F,1.00501006F,1.03118098F,1.04859687F,1.07569943F, //470, 480
1.09730519F,1.11491076F,1.14050132F,1.15840797F,1.18329521F,1.201486F,1.21613201F,1.23606546F,1.26362535F,1.2823049F,
1.30699879F,1.3313783F,1.35827114F,1.36887124F,1.39230524F,1.4085834F,1.43332827F,1.45833877F,1.48067617F,1.50420801F,
1.519656754F
}; //770
int i;
for (i=1; i<elemof(QT)-1; i++) {
if (Q<=QT[i]) break;
}
return 10*((Q-QT[i-1])/(QT[i]-QT[i-1])+(i-1))+110;
}
BOOL CALLBACK MainDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
static TCHAR DefaultTitle[64];
switch (Msg) {
case WM_INITDIALOG: {
int i;
MainWnd=Wnd;
for (i=0; i<4; i++) ADWert[i].idx=i;
GetWindowText(Wnd,DefaultTitle,elemof(DefaultTitle));
LargeFont=CreateFont(40,0,0,0,700,0,0,0,0,0,0,0,0,T("Times"));
BlueBrush=CreateSolidBrush(0xFFC0C0L);
if (LargeFont) for (i=0; i<4; i++) {
SendDlgItemMessage(Wnd,108+2*i,WM_SETFONT,(WPARAM)LargeFont,0);
}
PorttalkStart();
PostMessage(Wnd,WM_CONTINUEINIT,0,0); // ShowWindow verzögern (geht sonst nicht)
}return TRUE;
case WM_CONTINUEINIT: {
ShowWindow(Wnd,SW_SHOWDEFAULT);
SendMessage(Wnd,WM_WININICHANGE,0,0);
SetTimer(Wnd,2,200,NULL);
}break;
case WM_WININICHANGE: { // Wenn in Systemsteuerung Punkt/Komma wechselt
GetProfileString(T("intl"),T("sDecimal"),T("."),sDecimal,elemof(sDecimal));
}break;
case WM_TIMER: switch (wParam) {
case 2: {
KillTimer(Wnd,wParam);
LoadConfig(); // per Timer funktioniert EnableWindow (jetzt erst!)
DdeStart();
SetTimer(Wnd,1,Millisek,NULL);
}break;
case 1: {
static int j;
long v;
if (GetMesswert3x(ADWert+j,&v)) {
int k=KanalNext(j); // nächster Index
if (j!=k) StartMessung(ADWert+k); // wenn Kanalumschaltung erforderlich
SetWert(ADWert+j,v); // Bildschirm aktualisieren (jetzt erst!)
if (k<=j) { // Wenn alle Kanäle durch...
float Qs=ADWert[1].anz?ADWert[0].anz/ADWert[1].anz:0;
float Ts=Q2T(((Qs))); // Strahler-Temperatur (Abweichung zz. 1000%)
float Ra=U2R(ADWert[2].anz); // Thermistor-Widerstand
float Ta=R2T(Ra); // Thermistor-Temperatur
TCHAR s[32];
Float2String(s,Qs); SetDlgItemText(Wnd,120,s);
Float2String(s,Ts); SetDlgItemText(Wnd,122,s);
Float2String(s,Ra); SetDlgItemText(MainWnd,121,s);
Float2String(s,Ta); SetDlgItemText(Wnd,123,s);
if (f) { // Wenn Loggen aktiv...
int kk=k;
do{
fprintf(f,"%f ",ADWert[kk].anz); // Aktive Kanäle loggen
kk=KanalNext(kk);
}while (kk!=k);
fprintf(f,"%f %f\n",Qs,Ta);
// Quotient und Thermistortemperatur am Zeilenende loggen
if (LogZaehler) {
if (--LogZaehler) fflush(f);
else{
MessageBeep(MB_OK);
SwitchLog(); // Log ausschalten
}
}else{
fflush(f);
}
}
}
j=k;
if (IsIconic(Wnd)) goto settitle;
}
}break;
}break;
case WM_SIZE: if (wParam==SIZEICONIC) {
TCHAR buf[64];
settitle:
GetDlgItemText(Wnd,108,buf,32);
lstrcat(buf,T("; "));
GetDlgItemText(Wnd,110,buf+lstrlen(buf),32);
SetWindowText(Wnd,buf);
}break;
case WM_QUERYOPEN: {
SetWindowText(Wnd,DefaultTitle);
}break;
case WM_CTLCOLORSTATIC: switch (GetDlgCtrlID((HWND)lParam)) {
case 108:
case 110:
case 112:
case 114: {
SetBkMode((HDC)wParam,TRANSPARENT);
if (GetProp((HWND)lParam,(LPTSTR)AtomBack)) return (BOOL)YellowBrush;
return (BOOL)BlueBrush;
}
}break;
case WM_COMMAND: switch (LOWORD(wParam)){
case 0x11: SwitchLog(); break;
case 0x1F: SendMessage(Wnd,WM_CLOSE,0,0); break;
case 0x21: DialogBox(HInstance,MAKEINTRESOURCE(0x21),Wnd,PortDlgProc); break;
case 0x22: DialogBox(HInstance,MAKEINTRESOURCE(0x22),Wnd,KoeffDlgProc); break;
case 0x23: DialogBox(HInstance,MAKEINTRESOURCE(0x23),Wnd,KonfDlgProc); break;
case 0x2E: SaveConfig(); break;
case 0x31: WinHelp(Wnd,HelpFileName,HELP_INDEX,0); break;
case 0x32: WinHelp(Wnd,HelpFileName,HELP_CONTEXT,0x32); break;
case 0x3F: DialogBox(HInstance,MAKEINTRESOURCE(0x3F),Wnd,AboutDlgProc); break;
}break;
case WM_CLOSE: {
if (f) fclose(f);
WinHelp(Wnd,HelpFileName,HELP_QUIT,0);
EndDialog(Wnd,0);
}break;
case WM_DESTROY: {
DdeStop();
PorttalkStop();
DeleteObject(LargeFont);
DeleteObject(BlueBrush);
}break;
}
return FALSE;
}
int _fltused;
// Hauptprogramm
void CALLBACK WinMainCRTStartup() {
static WNDCLASS wc={
CS_DBLCLKS,
DefDlgProc,
0,
DLGWINDOWEXTRA,
0,0,0,
(HBRUSH)(COLOR_BACKGROUND+1),
NULL,
T("ADS121x")};
wc.hInstance=HInstance=GetModuleHandle(NULL);
wc.hIcon=LoadIcon(wc.hInstance,MAKEINTRESOURCE(100));
wc.hCursor=LoadCursor(0,IDC_ARROW);
if (!RegisterClass(&wc)) {
#ifdef UNICODE
CHAR buf[256];
LoadStringA(wc.hInstance,210,buf,elemof(buf));
MessageBoxA(0,buf,NULL,MB_OK|MB_ICONSTOP); // Zwang: ANSI-Version
#endif
ExitProcess(3);
}
GetModuleFileName(0,IniFileName,elemof(IniFileName));
lstrcpy(PathFindFileName(IniFileName),T("ADS121x.INI"));
ExitProcess(DialogBox(wc.hInstance,MAKEINTRESOURCE(100),0,MainDlgProc));
}
Detected encoding: UTF-8 | 0
|