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.

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)


