TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: morpheo81 en 06 de Mayo de 2003, 11:21:00
-
Estoy intentando hacer un termometro con un pic 16f84 y un ds1820, que es un dispositivo por bus de 1 linea.
Mi problema es que quiero conectar mas de un ds1820 al bus pero no consigo ke me distinga entre unos y otros, solo me funciona con un solo dispositivo.
¿alguien sabe algo sobre este tema?, ¿alguien concoce alguna pagina en castellano sobre este tema?
Muchas gracias
-
Prueba con este programa para picbasic pro
los valores
$xx,$xx,$xx,$xx,$xx,$xx,$xx,$xx
$yy,$yy,$yy,$yy,$yy,$yy,$yy,$yy
son los de tus sensores (cada uno es diferente)en hexadecimal
DQ VAR PortB.0 "patilla donde conectas el 1 wire
Listo VAR BIT
Temp VAR WORD
Temp2 VAR WORD
Sensor_1:
OWOUT DQ, 1, [$55,$xx,$xx,$xx,$xx,$xx,$xx,$xx,$xx,$44]
Loop_1:
OWIN DQ, 4, [Listo]
IF Listo = 0 THEN Loop_1
OWOUT DQ, 1, [$55,$xx,$xx,$xx,$xx,$xx,$xx,$xx,$xx,$BE]
OWIN DQ, 2, [Temp.LOWBYTE,Temp.HIGHBYTE]
Sensor_2:
OWOUT DQ, 1, [$55,$yy,$yy,$yy,$yy,$yy,$yy,$yy,$yy,$44]
Loop_2:
OWIN DQ, 4, [Listo]
IF Listo = 0 THEN Loop_2
OWOUT DQ, 1, [$55,$yy,$yy,$yy,$yy,$yy,$yy,$yy,$yy,$BE]
OWIN DQ, 2, [Temp2.LOWBYTE,Temp2.HIGHBYTE]
-
te agradezco la respuesta pero no he utilizado nunka picbasic pro y es que el resto del programa ya lo tengo hecho kon mplab buscare algun traductor o algo asi pk sino no le veo soulucion. De todas formas gracias.
-
Hola frenadol501!
Me parecio muy interesante el codigo que posteaste para manejar mas de un DS1820. El problema que tengo es que uso otro basic, que no maneja directamente el protocolo onewire, por lo tanto lo hago mediante mis propias rutinas. Me gustaria que me hagas el favor de pasarme en privado, copiando y pegando desde la ayuda de tu basic, la sintaxis de las intrucciones que usas OWIN y ONWOUT (sobre todo que es el sefundo parametro de OWIN, no me doy cuenta que puede ser), a fin de implementarlas como rutinas y ver que pasa...puede ser?
Desde ya, gracias!
PD: Si te sirven de algo, las rutinas que tengo hechas te las puedo pasar....
-
:-/Bien primero comentarte que he trabajado mucho con el DS18B20, lo primero que creo que debes hacer es hacerte con el datasheets de la red 1 wire, aqui te explica de forma detallada el funcionamiento. Pero bueno te voy a ahorrar algo de curro.
Creo que debes comenzar por leer el código ROM de varios dispositivos, morpheo81 si has conseguido leer la temperatura de un sólo dispositivo creeme lo tienes casi hecho.
Este es el código que yo he utilizado, bueno la libreria:
////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
//
unsigned char ROM_NO[8];
unsigned char ROM[8]; // ROM Bit
unsigned char lastDiscrep = 0; // last discrepancy
unsigned char doneFlag = 0; // Done flag
unsigned char FoundROM[5][8]; // table of found ROM codes
unsigned char numROMs;
unsigned char dowcrc;
unsigned char dscrc_table[] = {
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
unsigned char page_data[32];
//////////////////////////////////////////////////////////////////////////////
// OW_RESET - performs a reset on the one-wire bus and
// returns the presence detect. Reset is 480us, so delay
// value is (480-24)/16 = 28.5 - we use 29. Presence checked
// another 70us later, so delay is (70-24)/16 = 2.875 - we use 3.
//
unsigned char ow_reset(void)
{
unsigned char presence;
output_low(DQ); //pull DQ line low
delay_us(480);// leave it low for 480us
output_bit(DQ,1); // allow line to return high
delay_us(72); // wait for presence
presence =input(DQ); // get presence signal
delay_us(424);
return(presence); // presence signal returned
} // 0=presence, 1 = no part
//////////////////////////////////////////////////////////////////////////////
// READ_BIT - reads a bit from the one-wire bus. The delay
// required for a read is 15us, so the DELAY routine won't work.
// We put our own delay function in this routine in the form of a
// for() loop.
//
unsigned char read_bit(void)
{
unsigned char i;
output_bit(DQ,0); // pull DQ low to start timeslot
output_bit(DQ,1); // then return high
delay_us(15); // delay 15us from start of timeslot
return(input(DQ)); // return value of DQ line
}
//////////////////////////////////////////////////////////////////////////////
// WRITE_BIT - writes a bit to the one-wire bus, passed in bitval.
//
void write_bit(char bitval)
{
output_bit(DQ,0); // pull DQ low to start timeslot
if(bitval==1) output_bit(DQ,1); // return DQ high if write 1
delay_us(104); // hold value for remainder of timeslot
output_bit(DQ,1);
}// Delay provides 16us per loop, plus 24us. Therefore delay(5) = 104us
//////////////////////////////////////////////////////////////////////////////
// READ_BYTE - reads a byte from the one-wire bus.
//
unsigned char read_byte(void)
{
unsigned char i;
unsigned char value=0;
for (i=0;i<8;i++)
{
if(read_bit()) value|=0x01<<i; // reads byte in, one byte at a time and then
// shifts it left
delay_us(120); // wait for rest of timeslot
}
return(value);
}
//////////////////////////////////////////////////////////////////////////////
// WRITE_BYTE - writes a byte to the one-wire bus.
//
void write_byte(char val)
{
unsigned char i;
unsigned char temp;
for (i=0; i<8; i++) // writes byte, one bit at a time
{
temp = val>>i; // shifts val right 'i' spaces
temp &= 0x01; // copy that bit to temp
write_bit(temp); // write bit in temp into
}
delay_us(104);
}
//////////////////////////////////////////////////////////////////////////////
// ONE WIRE CRC
//
unsigned char ow_crc( unsigned char x)
{
dowcrc = dscrc_table[dowcrc^x];
return dowcrc;
}
/////////////////////////////////////////////////////////////////////////////////
// NEXT
// The Next function searches for the next device on the 1-wire bus. If
// there are no more devices on the 1-wire then false is returned.
//
unsigned char Next(void)
{
unsigned char m = 1; // ROM Bit index
unsigned char n = 0; // ROM Byte index
unsigned char k = 1; // bit mask
unsigned char x = 0;
unsigned char discrepMarker = 0; // discrepancy marker
unsigned char g; // Output bit
unsigned char nxt; // return value
int flag;
nxt = FALSE; // set the next flag to false
dowcrc = 0; // reset the dowcrc
flag = ow_reset(); // reset the 1-wire
if(flag||doneFlag) // no parts -> return false
{
lastDiscrep = 0; // reset the search
return FALSE;
}
write_byte(0xF0); // send SearchROM command
do
// for all eight bytes
{
x = 0;
if(read_bit()==1) x = 2;
delay_us(120);
if(read_bit()==1) x |= 1; // and its complement
if(x ==3) // there are no devices on the 1-wire
break;
else
{
if(x>0) // all devices coupled have 0 or 1
g = x>>1; // bit write value for search
else
{
// if this discrepancy is before the last
// discrepancy on a previous Next then pick
// the same as last time
if(m<lastDiscrep)
g = ((ROM[n]&k)>0);
else // if equal to last pick 1
g = (m==lastDiscrep); // if not then pick 0
// if 0 was picked then record
// position with mask k
if (g==0) discrepMarker = m;
}
if(g==1) // isolate bit in ROM[n] with mask k
ROM[n] |= k;
else
ROM[n] &= ~k;
write_bit(g); // ROM search write
m++; // increment bit counter m
k = k<<1; // and shift the bit mask k
if(k==0) // if the mask is 0 then go to new ROM
{ // byte n and reset mask
ow_crc(ROM[n]); // accumulate the CRC
n++; k++;
}
}
}while(n<8); //loop until through all ROM bytes 0-7
if(m<65||dowcrc) // if search was unsuccessful then
lastDiscrep=0; // reset the last discrepancy to 0
else
{
// search was successful, so set lastDiscrep,
// lastOne, nxt
lastDiscrep = discrepMarker;
doneFlag = (lastDiscrep==0);
nxt = TRUE; // indicates search is not complete yet, more
// parts remain
}
return nxt;
}
////////////////////////////////////////////////////////////////////////////
// FIRST
// The First function resets the current state of a ROM search and calls
// Next to find the first device on the 1-wire bus.
//
unsigned char First(void)
{
lastDiscrep = 0; // reset the rom search last discrepancy global
doneFlag = FALSE;
return Next(); // call Next and return its return value
}
////////////////////////////////////////////////////////////////////////////////
// FIND DEVICES
void FindDevices(void)
{
unsigned char m;
if(!ow_reset()) //Begins when a presence is detected
{
if(First()) //Begins when at least one part is found
{
numROMs=0;
do
{
numROMs++;
for(m=0;m<8;m++){FoundROM[numROMs][m]=ROM[m]; //Identifies ROM
//number on found device
}
//printf("\nROM CODE =%02X%02X%02X%02X\n",FoundROM[4][7],FoundROM[4][6],FoundROM[4][5],FoundROM[4][4],FoundROM[4][3],FoundROM[4][2],FoundROM[4][1],FoundROM[4][0]);
}while (Next()&&(numROMs<10)); //Continues until no additional devices are found
}
}
}
/////////////////////////////////////////////////////////////////////////////
Debes saber que los tiempos de slots son distintos, por lo que en las funciones read_byte,read_bit,write_byte,write_bit y ow_reset debes cambiarlos(no se cuales son). Una vez corregido esto coloque los dispositivos que coloques los podrás observar mediante la variable numROMs, y en ROM[][], encuentras una estructura que si la recorres encuentras el código ROM de cada dispositivo, recuerda que yo he colocado A0 como pin DQ.
Espero que te sirva, no lees la temperatura con esto pero creo que te ayudará.