Page 1 sur 1

Soucis de communication 1-wire

Publié : 23 mai 2007 16:24
par pulsar67
Bonjour à tous,

Tout d'abord, comme je débarque sur le forum, brève présentation : jeune ingénieur en électronique, je suis aussi passionné par tout ce qui touche à l'embarqué. A côté de cela, ma principale passion est l'astronomie, et plus particulièrement l'astrophoto. Depuis quelques temps je cherche à mettre à profit mes compétences en électronique pour apporter de nouvelles idées pour améliorer le quotidien de l'astronome amateur.

Actuellement, je travaille principalement sur un projet dont le but est de centraliser un maximum de fonctionnalités afin de rendre l'installation de l'astronome la plus autonome possible, et ainsi réduire au maximum le nombre de câbles allant jusqu'au PC (en astrophoto, le PC portable devient quasiment un outil incontournable permettant le contrôle simultané de la monture, le focuser, la caméra CCD, la régulation de température de la CCD, la webcam, la longue pose de la webcam, etc...).

Ce projet est structuré autour d'un ARM7 de chez NXP (LPC2148). Depuis quelques jours, je travaille sur une partie communication en 1-wire permettant le contrôle de différentes températures à l'aide de sondes DS18S20. Seulement voilà... ça ne veut pas vraiment, et c'est là que j'aurais besoin de votre aide.

Pour l'instant, le DS18S20 répond bien au reset... mais rien de plus, quand je veux relire, j'ai 0xFF dans chaque registre. Comme c'est la première fois que je fais du 1-wire, je suis un peu bloqué.

Quelqu'un saurait-il m'aider?

Voici les différentes fonction :

Fonction Reset :

Code : Tout sélectionner

int reset1wire(void)
{
	int status;	

	// configurer P0.28 en sortie
	IODIR0 |= 0x10000000;
	
	// P0.28 = 0
	IOCLR0 = 0x10000000;
	
	// tempo 480us
	delay(480);
	// configurer P0.28 en entrée
	IODIR0 &= 0xEFFFFFFF;

	// tempo 70us
	delay(70);
	// lecture
	if(!(IOPIN0 & 0x10000000))status = 1;
	else status = 0;

	IODIR0 |= 0x10000000;
	delay(410);

	return status;
}
Envoi d'un bit :

Code : Tout sélectionner

void send1wirebit(char bit)
{
	if(bit)
	{
		// configurer P0.28 en sortie
		IODIR0 |= 0x10000000;
		// P0.28 = 1
		IOSET0 = 0x10000000;
		// attente 6us
		delay(6);
		// configurer P0.28 en entrée
		IODIR0 &= 0xEFFFFFFF;

		// attente 64us
		delay(64);
	}
	else
	{
		// configurer P0.28 en sortie
		IODIR0 |= 0x10000000;
		// P0.28 = 0
		IOCLR0 = 0x10000000;
		// attente 60us
		delay(60);
		// configurer P0.28 en entrée
		IODIR0 &= 0xEFFFFFFF;
		// attente 10us
		delay(10);
	}	
}
Envoi d'un octet :

Code : Tout sélectionner

void send1wire(char data)
{
	char i;
	
	// boucle envoi
	for(i=0;i<8;i++)
	{
		// envoi bit
		send1wirebit(data & 0x01);
		// décalage de 1 à droite
		data >>= 1;
	}
}
Lecture d'un bit :

Code : Tout sélectionner

char read1wirebit(void)
{
	char result = 0x00;
	// configurer P0.28 en sortie
	IODIR0 |= 0x10000000;
	// P0.28 = 0
	IOCLR0 = 0x10000000;
	// attente 6us
	delay(6);
	// configurer P0.28 en entrée
	IODIR0 &= 0xEFFFFFFF;
	// attente 9us
	delay(9);
	// lecture
	result = ((IOPIN0 & 0x10000000)>>28);
	
	// attente 55us (pour compléter le time slot)
	delay(55);
	// renvoi résultat lecture
	return result;
}
Lecture d'un octet :

Code : Tout sélectionner

