re la source de ce petit prog très pratique
Usage et copie libre, je ne projette pas de gagner le prix Turing avec.
dit par l'auteurCode :
/*--------------------------------------------------------------------------
* Programme qui opère sur un bus 1-wire connecté au PC
* La gestion des erreurs 1-wire est basique (on abandonne si problème)
* Options :
* - temp : lit et écrit sur stdout les ROM id et températures
* de toutes les DS18B20 trouvées : ROMid1 temperature1 ROMid2 temperature2...
* - config <precision> : fixe la résolution EEPROM des sondes DS18B20 trouvées
* - search : retourne le ROM id de tous les devices 1-wire trouvés sur le bus
* - dump : rend le scratchpad des sondes DS18B20 trouvées sur le bus
* Rend 0 si succès, 1 si échec
*
* Nécessite que les drivers Maxim/Dallas TMEX soient installés.
*
* Auteur : T.Streiff 01/2010
* 27/01/10 : correction pour les températures négatives
*
* Compilateur : Microsoft Visual C++ 2008 Express
* --------------------------------------------------------------------------
*/
#include "iBTMEXCW.H"
#include <stdio.h>
// prototypes locaux
void fatal(char *);
#define DS18B20_FAMILY 0x28
// variables globales
uchar buffer[5120]; // buffer 1-wire
long session; // session 1-wire
int rc; // code retour générique
/*----------------------------------------------------------------------
* Ecrit le message d'erreur sur stderr
*/
typedef struct msg
{
int code;
char *msg;
} msgT;
msgT mapping[] =
{
{ -200, "invalid session" },
{ -201, "session non trouvée" },
{ -1, "port non initialise" },
{ -2, "port non existant" },
{ -3, "fonction non existante" },
{ -12, "echec BCOM" },
{ -13, "evenement BCOM" },
{ 0, "" }
};
char *msgErr(code)
{
msgT *m = mapping;
while (m->code)
{
if (m->code == code)
return m->msg;
++m;
}
return "";
}
void erreur(char *texte)
{
char* msg = msgErr(rc);
fprintf(stderr, "Erreur, ");
fprintf(stderr, texte);
fprintf(stderr, " : (%d) %s\n", rc, msg);
}
/*----------------------------------------------------------------------
* Termine le programme
*/
void fin(int diag)
{
#if DEBUG
char *msg;
switch (diag)
{
case EXIT_SUCCESS: msg = "OK"; break;
case EXIT_FAILURE: msg = "echec"; break;
default: msg = "inconnu"; break;
}
fprintf(stderr, "Resultat : %s\n", msg);
#endif
exit(diag);
}
/*----------------------------------------------------------------------
* Affiche l'usage sur stdout et quitte
*/
char* usageMsg[] =
{
"Usage",
" search [alarm] : donne les ROM de tous les devices [en alarme] du bus",
" temp : donne ROM et temperatures des DS18B20 du bus",
" dump : donne ROM et scratchpad des DS18B20 du bus",
" config [<precision>] : configure la precision des DS18B20 du bus (12-bit par défaut)",
NULL
};
void usage(void)
{
char **p = usageMsg;
while (*p)
{
fprintf(stderr, *p);
fprintf(stderr, "\n");
++p;
}
fin(EXIT_FAILURE);
}
/*----------------------------------------------------------------------
* Fait un reset du bus 1-wire
*/
void OWReset(void)
{
rc = TMTouchReset(session);
if ((rc != 1) && (rc != 2))
fatal("TMTouchReset");
}
/*----------------------------------------------------------------------
* Fait un reset et un match ROM sur le device courant
*/
void OWAccess(void)
{
if ((rc = TMAccess(session, buffer)) < 0)
fatal("TMAccess");
}
/*----------------------------------------------------------------------
* Lance une recherche générale sur le bus 1-wire
*/
void OWFirst(void)
{
if ((rc = TMFirst(session, buffer)) < 0)
fatal("TMFirst");
}
/*----------------------------------------------------------------------
* Lance une recherche de devices en alarme sur le bus 1-wire
*/
void OWFirstAlarm(void)
{
if ((rc = TMFirstAlarm(session, buffer)) < 0)
fatal("TMFirstAlarm");
}
/*----------------------------------------------------------------------
* Continue une recherche en cours sur le bus 1-wire
*/
void OWNext(void)
{
if ((rc = TMNext(session, buffer)) < 0)
fatal("TMNext");
}
/*----------------------------------------------------------------------
* Continue une recherche en cours des devices en alarme sur le bus 1-wire
*/
void OWNextAlarm(void)
{
if ((rc = TMNextAlarm(session, buffer)) < 0)
fatal("TMNextAlarm");
}
/*----------------------------------------------------------------------
* Continue une recherche en cours sur le bus 1-wire
*/
void OWRom(short rom[])
{
if ((rc = TMRom(session, buffer, rom)) < 0)
fatal("TMRom");
}
/*----------------------------------------------------------------------
* Lit/écrit un octet sur le bus 1-wire
*/
short OWTouchByte(short byte)
{
if ((rc = TMTouchByte(session, byte)) < 0)
fatal("TMTouchByte");
return rc;
}
/*----------------------------------------------------------------------
* Fixe le niveau du bus 1-wire
*/
short OWLevel(short operation, short levelMode, short primed)
{
if ((rc = TMOneWireLevel(session, operation, levelMode, primed)) < 0)
fatal("TMOneWireLevel");
return rc;
}
/*----------------------------------------------------------------------
* Prépare une recherche de devices par famille
*/
void OWFamilySearchSetup(short family)
{
if ((rc = TMFamilySearchSetup(session, buffer, family)) < 0)
fatal("TMFamilySearchSetup");
}
/*----------------------------------------------------------------------
* Ouvre la session 1-wire
*/
void ouvreSession(void)
{
short portNum, portType;
int preMsg;
char *msg;
// récupère le port
if (TMReadDefaultPort(&portNum, &portType) < 0)
{
rc = 0;
fatal("TMReadDefaultPort : port par defaut non trouve");
}
// attend qu'il soit possible d'ouvrir la session
preMsg = TRUE;
for (;;)
{
rc = TMExtendedStartSession(portNum, portType, NULL);
if (rc < 0)
{
fatal("TMExtendedStartSession");
}
if (rc > 0) break;
if (preMsg)
{
fprintf(stderr, "Une autre application utilise le 1-wire...\n");
preMsg = FALSE;
}
}
session = rc;
// setup du bus 1-wire
rc = TMSetup(session);
if (rc < 0)
fatal("TMSetup");
if (rc == 1) return;
switch (rc)
{
case 0: msg = "echec du setup"; break;
case 2: msg = "setup OK mais bus en court-circuit"; break;
case 3: msg = "setup : le bus 1-wire n'existe pas"; break;
case 4: msg = "TMSetup non supporte"; break;
default: msg = "probleme setup inconnu"; break;
};
fatal(msg);
}
/*----------------------------------------------------------------------
* Ferme la session 1-wire
*/
void fermeSession(void)
{
// ignore le retour
TMEndSession(session);
}
/*----------------------------------------------------------------------
* Ecrit le message d'erreur sur stderr et quitte
*/
void fatal(char *texte)
{
erreur(texte);
fermeSession();
fin(EXIT_FAILURE);
}
/*----------------------------------------------------------------------
* Ecrit le ROM courant dans un fichier (avec un espace derrière)
*/
void ecritRom(FILE *f)
{
short rom[8];
int i;
rom[0] = 0;
OWRom(rom);
for (i=7; i>=0; --i)
fprintf(f, "%02x", rom[i]);
fprintf(f, " ");
}
/*----------------------------------------------------------------------
* Attente de x ms
*/
void attente(ms)
{
ulong t = GetTickCount() + ms;
while (GetTickCount() < t)
TMValidSession(session);
}
/*------------------------------------------------------------------------
* Lit le scratchpad du DS18B20 courant
*/
int litDS18B20(uchar *mem)
{
int i;
uchar CRCByte;
short CRC8;
// sélectionne la sonde courante
OWAccess();
if (rc == 0) return EXIT_FAILURE;
// envoie la commande de lecture mémoire
OWTouchByte(0xbe);
// lit les 8 octets de la mémoire et calcule le CRC
CRC8 = 0;
for (i=0; i<8; ++i)
{
OWTouchByte(0x0ff);
mem[i] = (uchar) rc;
CRC8 = TMCRC(1, &mem[i], CRC8, 0);
}
// lit et contrôle le CRC
OWTouchByte(0x0ff);
CRCByte = (uchar) rc;
if (TMCRC(1, &CRCByte, CRC8, 0) != 0)
{
rc = 0;
erreur("CRC invalide en lisant un scratchpad");
return EXIT_FAILURE;
}
// c'est OK
return EXIT_SUCCESS;
}
/*----------------------------------------------------------------------
* Commande "search"
* écrit sur stdout tous les ROM des devices trouvés sur le bus 1-wire
* si alarm est vrai, sélectionne seulement les devices en alarme
*/
int cmdeSearch(int alarm)
{
ouvreSession();
OWReset();
if (alarm) OWFirstAlarm(); else OWFirst();
OWFirst();
while (rc)
{
ecritRom(stdout);
if (alarm) OWNextAlarm(); else OWNext();
}
fermeSession();
return EXIT_SUCCESS;
}
/*----------------------------------------------------------------------
* Commande "config"
* configure la précision de tous les DS18B20 sur le bus 1-wire
*/
int cmdeConfig(int precision)
{
int config;
ouvreSession();
// calcule l'octet de configuration selon la précision demandée
switch (precision)
{
case 9: config = 0x00; break;
case 10: config = 0x20; break;
case 11: config = 0x40; break;
case 12: config = 0x60; break;
default:
rc = 0;
fatal("precision invalide");
}
// écrit la configuration dans le scratchpad
OWReset();
OWTouchByte(0xcc); // cmd "skip ROM"
OWTouchByte(0x4e); // cmd "write scratchpad"
OWTouchByte(0); // TH (remplissage)
OWTouchByte(0); // TL (remplissage)
OWTouchByte(config); // configuration
// écrit le scratchpad dans l'EEPROM
OWReset();
OWTouchByte(0xcc); // cmd "skip ROM"
OWLevel(LEVEL_SET, LEVEL_STRONG_PULLUP, PRIMED_BYTE); // active le strong pullup
OWTouchByte(0x48); // cmd "copy scratchpad"
attente(10); // attente 10 ms
OWLevel(LEVEL_SET, LEVEL_NORMAL, PRIMED_NONE); // retire le strong pullup
fermeSession();
return EXIT_SUCCESS;
}
/*----------------------------------------------------------------------
* Cherche tous les DS18B20 sur le bus et exécute la fonction pour chacun
*/
void tousDS18B20(void (*fn)())
{
short rom[8];
// initialise la recherche
OWFamilySearchSetup(DS18B20_FAMILY);
for (;;)
{
// cherche le DS18B20 suivant et teste s'il en reste
OWNext();
if (rc == 0) break;
// s'assure que c'est bien un DS18B20
rom[0] = 0;
OWRom(rom);
if (rom[0] != DS18B20_FAMILY) break;
// appelle la fonction à appliquer sur le DS18B20 courant
(*fn)();
}
}
/*----------------------------------------------------------------------
* Affiche le scratchpad du DS18B20 courant
*/
void dumpDS18B20(void)
{
uchar mem[8];
int i;
// lit le scratchpad
if (litDS18B20(mem) != EXIT_SUCCESS)
return;
// affiche le ROM et le scratchpad
ecritRom(stdout);
for (i=0; i<8; ++i)
printf("%02x ", mem[i]);
puts("");
}
/*----------------------------------------------------------------------
* Commande "dump"
* Affiche le scratchpad de tous les DS18B20 sur le bus 1-wire
*/
int cmdeDump(void)
{
// applique la fonction de dump à tous les DS18B20 trouvés
ouvreSession();
tousDS18B20(dumpDS18B20);
fermeSession();
return EXIT_SUCCESS;
}
/*----------------------------------------------------------------------
* Affiche le température du DS18B20 courant
*/
void tempDS18B20(void)
{
uchar mem[8];
float temperature;
int msk;
short temp;
// lit le scratchpad
if (litDS18B20(mem) != EXIT_SUCCESS)
return;
// affiche le ROM
ecritRom(stdout);
// calcule la température selon la précision configurée
// masque les bits non significatifs (le DS ne précise pas qu'ils sont à 0)
switch (mem[4] & 0x60)
{
case 0x00: msk = 0x0f8; break;
case 0x20: msk = 0x0fc; break;
case 0x40: msk = 0x0fe; break;
case 0x60: msk = 0x0ff; break;
default: break; // ne peut pas arriver
}
temp = mem[1] << 8 | (mem[0] & msk);
temperature = (float)(temp * 0.0625);
// affiche la température
printf("%f\n", temperature);
}
/*----------------------------------------------------------------------
* Commande "temp"
* lit la température de tous les DS18B20 sur le bus 1-wire
*/
int cmdeTemp(void)
{
ouvreSession();
// envoie une commande Convert T à tous les DS18B20
// en activant le strong pullup pendant 750 ms
OWReset();
OWTouchByte(0xcc); // cmd "skip ROM"
OWLevel(LEVEL_SET, LEVEL_STRONG_PULLUP, PRIMED_BYTE);// active le strong pullup
OWTouchByte(0x44); // cmd "convert T"
attente(750); // attente 750 ms
OWLevel(LEVEL_SET, LEVEL_NORMAL, PRIMED_NONE); // retire le strong pullup
// lit la température de tous les DS18B20 trouvés
tousDS18B20(tempDS18B20);
fermeSession();
return EXIT_SUCCESS;
}
/*----------------------------------------------------------------------
* Tout commence ici...
*/
void main(int argc, char **argv)
{
int precision;
int alarm;
// vérifie les arguments et appelle la bonne fonction
if (argc == 1)
usage();
// search
if (strcmp(argv[1], "search") == 0)
{
if (argc == 2)
alarm = FALSE;
else
{
if ((argc != 3) || strcmp(argv[2], "alarm") != 0)
usage();
alarm = TRUE;
}
fin(cmdeSearch(alarm));
}
// config <precision>
if (strcmp(argv[1], "config") == 0)
{
if (argc == 2)
precision = 12;
else
{
if ((argc != 3) || (sscanf(argv[2], "%d", &precision) != 1))
usage();
if ((precision < 9) || (precision > 12))
{
rc = 0;
fatal("la precision doit etre entre 9 et 12 bits");
}
}
fin(cmdeConfig(precision));
}
// temp
if (strcmp(argv[1], "temp") == 0)
{
if (argc != 2)
usage();
fin(cmdeTemp());
}
// dump
if (strcmp(argv[1], "dump") == 0)
{
if (argc != 2)
usage();
fin(cmdeDump());
}
// erreur si autre chose
usage();
}
_________________
station Orégon WMR 200
logiciel Xnet version 2012-03-17a et Graphweather V 3.0.15
http://mapetitemeteo.esy.es/