|
|
View previous topic :: View next topic |
Author |
Message |
psypersky
Joined: 06 Jul 2008 Posts: 13
|
One wire library search protocol HELP DS18S20 |
Posted: Thu Jul 31, 2008 3:48 pm |
|
|
Hi, im using one wire library but i have a problem, the functions ow_reset, and search supply, works fine, but when the program enter in the function Find_devices() inside, that function call first() and first call next(), and inside of next when next send write_byte(0xF0); (SearchROM command), then read the first two bits , and always read "1" in the first bit and "1" in the second bit that means there are not sensors conected, and i cant make that part work, i have the sensors conected im using DS18S20
i marked the errors with 2 lines of "####" , you can search the "####" and see where is the error..
Find_devices is called from the main file ans it's in the one wire library.
First() and Next() [Where the problem is] are in the one wire library too.
You can download the complete proyect from here:
http://rapidshare.com/files/133925184/Modulo_Temp_ds1820s.rar.html
This is the main file.
Code: | #include "C:\Archivos de programa\PICC\Examples\Modulo Temp ds1820s\Ds18S20.h"
#include <flex_LCD_ds18s20.C>
#define sensor_pin pin_a5
static int8 inteiro, decimal, i, num_devices;
static int1 parasite_power;
#include <ds1820.c>
int dados[9];
void procurar (void)//-------------------------------------------------------------
{
if(search_supply()){
parasite_power=TRUE;
printf(lcd_putc,"\fparasit true");
delay_ms(3000);
}
else{
parasite_power=FALSE;
printf(lcd_putc,"\fparasit false");
delay_ms(3000);
}
// printf(lcd_putc,"\fUNo!");
// delay_ms(1000);
if(ow_reset()){
printf(lcd_putc,"\fNenhum Disposit.\n Detectado! reset");
num_devices=0;
delay_ms(5000);
return;
}
// printf(lcd_putc,"\fDoSs!");
FindDevices(); //until here its fine, inside this function is the error ###################################################################################################################################
if(num_devices==numROMs)
return;
if(numROMs>num_devices)
printf(lcd_putc,"\fNovo Dispositivo\n Detectado");
else if(numROMs<num_devices)
printf(lcd_putc,"\f Um dispositivo\nfoi desconectado");
Delay_ms(400);
printf(lcd_putc,"\f A Indexar\nDispositivos...");
delay_ms(600);
printf(lcd_putc,"\fTotal Disp.: %u",numROMs);
delay_ms(2000);
printf(lcd_putc,"\f");
num_devices=numROMs;
} //final de funçao--------------------------------------------------------------------
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
// setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
lcd_init();
num_devices=0;//temp
procurar(); // procura todos os dispositivos presentes no bus
// printf(lcd_putc,"\fSali de procurar()");//temp
//delay_ms(500);
num_devices=numROMs; // guarda o numero de dispositivos encontrados
do{
// for(i=1;i<=numROMs;i++)
convert_temp(); // envia o comando para iniciar a conversao de temperatura
// para todos os dispositivos presentes no bus
for(i=1; i<=numROMs;i++){ // faz a leitura de todos os dispositivos
if(!read_temp(dados, i)) // lê a temperatura do dispositivo 'i'
procurar(); // se der erro, faz a procura de dispositivos
trata_temperatura(dados); // processa os valores
if(FoundROM[i][7]==0x35 && FoundROM[i][6]==0x00 && FoundROM[i][5]==0x08 && FoundROM[i][4]==0x00 && FoundROM[i][3]==0xc4 && FoundROM[i][2]==0xb0 && FoundROM[i][1]==0xf6 && FoundROM[i][0]==0x10){
//se o chip do exterior corresponde ao ROM
lcd_gotoxy(1,1);
printf(lcd_putc,"Ext.: %2u,%02u 'C ",inteiro, decimal);
}//if
if(FoundROM[i][7]==0xe1 && FoundROM[i][6]==0x00 && FoundROM[i][5]==0x08 && FoundROM[i][4]==0x00 && FoundROM[i][3]==0xc4 && FoundROM[i][2]==0x8f && FoundROM[i][1]==0xbb && FoundROM[i][0]==0x10){
//se o chip do interior corresponde ao ROM //E1000800C48FBB10
lcd_gotoxy(1,2);
printf(lcd_putc,"Int.: %02u,%02u 'C ",inteiro, decimal);
}//if
}// for
procurar(); // procura se existem novos dispositivos, ou se algum foi desconectado
}while(TRUE);
} |
This is the one wire library
Code: | //******************************************************************************
// onewire.c
//
// DESCRIÇAO GERAL: Driver para comunicaçoes sobre o bus ONEWIRE.
//
// * ow_reset(); Envia um pulso de reset, devolve: 0 se um ou mais dispositivos presentes
// 1 se nenhum dispositivo presente
//
// * read_bit(); Lê um bit do bus onewire
//
// * write_bit(bitval); escreve um bit 'bitval' no bus onewire
//
// * read_byte(); Lê um byte do bus onewire
//
// * write_byte(val); Escreve um byte 'val' no bus
//
// * ow_crc(x); Processa o valor de CRC
//
// * FindDevices(); Procura dispositivos no bus onewire
//
// * Send_MatchRom(); Envia o comando Match_rom e depois o endereço do dispositivo
//
//******************************************************************************
// Variaveis Globais
int8 ROMM[8]; // ROM bit
int8 lastDiscrep = 0;
short doneFlag = 0;
int8 FoundROM[7][8]; // Tabela dos codigos ROM encontrados, 8 bytes para cada um
int8 numROMs=0;
int8 dowcrc; // acumula o CRC
// crc lookup table
int8 const 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
};
//******************************************************************************
// DESCRIÇAO: Faz reset no bus
//
// INPUT: Nada
//
// OUTPUT: 0 se um dispositivo presente
// 1 se nenhum dispositivo presente
//------------------------------------------------------------------------------
int1 ow_reset(void)
{
int1 presence;
output_low(sensor_pin);
delay_us(488); // Min. 480uS
output_float(sensor_pin);
delay_us(72); // Takes 15 to 60uS for devices to respond
presence = input(sensor_pin);
delay_us(424); // Wait for end of timeslot
return(presence); //devolve 0 se um dispositivo esta presente
}
//******************************************************************************
//******************************************************************************
// DESCRIÇAO: Lê um bit no bus
//
// INPUT: nada
//
// OUTPUT: bit lido
//------------------------------------------------------------------------------
int8 read_bit(void)
{
output_low(sensor_pin);
delay_us(1); // 1uS min. Original code relied on 8051 being slow
output_float(sensor_pin);
delay_us(20); // Wait at least 15mS from start of time slot
return(input(sensor_pin)); // Delay to finish time slot (total 60 to 120uS)
} // must be done next.
//******************************************************************************
//
//******************************************************************************
// DESCRIÇAO: Escreve um bit no bus
//
// INPUT: bit a ser enviado para o bus
//
// OUTPUT: nada
//------------------------------------------------------------------------------
void write_bit(int8 bitval)
{
output_low(sensor_pin);
if(bitval == 1) {
delay_us(1); // 1uS min. Original code relied on 8051 being slow
output_float(sensor_pin);
}
delay_us(105); // Wait for end of timeslot
output_float(sensor_pin);
}
//******************************************************************************
//
//******************************************************************************
// DESCRIÇAO: Lê um byte do bus
//
// INPUT: nada
//
// OUTPUT: um byte lido do bus
//------------------------------------------------------------------------------
int8 read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0;i<8;i++)
{
if(read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//******************************************************************************
//
//******************************************************************************
// DESCRIÇAO: escreve um byte no bus
//
// INPUT: byte a ser enviado
//
// OUTPUT: nada
//------------------------------------------------------------------------------
void write_byte(int8 val)
{
int8 i;
int8 temp;
for (i=0;i<8;i++)
{
temp = val >> i;
temp &= 0x01;
write_bit(temp);
}
delay_us(105);
}
//******************************************************************************
//******************************************************************************
//DESCRIÇAO: Processa o valor de CRC recebido
//
// INPUT: Valor lido no bus
//
// OUTPUT: Valor processado
//------------------------------------------------------------------------------
int8 ow_crc(int8 x)
{
dowcrc = dscrc_table[dowcrc^x];
return dowcrc;
}
//******************************************************************************
//******************************************************************************
// DESCRIÇAO: Procura o proximo dispositivo no bus e armazena o seu serial
//
// INPUT: Nada
//
// OUTPUT: 1 se novos dispositivos encontrados
// 0 se nao houver novos dispositivos
//------------------------------------------------------------------------------
int8 Next(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 = ow_reset(); // igual a 1 si no hay dispositivos ..
if (flag||doneFlag) // If no parts return false y no estamos en first()...
{
lastDiscrep = 0; // Reset the search
return FALSE;
}
write_byte(0xF0); // Send SearchROM command
do
{
x = 0;
if (read_bit() == 1) x = 2;
delay_us(120);
if (read_bit() == 1) x |= 1; // And it's complement
//always read "1" and "1" HERE IS THE ERROR
################################
###########################################################################################################################
###########################################################################################################################
printf(lcd_putc,"\fFOUND %u",x);
//delay_ms(5000);
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 = ((ROMM[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) ROMM[n] |= k;
else ROMM[n] &= ~k;
write_bit(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(ROMM[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;
}
//******************************************************************************
//******************************************************************************
// DESCRIÇAO: Reseta a actual procura e chama a funçao 'Next()' para iniciar a
// procura do primeiro dispositivo no bus.
//
// INPUT: Nada
//
// OUTPUT: O valor da funçao Next().
//------------------------------------------------------------------------------
int8 First(void)
{
lastDiscrep = 0;
doneFlag = FALSE;
return Next(); // Call Next and return it's return value;
}
//******************************************************************************
//******************************************************************************
// DESCRIÇAO: Procura novos dispositivos no bus
//
// INPUT: Nada
//
// OUTPUT: Nada
//------------------------------------------------------------------------------
void FindDevices(void)
{
int8 m;
if(!ow_reset())//(Si hay un dispositivo presente) devuelve 0 si un dispositivo esta presente
{
if(First()) // Begins when at least one part found
{
numROMs = 0;
do
{
numROMs++;
for (m=0;m<8;m++)
{
FoundROM[numROMs][m] = ROMM[m]; // Identifies ROM no. on device
}
/*
printf("\r\nEndereco do dispositivo No %u: ",numROMs);
printf("%X%X%X%X%X%X%X%X\n\r",
FoundROM[numROMs][7],FoundROM[numROMs][6],FoundROM[numROMs][5],
FoundROM[numROMs][4],FoundROM[numROMs][3],FoundROM[numROMs][2],
FoundROM[numROMs][1],FoundROM[numROMs][0]);
*/
} while (Next() && (numROMs<10)); // Continues until no additional
// devices found.
}
// printf(lcd_putc,"\fFOUND %u",numROMs);
delay_ms(2000);
}
// putc('\n'); putc('\r');
}
//******************************************************************************
//******************************************************************************
// DESCRIÇAO: envia o comando Match_rom e depois o endereço do dispositivo
//
// INPUT: Nada
//
// OUTPUT: 0 se o dispositivo nao esta presente
// 1 se o dispositivo esta presente
//------------------------------------------------------------------------------
int8 Send_MatchRom(int num_dispositivo)
{
int8 i;
if (ow_reset()) return FALSE; // 0 if device present
write_byte(0x55); // Match ROM
for (i=0;i<8;i++)
{
write_byte(FoundRom[num_dispositivo][i]); // Send ROM code
}
return TRUE;
}
/******************************************************************************/ |
And the ds1820 driver..
Code: | //******************************************************************************
// ds1820.c
//
// Driver para o sensor de temperatura digital ds1820
//
// *tem que definir 2 variaveis globais no programa main: int8 inteiro, decimal;
//
// AUTOR: Ricardo Lopes DATA: Março 2006
//------------------------------------------------------------------------------
#if !defined sensor_pin
#error Tem que definir o pino de comunicaçao //#define sensor_pin pin_XX (onde XX é o pino)
#endif
#include <onewire.c>
#define SEARCH_ROM 0XF0
#define MATCH_ROM 0X55
#define READ_ROM 0X33
#define SKIP_ROM 0xcc
#define READ_SCRACHPAD 0xbe
#define CONVERT 0x44
#define READ_POWER_SUPPLY 0xb4
//******************************************************************************
// void read_ds1820_scrachpad(void)
//
// DESCRIÇAO: Lê o scrachpad (9 bytes);
//
// INPUT: vector com 9 elementos que vai armazenar os valores;
//
// OUTPUT: Vector inicial com os dados adquiridos;
//
//------------------------------------------------------------------------------
void read_ds1820_scrachpad(int8 data[9]){
byte i,j;
for(i=0;i<9;i++){ // para ler 9 bytes
for(j=0;j<8;j++){ // para ler 8 bits
output_low(sensor_pin);
delay_us(2);
output_float(sensor_pin);
delay_us(9);
shift_right(&data[i],1,input(sensor_pin));
delay_us(60); //tempo de slot
}
}
}
//******************************************************************************
//******************************************************************************
// void ler_temp (void)
//
// DESCRIÇÃO: Faz a sequencia de leitura dos valores do scrachpad;
//
// INPUT: Vector que vai armazenar os dados lidos;
//
// OUTPUT: Vector preenchido com os valores recebidos
//
// OBS: A funçao 'convert_temp(dispositivo)' deve ser chamada imediatamente antes
// da leitura de temperatura.
//------------------------------------------------------------------------------
int1 read_temp (int data[9], int num_dispositivo)
{
if(!send_MatchRom(num_dispositivo)) //envia o rom code e se encontrado, devolve 1
return FALSE;
write_byte(READ_SCRACHPAD); //envia o comando para leitura de scratchpad
read_ds1820_scrachpad(data); //faz a leitura do scratchpad
return TRUE;
}
//******************************************************************************
//******************************************************************************
// int1 convert_temp(void)
//
// DESCRIÇAO: Envia para todos os dispositivos o comando de inicio de conversao de temperatura
//
// INPUT: Numero do dispositivo
//
// OUTPUT: nada
//------------------------------------------------------------------------------
int1 convert_temp(void)
{
if(ow_reset())
return FALSE;
write_byte(SKIP_ROM); // Selecciona todos os dispositivos
write_byte(CONVERT); // envia o comando para iniciar a conversao de temperatura
if(parasite_power){ //se nao estiver alimentado por Vcc
output_high(sensor_pin); //aplicar um forte pull up
delay_ms(750); //delay obrigatório para conversao de temperatura
return TRUE;
}
else{ // Se estiverem alimentados por Vcc
while(!input(sensor_pin)) //|
delay_ms(5); //|Espera que todos terminem a conversao
return TRUE;
}
}
//******************************************************************************
// void ler_rom(int rom[8])
//
// DESCRIÇAO: Lê os 64 bits que compoêm o endereço de rom
//
// INPUT: Vector que vai armazenar os valor da rom
//
// OUTPUT: Vector preenchido com o codigo serial do chip
//------------------------------------------------------------------------------
void read_ds1820_rom(int romm[8])
{
int i,j;
if(!ow_reset()){
write_byte(READ_ROM);
for(i=0;i<8;i++){
for(j=0;j<8;j++){
output_low(sensor_pin);
delay_us(2);
output_float(sensor_pin);
delay_us(9);
shift_right(&romm[i],1,input(sensor_pin));
delay_us(60);
}//for
}//for
} //if
} //final de funçao
//******************************************************************************
void trata_temperatura (int dados[9])
{
int count_rem, count_per_c, i;
static int16 valor, sub, div, final, final_aux, aux;
count_rem = dados[6];
count_per_c = dados[7];
shift_right(dados,2,0); //discarta o bit menos significativo
valor=dados[0]; //passa para uma variavel de 16 bits (byte menos significativo)
for(i=0;i<8;i++)
shift_left(&valor,2,0); //passa para o byte mais significativo
valor= valor - 0x40; //subtrai 0.25 (0x40 em hexadecimal)
sub=count_per_c - count_rem; //faz a subtracçao do numerador
for(i=0;i<8;i++)
shift_left(&sub,2,0); //multiplica por 100 (basta mover 8 bits para a esquerda)
div=sub/count_per_c; //faz a divisao
final= valor + div; //efectua a soma da equaçao (com o resultado anterior)
aux=final; //passa para uma variavel auxiliar
for(i=0;i<8;i++) //|
shift_left(&aux,2,0); //|
// ficar com o byte menos significativo e abdicar do mais significativo
for(i=0;i<8;i++) //|
shift_right(&aux,2,0); //|
final_aux=aux*0x64; //converter o resultado da fracçao para decimal
for(i=0;i<8;i++)
shift_right(&final_aux,2,0); //passar para o byte menos significativo
decimal=final_aux; //passar para uma variavel de 8 bits
for(i=0;i<8;i++) //passar para o byte menos significativo
shift_right(&final,2,0);
inteiro=final; //passar para uma variavel de 8 bits
}
//******************************************************************************
//******************************************************************************
// int1 search_supply (void)
//
// DESCRIÇAO: Pesquisa no bus se existe algum dispositivo com parasite_power
//
// INPUT: Nada
//
// OUTPUT: 0 se nao houver nenhum dispositivo com parasite_power
// 1 se houver algum dispositivo com parasite_power
//------------------------------------------------------------------------------
int1 search_supply (void)
{
int1 power;
if(!ow_reset())
{
write_byte(SKIP_ROM);
write_byte(READ_POWER_SUPPLY);
power=read_bit();
return !power; //
}
}
//****************************************************************************** |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jul 31, 2008 7:10 pm |
|
|
Today someone reminded me: 'A lazy programmer is a good programmer.'
- I don't want to read your large posted program. I like the problems presented as a short test program.
- If possible I use tested code. Have a look at the CCS supplied driver ds2432.c It contains a function search_rom() for finding all chips on the bus.
Remark: your function ow_reset() has several timings barely within specifications. If bus loading is a bit larger you will read wrong data. |
|
|
herselmann
Joined: 31 May 2008 Posts: 7
|
|
Posted: Fri Aug 01, 2008 1:30 am |
|
|
Have a look at the app notes on the Maxim website. They have an app note with the complete search function. Do a search and you should find the links.
All you need to do is to port it to CCS, which is really not that difficult. I am currently working on a new OW lib with just about all the functions found in the OW Public Domain kit. I can however not release it yet as it is not 100% tested yet, but should do so soon.
I do remember though that the Match ROM command does not 'follow' the flow chart in the datasheets. Effectively you have to do a search ROM and then see if the device you want to match is in the list of found devices, if so, then send your Match ROM command followed by your specific command. The datasheet gave the impression that the device echos each bit sent to it (well at least thats how I understood it ). _________________ There are only 10 kinds of people, those who understand binary and those who don't. |
|
|
|
|
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
|