char read1wire(void)
{
	int i;
	char result = 0x00;
	for(i=0;i<8;i++)
	{
		result >>= 1;
		if(read1wirebit())result |= 0x80;
	}
	return result;
}
Fonction demandant de faire une conversion de température puis sensée la relire (je précise que les messages sont bien renvoyées sur la console donc que la fonction arrive à s'exécuter jusqu'au bout) :

Code : Tout sélectionner

int readtemperature(void)
{
	char templow, temphigh, th, tl, res1, res2, countremain, countperc, crc;

	if(!reset1wire())return 0;
	else
	{
		// Skip ROM
		send1wire(0xCC);
		// Convert T
		send1wire(0x44);
		// attente conversion (750ms!)
		while(read1wire()!=0xFF); 
		// reset
		if(!reset1wire())return 0;
		else
		{
			// Skip ROM
			send1wire(0xCC);
			// Read Scratchpad
			send1wire(0xBE);
			// Read byte 1
			templow = read1wire();
			// Read byte 2
			temphigh = read1wire();
			// Read byte 3
			th = read1wire();
			// Read byte 4
			tl = read1wire();
			// Read byte 5
			res1 = read1wire();
			// Read byte 6
			res2 = read1wire();
			// Read byte 7
			countremain = read1wire();
			// Read byte 8
			countperc = read1wire();
			// Read byte 9
			crc = read1wire();
			
			// Write results
			putstr("templow = ");puthex(templow);putstr("\n");
			putstr("temphigh = ");puthex(temphigh);putstr("\n");
			putstr("th = ");puthex(th);putstr("\n");
			putstr("tl = ");puthex(tl);putstr("\n");
			putstr("res1 = ");puthex(res1);putstr("\n");
			putstr("res2 = ");puthex(res2);putstr("\n");
			putstr("countremain = ");puthex(countremain);putstr("\n");
			putstr("countperc = ");puthex(countperc);putstr("\n");
			putstr("crc = ");puthex(crc);putstr("\n");
			return 1;
		}
	}
}
Ai-je fait une connerie quelque part?

Merci d'avance pour vos réponses :)

A+
Gilles

Publié : 29 mai 2007 13:35
par pulsar67
personne ne peut m'aider? pourtant, si j'ai posté ici, c'est bien parce qu'il y en a qui ont déjà fait du 1-wire...

1-wire

Publié : 30 mai 2007 10:53
par Matthieu
Bonjour,

une premiere piste:
Dans ta fonction void send1wirebit(char bit),
quelque soit la valeur de ton bit, tu fais la meme chose dans le if et le else.(tu ecrirait un 0 sur le port P0.28 )

Matthieu

Publié : 30 mai 2007 13:46
par pulsar67
Oupss! Merci!

Ah c'est beau le copier-coller... Pourtant, j'avais beau revoir mon code (pourtant, il me semblais avoir fait une simul), j'ai dû passer là dessus 10x sans m'en rendre compte...

Bon, je vais corriger ça ce soir, je verrai ce que ça dit.

Encore merci!

A+
Gilles

Publié : 31 mai 2007 13:18
par pulsar67
Bon, c'était pas ça.. je relis toujours 0xFFFF comme si le bus restait scotché à 1... et le composant répond toujours au reset.

Publié : 31 mai 2007 17:30
par nanick
bonjour,
au dela du code, avez vous la possibilité de mettre un oscillo sur la ligne pour voir s'il ya des changement d'état lors d'une comm.

ça peut aider.

A+

Publié : 01 juin 2007 9:39
par pulsar67
Bonjour,

C'est la prochaine étape... il faut que je voie s'il m'est possible d'emprunter un oscillo numérique au boulot car celui que je possède, c'est galère : un simple analogique tout bête, c'est chaud quand on ne peut pas faire un "run/stop" ;)

C'est un peu frustrant de chercher sans savoir à quoi ressemblent les signaux...

A+

Publié : 06 juin 2007 13:26
par pulsar67
Finalement, j'ai refait tout le code de la partie 1-wire d'une autre manière, en m'inspirant d'un driver existant, et ça marche.... (à un bug près : ça fonctionne avec un DS1820 et pas avec un DS18S20)