|
|
View previous topic :: View next topic |
Author |
Message |
Swys
Joined: 24 Feb 2010 Posts: 22
|
1-Wire Search ROM |
Posted: Tue Apr 06, 2010 3:04 am |
|
|
Hi all,
If anyone can help me with this problem, I will appreciate it a lot!
I am using a PIC24HJ128GP502 with a 20MHz clock and I am trying to interface with a DS18B20 temperature sensor. At the moment I am able to get a result from a single temp sensor, but I would like to interface with more than one at a time.
My problem is that when I implement the SEARCH ROM function and try to find devices, my UART continuously outputs 0xFF, even though I don't call printf... This is quite strange.
I tried to implement the SEARCH ROM function myself, but after a while gave up and used the code cotestatnt put in the code library. But alas, I still have the same problem.
Here is my code, with the code from cotestatnt:
one_wire.c
Code: | #ifndef ONE_WIRE_C
#define ONE_WIRE_C
#define OW_PIN PIN_A4
// Global variables
int8 RomBytes[8];
int8 lastDiscrep = 0;
short doneFlag = 0;
int8 FoundROM[9][8]; // Table of found ROM codes, 8 bytes for each
int8 numROMs;
int8 dowcrc; // crc is accumulated in this variable
/* OWWriteBit()
* Description:
* Writes a single bit on the 1-Wire bus
* Returns:
* Nothing
*/
void OWWriteBit(int8 bitval)
{
if (bitval)
{
//Write '1' bit
output_low(OW_PIN);
delay_us(6);
output_float(OW_PIN);
delay_us(64);
}
else
{
//Write '0' bit
output_low(OW_PIN);
delay_us(60);
output_float(OW_PIN);
delay_us(10);
}
}
/* OWReadBit()
* Description:
* Reads a single bit from the 1-Wire bus
* Returns:
* The result from the read
*/
int8 OWReadBit(void)
{
int8 value;
output_low(OW_PIN);
delay_us(6);
output_float(OW_PIN);
delay_us(9);
value = input(OW_PIN);
delay_us(55);
return value;
}
/* OWReset()
* Description:
* Reset the 1-Wire bus slave devices and ready them for a command
* Returns:
* 0 = Device(s) present
* 1 = No device present
*/
int1 OWReset(void)
{
int1 value = 0;
output_low(OW_PIN);
delay_us(480); //Pull wire LOW for minimum of 480us
output_float(OW_PIN); //Let the line recover to its HIGH state
delay_us(80); //Wait for the device to transmit its presence
value = input(OW_PIN); //Receive device present signal
delay_us(400); //Complete the reset time slot
return value;
}
/* OWWriteByte()
* Description:
* Write a byte of data to the 1-Wire slaves
* Returns:
* Nothing
*/
void OWWriteByte(int8 data)
{
int8 i;
for (i = 0; i < 8; i++)
{
output_low(OW_PIN);
delay_us(2);
output_bit(OW_PIN, shift_right(&data, 1, 0));
delay_us(60);
output_float(OW_PIN);
delay_us(2);
}
}
/* OWReadByte()
* Description:
* Read a byte of data from the 1-Wire slaves
* Returns:
* A byte of data
*/
int8 OWReadByte(void)
{
int8 i, data;
for (i = 0; i < 8; i++)
{
output_low(OW_PIN);
delay_us(2);
output_float(OW_PIN);
delay_us(8);
shift_right(&data, 1, input(OW_PIN));
delay_us(120);
}
return data;
}
//calc_CRC - INTERNAL FUNCTION
//Purpose: To calculate an 8-bit CRC based on a polynomial and the series
// of data bytes
//Note: Polynomial used x^8 + x^5 + x^4 + 1 = 10001100
//Inputs: A pointer to an array of the data bytes and an int saying how many
// bytes there are in the data array
//Outputs: An int8 which is the calculated CRC
int8 calc_CRC(int8* data, int8 bytes)
{
#define CRC_POLY 0x8C
int8 shift_register = 0, i, datab, bits;
for(i = 0; i < bytes; ++i)
{
datab = *(data + i);
for(bits = 0; bits < 8; ++bits)
{
if(bit_test((shift_register ^ datab), 0))
{
shift_register = shift_register >> 1;
shift_register ^= CRC_POLY;
}
else
{
shift_register = shift_register >> 1;
}
datab = datab >> 1;
}
}
return shift_register;
} //calc_CRC
// One wire crc
int8 ow_crc(int8 x)
{
dowcrc = calc_CRC(x,8);
return dowcrc;
}
/* OWNext()
* Description:
* Searches for the next device on the 1-Wire device
* Result:
* Retuns false if no more devices are found
*/
int8 OWNext(void)
{
int8 m = 1; // ROM Bit index
int8 n = 0; // ROM Byte index
int8 k = 1; // Bit mask
int8 x = 0;
int8 discrepMarker = 0;
int8 g; // Output bit
int8 nxt; // Return value
short flag;
nxt = FALSE; // Reset next flag to false
dowcrc = 0; // Reset the dowcrc
flag = OWReset();
if (flag||doneFlag) // If no parts return false
{
lastDiscrep = 0; // Reset the search
return FALSE;
}
OWWriteByte(0xF0); // Send SearchROM command
do
{
x = 0;
if (OWReadBit() == 1)
x = 2;
delay_us(120);
if (OWReadBit() == 1)
x |= 1; // And it's complement
if (x == 3) // There are no devices on the one wire bus
break;
else
{
if (x > 0) // All devices coupled have 0 or 1
g = x >> 1; // Bit write value for search
// If this discrepancy is before the last discrepancy on a previous
// Next then pick the same as last time.
else
{
if (m < lastDiscrep)
g = ((RomBytes[n] & k) > 0);
// If equal to last pick 1
else
g = (m == lastDiscrep); // If not then pick 0
// If 0 was picked then record position with mask k
if (g == 0) discrepMarker = m;
}
// Isolate bit in ROM[n] with mask k
if (g == 1) RomBytes[n] |= k;
else RomBytes[n] &= ~k;
OWWriteBit(g); // ROM search write
m++; // Increment bit counter m
k = k << 1; // and shift the bit mask k
// If the mask is 0 then go to new ROM
if (k == 0)
{ // Byte n and reset mask
ow_crc(RomBytes[n]); // Accumulate the crc
n++;
k++;
}
}
} while (n < 8); // Loop through until through all ROM bytes 0-7
if (m < (65||dowcrc)) // If search was unsuccessful then
lastDiscrep = 0; // reset the last Discrepancy to zero
else // Search was successful, so set lastDiscrep, lastOne, nxt
{
lastDiscrep = discrepMarker;
doneFlag = (lastDiscrep == 0);
nxt = TRUE; // Indicates search not yet complete, more parts remain
}
return nxt;
}
/* OWFirst()
* Description:
* Search for the first device on the 1-Wire bus
* Returns:
* The result of OWNext()
*/
int8 OWFirst(void)
{
lastDiscrep = 0;
doneFlag = FALSE;
return OWNext(); // Call Next and return it's return value;
}
/* OWFindDevices()
* Description:
* Searches for all the devices on the 1-Wire bus
* Returns:
* Nothing
*/
int8 OWFindDevices(void)
{
int8 m, cont = 0;
if(!OWReset())
{
if(OWFirst()) // Begins when at least one part found
{
numROMs = 0;
do
{
numROMs++;
cont++;
for (m=0;m<8;m++)
{
FoundROM[numROMs][m] = RomBytes[m];
}
} while (OWNext()); // Continues until no additional
}
}
return cont;
}
#endif |
main.h
Code: | #ifndef MAIN_H
#define MAIN_H
#include<24HJ128GP502.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOWRTB //Boot block not write protected
#FUSES NOBSS //No boot segment
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#FUSES PR //Primary Oscillator
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES WINDIS //Watch Dog Timer in non-Window mode
#FUSES WPRES128 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16 //Watch Dog Timer PostScalar 1:32768
#FUSES NOPUT //No Power Up Timer
#FUSES IOL1WAY //Allows only one reconfiguration of peripheral pins
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES NORSS //No secure segment RAM
#FUSES NOSSS //No secure segment
#FUSES NOWRTSS //Secure segment not write protected
#FUSES NORBS //No Boot RAM defined
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOCOE //Device will reset into operational mode
#FUSES NOJTAG //JTAG disabled
#FUSES ICSP1 //ICD uses PGC1/PGD1 pins
#FUSES NOALTI2C //I2C mapped to alternate pins
#use delay(clock=20000000)
#pin_select U1TX=PIN_B7
#pin_select U1RX=PIN_B5
#use rs232(UART1, baud=9600,parity=N,bits=8)
#endif //MAIN_H |
main.c
Code: | #include "main.h"
#include "one_wire.c"
void main()
{
int8 devCount = 0;
devCount = OWFindDevices();
printf("\n\rNumber of devices found: %u\n\r", devCount);
} |
I am using the version 4.104 of the CCS compiler. |
|
|
Swys
Joined: 24 Feb 2010 Posts: 22
|
|
Posted: Tue Apr 06, 2010 7:03 am |
|
|
OK, I got it working. I rewrote the code in the Maxim Application Note 187. Now I am able to get the number of devices, but it seems that the ROM numbers of the sensors are incorrect. If I program the PIC and run the program, I get one set of ROM numbers for the two sensors I've connected for testing. When I power down the circuit and power it up again, I get a completely different set of numbers. When I reprogram the PIC, I get the ROM numbers that I got when I first programmed the PIC.
This must mean that my code is wrong somewhere...can someone please have a look at it? I can't seem to find the problem...There must be something wrong with my OWNext() function.
Oh, and another turn of events is that, as soon as I have 3 sensors connected, the function goes completely haywire.
main.c
Code: | #include "main.h"
#include "one_wire.c"
int8 devCount = 0;
void main()
{
int8 i = 0;
printf("\n\rDetecting 1-Wire devices...\n\r");
if (OWReset())
printf("No 1-Wire devices found\n\r");
else
{
printf("1-Wire device(s) detected!\n\r");
printf("Finding 1-Wire device(s)...\n\r");
devCount = OWFindDevices();
printf("Found %u devices", devCount);
}
} |
one_wire.c
Code: | #ifndef ONE_WIRE_C
#define ONE_WIRE_C
#define OW_PIN PIN_A4
// Global variables
int8 LastDeviceFlag;
int8 LastDiscrepancy;
int8 LastFamilyDiscrepancy;
int8 last_zero;
int8 ROM_NO[8];
int8 ROM_LIST[10][8]; //List of ROM codes
int8 crc8;
/* OWWriteBit()
* Description:
* Writes a single bit on the 1-Wire bus
* Returns:
* Nothing
*/
void OWWriteBit(int8 bitval)
{
if (bitval)
{
//Write '1' bit
output_low(OW_PIN);
delay_us(6);
output_float(OW_PIN);
delay_us(64);
}
else
{
//Write '0' bit
output_low(OW_PIN);
delay_us(60);
output_float(OW_PIN);
delay_us(10);
}
}
/* OWReadBit()
* Description:
* Reads a single bit from the 1-Wire bus
* Returns:
* The result from the read
*/
int8 OWReadBit(void)
{
int8 value;
output_low(OW_PIN);
delay_us(6);
output_float(OW_PIN);
delay_us(9);
value = input(OW_PIN);
delay_us(55);
return value;
}
/* OWReset()
* Description:
* Reset the 1-Wire bus slave devices and ready them for a command
* Returns:
* 0 = Device(s) present
* 1 = No device present
*/
int1 OWReset(void)
{
int1 value = 0;
output_low(OW_PIN);
delay_us(480); //Pull wire LOW for minimum of 480us
output_float(OW_PIN); //Let the line recover to its HIGH state
delay_us(80); //Wait for the device to transmit its presence
value = input(OW_PIN); //Receive device present signal
delay_us(400); //Complete the reset time slot
return value;
}
/* OWWriteByte()
* Description:
* Write a byte of data to the 1-Wire slaves
* Returns:
* Nothing
*/
void OWWriteByte(int8 data)
{
int8 i;
for (i = 0; i < 8; i++)
{
output_low(OW_PIN);
delay_us(2);
output_bit(OW_PIN, shift_right(&data, 1, 0));
delay_us(60);
output_float(OW_PIN);
delay_us(2);
}
}
/* OWReadByte()
* Description:
* Read a byte of data from the 1-Wire slaves
* Returns:
* A byte of data
*/
int8 OWReadByte(void)
{
int8 i, data;
for (i = 0; i < 8; i++)
{
output_low(OW_PIN);
delay_us(2);
output_float(OW_PIN);
delay_us(8);
shift_right(&data, 1, input(OW_PIN));
delay_us(120);
}
return data;
}
//calc_CRC - INTERNAL FUNCTION
//Purpose: To calculate an 8-bit CRC based on a polynomial and the series
// of data bytes
//Note: Polynomial used x^8 + x^5 + x^4 + 1 = 10001100
//Inputs: A pointer to an array of the data bytes and an int saying how many
// bytes there are in the data array
//Outputs: An int8 which is the calculated CRC
int8 calc_CRC(int8* data, int8 bytes)
{
#define CRC_POLY 0x8C
int8 shift_register = 0, i, datab, bits;
for(i = 0; i < bytes; ++i)
{
datab = *(data + i);
for(bits = 0; bits < 8; ++bits)
{
if(bit_test((shift_register ^ datab), 0))
{
shift_register = shift_register >> 1;
shift_register ^= CRC_POLY;
}
else
{
shift_register = shift_register >> 1;
}
datab = datab >> 1;
}
}
return shift_register;
} //calc_CRC
// One wire crc
int8 ow_crc(int8 x)
{
crc8 = calc_CRC(x,8);
return crc8;
}
/* OWNext()
* Description:
* Searches for the next device on the 1-Wire device
* Result:
* Retuns false if no more devices are found
*/
int8 OWNext(void)
{
int8 id_bit;
int8 cmp_id_bit;
int8 id_bit_number;
int8 search_direction;
int8 rom_byte_number;
int8 search_result;
int8 rom_byte_mask;
//Initialize variables
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = 0;
crc8 = 0;
if (!LastDeviceFlag)
{
if (OWReset())
{
//Reset the search
LastDiscrepancy = 0;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
return false;
}
OWWriteByte(0xF0);
//Do the search
do
{
id_bit = OWReadBit();
//delay_us(120);
cmp_id_bit = OWReadBit();
//printf("id_bit = %u\n\rcmp_id_bit = %u", id_bit, cmp_id_bit);
if ((id_bit == 1) && (cmp_id_bit == 1))
break;
else
{
//All devices coupled have 0 or 1
if (id_bit != cmp_id_bit)
search_direction = id_bit;
else
{
if (id_bit_number < LastDiscrepancy)
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
else
search_direction = (id_bit_number == LastDiscrepancy);
if (search_direction == 0)
{
last_zero = id_bit_number;
if (last_zero < 9)
LastFamilyDiscrepancy = last_zero;
}
}
if (search_direction == 1)
ROM_NO[rom_byte_number] |= rom_byte_mask;
else
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
OWWriteBit(search_direction);
id_bit_number++;
shift_left(rom_byte_mask, 1, 0);
if (rom_byte_mask == 0)
{
ow_crc(ROM_NO[rom_byte_number]);
rom_byte_number++;
rom_byte_mask = 1;
}
}
}while(rom_byte_number < 8);
if (!((ID_bit_number < 65) || (crc8 != 0)))
{
LastDiscrepancy = last_zero;
if (LastDiscrepancy == 0)
LastDeviceFlag = true;
search_result = true;
}
}
if (!search_result || !ROM_NO[0])
{
LastDiscrepancy = 0;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
search_result = false;
}
return search_result;
}
/* OWFirst()
* Description:
* Search for the first device on the 1-Wire bus
* Returns:
* The result of OWNext()
*/
int8 OWFirst(void)
{
LastDiscrepancy = 0;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
return OWNext();
}
/* OWFindDevices()
* Description:
* Searches for all the devices on the 1-Wire bus
* Returns:
* Nothing
*/
int8 OWFindDevices(void)
{
int8 i;
int8 count = 0;
int8 rom_count = 0;
if (OWFirst())
{
rom_count = 0;
do
{
rom_count++;
count++;
for (i = 0; i < 8; i++)
{
ROM_LIST[rom_count][i] = ROM_NO[i];
}
printf("Device %u found: ", rom_count);
printf("%X %X %X %X %X %X %X %X\n\r",
ROM_LIST[rom_count][7], ROM_LIST[rom_count][6],
ROM_LIST[rom_count][5], ROM_LIST[rom_count][4],
ROM_LIST[rom_count][3], ROM_LIST[rom_count][2],
ROM_LIST[rom_count][1], ROM_LIST[rom_count][0]);
} while (OWNext());
}
return count;
}
#endif |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Apr 06, 2010 11:24 am |
|
|
Code: | rom_count = 0;
do
{
rom_count++; <-- move this ....
count++;
for (i = 0; i < 8; i++)
{
ROM_LIST[rom_count][i] = ROM_NO[i];
}
<-- ... to here | Move the rom_count++ to after the for-loop. Now your first found ROM will be random data and if 8 ROM's are found you'll be writing out of the array boundaries, overwriting other variables. |
|
|
Swys
Joined: 24 Feb 2010 Posts: 22
|
|
Posted: Wed Apr 07, 2010 4:40 am |
|
|
Thanks ckielstra. Unfortunately, that didn't work...
Ok, so I've found the Book of iButtonĀ® Standards (App Note 937). In section C.3. they discuss the Search ROM routine. I've reprogrammed my functions...AND IT WORKS! With one exception...if I have more than two sensors on the bus, it goes into a loop where it finds only the first two devices (which incidentily have similar ROM numbers, with little difference). I think my OWNext() function does not split the search path at the right location.
Below are my new OWNext(), OWFirst() and OWFindDevices() functions. Can anyone please look at this and help me find the problem?
Thanks.
Code: | /* OWNext()
* Description:
* Searches for the next device on the 1-Wire device
* Result:
* Retuns false if no more devices are found
*/
int8 OWNext(void)
{
int8 result;
int8 rom_index; //Counts to 64 for all the bits in the ROM number
int8 bit_index = 0; //When it is 8, a byte is completed
int8 discrepancy;
int8 bit_a;
int8 bit_b; //The complement reading of the devices
int8 rom_byte_index = 0;
int8 bit_val;
result = false;
if (LastDeviceFlag == true)
{
LastDeviceFlag = false;
return result;
}
if (OWReset())
{
LastDiscrepancy = 0;
return result;
}
else
{
//Presence signal detected
rom_index = 1;
discrepancy = 0;
//Send search command
OWWriteByte(0xF0);
do
{
bit_a = OWReadBit();
bit_b = OWReadBit();
if ((bit_a == 1) && (bit_b == 1))
{
//No device found
LastDiscrepancy = 0;
return result;
}
else
if ((bit_a == 0) && (bit_b == 0))
{
//Discrepancy found
if (rom_index == LastDiscrepancy)
{
//Set ROM BIT(rom_index) = 1
bit_val = 1;
}
else
if (rom_index > LastDiscrepancy)
{
//Set ROM BIT(rom_index) = 0
bit_val = 0;
discrepancy = rom_index;
}
else
if (bit_val == 0)
{
discrepancy = rom_index;
}
else
{
//WAT GEBEUR HIER MET bit_val???
//MAAK HOM DALK 1???
}
}
else
{
//Set ROM BIT(rom_index) = bit_a
bit_val = bit_a;
}
if (bit_val == 0)
{
bit_clear(ROM_DATA[rom_byte_index], bit_index);
}
else
{
bit_set(ROM_DATA[rom_byte_index], bit_index);
}
//Send ROM BIT(rom_index) on 1-Wire bus
OWWriteBit(bit_val);
//Increment rom_index
rom_index++;
//Increment the current byte's bit_index
bit_index++;
if (bit_index == 8)
{
bit_index = 0;
rom_byte_index++;
}
}while (rom_index < 64);
LastDiscrepancy = discrepancy;
if (LastDiscrepancy == 0)
{
LastDeviceFlag = true;
result = true;
}
else
{
result = true;
}
return result;
}
}
/* OWFirst()
* Description:
* Search for the first device on the 1-Wire bus
* Returns:
* The result of OWNext()
*/
int8 OWFirst(void)
{
LastDiscrepancy = 0;
LastDeviceFlag = false;
return OWNext();
}
/* OWFindDevices()
* Description:
* Searches for all the devices on the 1-Wire bus
* Returns:
* Nothing
*/
int8 OWFindDevices(void)
{
int8 i;
int8 count = 0;
int8 rom_count = 0;
if (OWFirst())
{
count = 0;
do
{
count++;
printf("Device %u: ", count);
for (i = 7; i >= 0; i--)
{
printf("%X ", ROM_DATA[i]);
}
printf("\n\r");
} while (OWNext());
}
return count;
} |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|