Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Sonda DS18B20 e PIC18

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Sonda DS18B20 e PIC18

Messaggioda Foto Utentericello9 » 22 feb 2012, 23:47

Ciao a tutti, oggi vi propongo l'ennesimo problema.
Sto cercando di far funzionare la sonda di temperatura della dallas DS18B20 collegata al PIC 18F4550.
Premetto che il codice non è tutta farina del mio sacco ma ho spulciato in rete per poi cercare di mettere tutto insieme.
La comunicazione tra i due dispositivi è funzionante infatti riesco a leggere il codice rom della sonda, tramite il comando 0X33, sul mio PC collegato tramite usart.
un altro discorso è per il valore di temperatura; che come risultato mi da sempre F02F.
Se scollego il pin DQ del dispositivo e rischiedo il valore di temperatura il risultato è FF FF, quindi significa che con la sonda collegata qualcosa leggo.
Prima di postare il codice cerco di spiegarvelo:
alla pressione del tasto collegato a RB5 richiamo la funzione OWConvertT() che per prima cosa esegue un reset, invia il comando per saltare la lettura della rom e infine invia il comando per la conversione della temperatura.
Atendo un secondo e poi richiamo la funzione OWReadMem(TE) che mi invia un impulso di reset alla sonda, salta la lettura della rom e invia il comando per la lettura della memoria Scratchpad.
Quest'ultima funzione dovrebbe avere come valore di ritorno un array contente il byte 0 della memoria Scratchpad, mentre la funzione sucessiva mi legge il valore della Scratchpad al byte 1 e lo copia nell'array TE1.
Infine stampo a video i due valori con il risultato di F0 2F.
Di seguito vi posto il codice:

Codice: Seleziona tutto
/******************************************/
//
// Test su sonda di temperature DS18B20
// PIC: 18F4550
// main.c
/******************************************/


#include <p18f4550.h>
#include <portb.h>
#include <usart.h>
#include <delays.h>
#include <one-wire.h>
#include <one-wire.c>

#pragma config FOSC = HS      //OSC = HS Impostato per lavorare ad alta frequenza
#pragma config WDT = OFF      //WDT = OFF Disabilito il watchdog timer
#pragma config LVP = OFF      //LVP = OFF Disabilito programmazione LVP
#pragma config PBADEN = OFF  //PBADEN = OFF Disabilito gli ingressi analogici


