Hallo,
seit gestern Abend ärger ich mich nun schon mit dem 1-Wire-Bus rum. Eigentlich ist ja alles recht einfach und es steht auch ausführlich im Datasheet von Application Note beschrieben.
Der DS1820 (Parasite Mode!) sendet beim Reset seinen Responce Pulse, wird also erkannt. Auch die Seriennummer wird korrekt ausgelesen. Starte ich nun allerdings einen Convert-Vorgang und gebe dann den Scratchpad aus, dann gibt er ihn so aus, wie er eigentlich beim Power-Up ist (laut DS) - es hat sich also nichts geändert.
Nachdem ich den Convert starte lege ich zusätzlich 5V (strong pullup) auf dem 1-Wire-Bus von einem Port-Pin aus an, da er sonst zuviel Strom für den Parasite-Mode zieht (im Datasheet wurde das ganze mit einem MOSFET umgesetzt, aber sollte ja das gleiche sein). Dann warte ich etwas mehr als 750ms und schalte die zusätzlichen 5V wieder ab. Sollte ja alles passen soweit. Aber funktionieren tut es nicht.
Hier mal der Quellcode, nicht erschrecken, das ist durch das ewige Rumprobieren, weil es nicht funktionierte, etwas durcheinander. Das Wesentliche (des Problems) ist in der: ds1820_read_temperature
Code:
#include <p18f2620.h>
#include "delays.h"
#pragma config OSC = INTIO67 //Intern Osci
#pragma config PWRT = ON
#pragma config WDT = OFF //Watchdog Timer
#pragma config LVP = OFF //Low Voltage ICSP
unsigned char temp;
/* prototypes */
void usart_init(void);
void usart_txc(char c);
void usart_txs(const rom char* s);
unsigned char ow_read();
void ow_high();
void ow_low();
unsigned char ow_reset_pulse();
void ow_write_bit(unsigned char write_bit);
void ow_write_byte(unsigned char write_data);
unsigned char ow_read_bit(void);
unsigned char ow_read_byte(void);
void usart_tx_hex_ascii(unsigned char display_data);
unsigned char ds1820_read_temperature(void);
void usart_init(void) {
SPBRG = 12; // 9600bps
TXSTAbits.SYNC = 0; // asynchronous
RCSTAbits.SPEN = 1; // enable usart
TXSTAbits.TXEN = 1; // enable transmit
}
void usart_txc(char c) {
TXREG = c;
while(!TXSTAbits.TRMT);
}
void usart_txs(const rom char* s) {
while(*s) {
usart_txc(*s);
s++;
}
}
void usart_tx_hex_ascii(unsigned char display_data) { /* not my work ;) c&p */
unsigned char temp;
temp = ((display_data & 0xF0)>>4);
if (temp <= 0x09)
usart_txc(temp+'0');
else
usart_txc(temp+'0'+0x07);
temp = display_data & 0x0F;
if (temp <= 0x09)
usart_txc(temp+'0');
else
usart_txc(temp+'0'+0x07);
}
unsigned char ow_read() {
unsigned char read_data=0;
TRISCbits.TRISC4 = 1;
if(PORTCbits.RC4 == 1)
read_data = 1;
else
read_data = 0;
return read_data;
}
void ow_high() {
LATCbits.LATC4 = 0;
TRISCbits.TRISC4 = 1;
}
void ow_low() {
LATCbits.LATC4 = 0;
TRISCbits.TRISC4 = 0;
}
unsigned char ow_reset_pulse() {
unsigned char presence_detect;
ow_low();
Delay10TCYx(96); /* 480us */
ow_high();
Delay10TCYx(14); /* 70us */
presence_detect = ow_read();
Delay10TCYx(82); /* 410us */
ow_high();
return presence_detect;
}
void ow_write_bit(unsigned char write_bit) {
if(write_bit) { /* writing a '1' */
ow_low();
Delay10TCYx(1); /* 5us */
ow_high();
Delay10TCYx(1); /* 5us */
}
else { /* writing a '0' */
ow_low();
Delay10TCYx(12); /* 60us */
ow_high();
Delay10TCYx(12); /* 60us */
}
}
void ow_write_byte(unsigned char write_data) {
unsigned char loop;
for(loop=0;loop<8;loop++) {
ow_write_bit(write_data & 0x01); /* Send LS-bit first */
write_data >>=1; /* shift data for the next bit to send */
}
}
unsigned char ow_read_bit(void) {
unsigned char read_data;
ow_low();
Delay10TCYx(1); /* 5us */
ow_high();
Delay10TCYx(2); /* 10us */
read_data = ow_read();
Delay10TCYx(11); /* 55us */
return read_data;
}
unsigned char ow_read_byte(void) {
unsigned char loop, result = 0;
for (loop=0;loop<8; loop++) {
result >>= 1; /* shift result 'out of the way' ;) */
if (ow_read_bit())
result |= 0x80; /* if result is one, then set MSB */
}
return result;
}
unsigned char ds1820_read_temperature(void) {
unsigned char temperature[9];
if(ow_reset_pulse()) /* first reset */
return 1;
ow_write_byte(0xCC); /* skip rom */
ow_write_byte(0x44); /* start convert */
TRISCbits.TRISC5 = 0; /* strong pullup on */
Delay10KTCYx(170); /* 750ms ... Tconv */
TRISCbits.TRISC5 = 1; /* strong pullup off */
if(ow_reset_pulse()) /* second reset */
return 1;
ow_write_byte(0xCC); /* skip rom */
ow_write_byte(0xBE); /* read Scratchpad */
usart_txs("\r\nTemperature: ");
for(temp=0;temp<=8;temp++)
temperature[temp] = ow_read_byte(); /* store in var */
for(temp=0;temp<=8;temp++)
usart_tx_hex_ascii(temperature[temp]); /* put it in hex->ascii on usart */
if(ow_reset_pulse()) /* third reset */
return 1;
return 0;
}
void main(void) {
unsigned char serialnumber[8];
OSCCON = 0x73; // 8mhz internal
TRISCbits.TRISC5 = 1;
LATCbits.LATC5 = 1;
ow_high();
usart_init();
usart_txs("=== Welcome to Thermostation v1.0 ===\r\nRunning at 8MHz on internal oscillator\r\n");
usart_txs("DS1820 detected: ");
if(!ow_reset_pulse())
usart_txs("yes\r\n");
else
usart_txs("no\r\n");
ow_write_byte(0x33); /* Command to send the serial number */
usart_txs("Serial number: ");
for(temp=0;temp<8;temp++)
serialnumber[temp] = ow_read_byte();
for(temp=0;temp<8;temp++)
usart_tx_hex_ascii(serialnumber[temp]);
if(ow_reset_pulse())
usart_txs("\r\nSomething went wrong\r\n");
while(1) {
if(ds1820_read_temperature()!=0)
usart_txs("\r\nLost connection. Try to reconnect\r\n");
Delay10KTCYx(100);
}
}
Die Ausgabe am PC:
=== Welcome to Thermostation v1.0 ===
Running at 8MHz on internal oscillator
DS1820 detected: yes
Serial number: 100356C1010800C0
Temperature: AA004B46FFFF0C1087
Temperature: AA004B46FFFF0C1087
Temperature: AA004B46FFFF0C1087
Temperature: AA004B46FFFF0C1087
Temperature: AA004B46FFFF0C1087
Temperature: AA004B46FFFF0C1087
[... geht immer so weiter ...]
Da wo AA00 steht sollte normal die Temperatur stehen, aber AA00 bedeutet 85°C und das passt definitiv nicht.
Würde mich freuen wenn mir jemand helfen kann.
Gruß Spessi
Lesezeichen