Sonda DS18B20 e PIC18
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:
Grazie per l'aiuto.
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.