/******************************************/
// Programma Principale
/******************************************/
void main (void){
unsigned char ID[8]; // verrà usato per memorizzare il rom code del dispositivo collegato al bus
unsigned char TE[8]; // verrà usato per memorizzare la memoria Scratchpad del dispositivo collegato al bus
unsigned char TE1[8]; // verrà usato per memorizzare la memoria Scratchpad del dispositivo collegato al bus
unsigned char a; // counter generico


// Configura l'USART
// 8 bit
// 9600 bit/s
// 1 bit stop
// 0 bit parità
OpenUSART( USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH,
129 );


// Abilita i resistori di pull-up sulla PORTB
EnablePullups();
// Imposto PORTA tutti ingressi
LATA = 0x00;
TRISA = 0xFF;
// Imposto PORTB tutti ingressi
LATB = 0x00;
TRISB = 0xFF;
// Imposto PORTC tutti ingressi e RC1 come uscita
LATC = 0x00;
TRISC = 0b11000000;
// Imposto PORTD tutte uscite
LATD = 0x00;
TRISD = 0b00000000;
// Imposto PORTE tutti ingressi
LATE = 0x00;
TRISE = 0xFF;

// Ciclo infinito
while(1){

if (!PORTBbits.RB4)
{
  Delay10KTCYx(50);
  if(!PORTBbits.RB4)
     {
    a=OWReset();
    if (a==OW_NO_PRESENCE)
      {
      putrsUSART("Nessun dispositivo 1Wire collegato\n\r");
      }
    else
      {
      OWReadRom(ID); // Eseguo la lettura della ROM, l'id sarà memorizzato nell'array ID
      putrsUSART("ROM code: ");
      for(a=0; a<8; a++)// ciclo per leggere gli 8 bytes restituiti dalla sonda
        {
        if (ID[a]<16) // per stampare lo zero davanti
         {
         putrsUSART("0x0");
         WriteHexUSART(ID[a]);
         }
        else
         {
         putrsUSART("0x");
         WriteHexUSART(ID[a]);
         }
         // se non sono all'ultimo byte, aggiungo una virgola
         if (a<7)
           {
           putrsUSART(",");
           }
       }// fine for
   putrsUSART("\n\r");
   switch(ID[0])
      {
      case 0x28:
         putrsUSART("Sonda di temperatura DS18B20 (risoluzione programmabile)\n\r");
         break;
      case 0x10:
         putrsUSART("Sonda di temperatura DS18S20 (risoluzione fissa)\n\r");
         break;
      case 0x06:
         putrsUSART("iButton da 4K\n\r");
         break;
      case 0x08:
         putrsUSART("iButton da 1K\n\r");
         break;
      case 0x0A:
         putrsUSART("iButton da 16K\n\r");
         break;
      case 0x0C:
         putrsUSART("iButton da 64K\n\r");
         break;
      //default:
      } // switch
   } // fine dispositivo presente
} // pulsante premuto (antibounce)
} // pulsante premuto


if (!PORTBbits.RB5)
  {
  Delay10KTCYx(50);
    if(!PORTBbits.RB5)
      {
     OWConvertT();
     putrsUSART("TEMPERATURA:  ");
     OWReadMem(TE);
       for(a=0; a<8; a++)// ciclo per leggere gli 8 bytes restituiti dalla sonda
      {
         WriteHexUSART(TE[a]);        
        }
     putrsUSART(" ");   
     OWReadMem2(TE1);
     for(a=0; a<8; a++)// ciclo per leggere gli 8 bytes restituiti dalla sonda
      {
         WriteHexUSART(TE1[a]);        
        }   
     putrsUSART("\n\r");   
     }
  }
} // while
} // main



Codice: Seleziona tutto
//*****************************************************************
//                    one-wire.c
//*****************************************************************

// resetta il bus 1-wire e rileva la presenza di dispositivi
unsigned char OWReset(void)
   {
    unsigned char ow_detect; // variabile usata per rilevare la presenza di dispositivi 1wire
   // variabile usata per rilevare la presenza di dispositivi 1wire
      TRISD=0b00000001; // avvio con linea RC5 in alta impedenza
         LATDbits.LATD0=0; // predispongo uscita bassa
         TRISD=0b00000000; // linea in uscita
      // linea a livello basso per 500uS
      // nota: la linea deve essere tenuta a livello basso
      // minimo 480uS
      Delay10TCYx(250);
      TRISD=0b00000001; // avvio con linea RC5 in alta impedenza
      // dopo che la linea è stata posta in alta impedenza
      // bisogna attendere dai 15 ai 60uS per una risposta
      Delay10TCYx(50);// attendo 100uS per stare tranquillo
      ow_detect= PORTDbits.RD0; // rilevo in che stato si trova la linea
      // l'impulso di presenza dura dai 60 ai 240uS
      // attendo 430uS dopo l'impulso di presenza
      Delay10TCYx(215);
      // 0 = ci sono dispositivi (OW_PRESENCE)
      // 1 = non ci sono dispositivi (OW_NO_PRESENCE)   
   // restituisco il valore ottenuto:
   return ow_detect;
    }

// leggo un byte dalla linea
unsigned char OWReadByte(void)
   {
    unsigned char i; // counter
    unsigned char value=0; // byte letto
    for(i=0; i<8; i++)
      {
        if(_OWReadBit()) // leggo un bit
         {
         // se la linea è a livello alto, sommo il bit
         // nella posizione giusta tramite lo shift
         value |= (0x01<<i);
         }
      // ritardo di 120uS per il resto del timeslot
         Delay10TCYx(60);
      }
    // restituisco il byte letto
   return value;
    }   



// scrivo un byte sulla linea
void OWWriteByte(char val)
   {
    unsigned char i; // counter
    unsigned char temp; // valore temporaneo
    for( i=0; i<8; i++) // ciclo per gli 8 bit del valore
      {
      temp=val>>i;  // sposto il byte di i posizioni per recuperare il solo bit i-esimo
        temp &= 0x01; // ottengo solo il valore 0 o 1
        _OWWriteBit(temp); // "scrivo" il bit sulla linea
        }
    // ritardo di 100uS per il resto del timeslot
      Delay10TCYx(50);
    }

// legge il codice del SINGOLO dispositivo sul bus
// e lo memorizza nell'array ID passato come argomento
void OWReadRom(unsigned char *ID)
   {
   unsigned char a;
   OWReset(); // resetto la linea one-wire
   OWWriteByte(OW_READ_ROM); // invio il comando readrom, che si può usare solo se sulla linea c'è una sola sonda
   for(a=0; a<8; a++)// ciclo per leggere gli 8 bytes restituiti dal dispositivo
      {
      // eseguo la lettura del byte a-esimo:
      ID[a]=OWReadByte();
      }
   }

// funzioni di basso livello

// leggo un singolo bit dalla linea
unsigned char _OWReadBit(void)
   {
      LATDbits.LATD0=0; // predispongo uscita bassa
      TRISD=0b00000000; // linea in uscita
    Delay10TCYx(1);
    TRISD=0b00000001;  // pin in alta impedenza
    // Devo aspettare minimo 10uS
   Delay10TCYx(7); //corrisponde a 14 Us
    return PORTDbits.RD0; // restituisco il valore sul quale si trova la linea
    }

// scrivo un singolo bit sulla linea   
void _OWWriteBit(char bitval)
   {
    LATDbits.LATD0=0; // predispongo uscita bassa
      TRISD=0b00000000; // linea in uscita
    Delay10TCYx(1);
    // se il bit vale 1, porto la linea in alta impedenza
   if(bitval==1)
      {
        TRISD=0b00000001;  // pin in alta impedenza
      }
    Delay10TCYx(50); // aspetto 100uS per la fine del timeslot
    TRISD=0b00000001;  // pin in alta impedenza
    }

// avvio la conversione della temperatura e leggo il valore
// nella'array TE
void OWConvertT(void)
   {
   unsigned char a;
   OWReset(); // resetto la linea one-wire
   OWWriteByte(OW_SALTA_ROM); // invio il comando readrom, che si può usare solo se sulla linea c'è una sola sonda
   OWWriteByte(OW_CONVERT_T); // invio il comando convert_t, che converte il valore temperatura
   Delay10KTCYx(250); // aspetto un secondo
   Delay10KTCYx(250); // aspetto un secondo
   }

void OWReadMem(unsigned char *TE)
   {
   unsigned char a;
   OWReset(); // resetto la linea one-wire
   OWWriteByte(OW_SALTA_ROM); // invio il comando readrom, che si può usare solo se sulla linea c'è una sola sonda
   OWWriteByte(OW_LEGGI_SCRAT);//leggi il
   for(a=0; a<8; a++)// ciclo per leggere gli 8 bytes restituiti dal dispositivo
     {
     TE[a]=OWReadByte();
     }   
   }

void OWReadMem2(unsigned char *TE1)
   {
   unsigned char a;   
   for(a=0; a<8; a++)// ciclo per leggere gli 8 bytes restituiti dal dispositivo
     {
     TE1[a]=OWReadByte();
     }   
   }


Grazie per l'aiuto.
Avatar utente
Foto Utentericello9
195 1 3 7
Stabilizzato
Stabilizzato
 
Messaggi: 360
Iscritto il: 16 mar 2009, 0:13

0
voti

[2] Re: Sonda DS18B20 e PIC18

Messaggioda Foto Utentedadodj » 21 mar 2012, 14:13

Saluti,

in che modo stai alimentando il dallas? parassite mode o supply? che valori hai scelto per lo strong pull-up??

Hai provato a dare 4V su Vdd? e 4 su Vpu utilizzando così il supply powering?
Avatar utente
Foto Utentedadodj
45 1 2
New entry
New entry
 
Messaggi: 87
Iscritto il: 18 lug 2011, 23:14


Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 11 ospiti