PDA

View Full Version : Cần giúp đỡ về giao tiếp 1-wire với ds1820


notbadday
08-03-2009, 10:41 AM
Em đang viết 1 đoạn chương trình để hiển thị nhiệt độ lên LCD dùng cảm biến ds1820 và pic6f877a. Em đang gặp rắc rối trong việc giao tiếp với ds1820. Cụ thể là không hiện được nhiệt độ. Mấy anh xem giúp,có gì góp ý thì em cảm ơn rất nhiều.
Đây là code CCS, có mượn đoạn code phần LCD của bác nhh (hy vọng bác ko phản đối :) )

#include <16F877A.h>
#include <DEFS_16F877A.h>
#include <stdlib.h>

#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define E RD2
#define RS RD0
#define RW RD1
#define DQ RC0
#DEFINE TRISC 0x07
#byte lcd_data = 0x06 // Dia chi PORTB

/* Khai bao nguyen mau cac ham su dung */
byte lcd_read_byte();
void lcd_send_byte( byte address, byte n );
void lcd_init();
void lcd_gotoxy( byte x, byte y);
void lcd_putc( char c);
void lcd_refresh();
unsigned char ow_reset(void);
unsigned char read_bit(void);
void write_bit(char bival);
unsigned char read_byte(void);
void write_byte(char val);

/* Doc mot byte tu LCD */
byte lcd_read_byte()
{
byte read_byte;
set_tris_B(0xFF); // PORTB = input
RW = 1;
delay_cycles(1);
E = 1;
delay_cycles(1);
read_byte = lcd_data;
E = 0;
set_tris_B(0x00); // PORTB = output
return(read_byte);
}

/* Goi 1byte den LCD */
void lcd_send_byte( byte address, byte n )
{
RS = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
RS = address;
delay_cycles(1);
RW = 0;
delay_cycles(1);
E = 0;
lcd_data = n;
delay_cycles(1);
E = 1;
delay_us(2);
E = 0;
}

/* Khoi tao ban dau cho LCD */
void lcd_init()
{
byte const lcd_init_string[4] = {0x38, 0x0C, 1 , 6};
byte i;
set_tris_B(0x00);
RS = 0;
RW = 0;
E = 0;
delay_ms(15);
for(i=1;i<=3;++i)
{
lcd_data = 3;
delay_cycles(1);
E = 1;
delay_us(2);
E = 0;
delay_ms(5);
}
lcd_data = 2;
delay_cycles(1);
E = 1;
delay_us(2);
E = 0;
delay_ms(5);
for(i=0;i<=3;++i)
{
lcd_send_byte(0,lcd_init_string[i]);
}
}

/* Nhay den vi tri (x,y) tren LCD,nhay nham y se bao loi */
void lcd_gotoxy( byte x, byte y)
{
byte address;
switch(y)
{
case 1: address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
break;
case 2: address=0x40;
address+=x-1;
lcd_send_byte(0,0x80|address);
break;
default :lcd_init();
lcd_putc("ERROR Y POSITION");
while(true); // Dung tai day!
}
}

/* Hien thi ki tu hoac chuoi ra LCD */
void lcd_putc( char c)
{
lcd_send_byte(1,c);
}

/* Hien thi ki tu hoac chuoi ra LCD */
void lcd_refresh()
{
lcd_send_byte(0,1);
lcd_send_byte(0,6);
}

//reset

unsigned char ow_reset(void)
{
unsigned char presence;
set_tris_C(0);
DQ = 0; //pull DQ line low
delay_us(500); // leave it low for at least 480us
DQ = 1; // allow line to return high
delay_us(40); // wait for presence
set_tris_C(0x01);
presence = DQ; // get presence signal
delay_us(150); // wait for end of timeslot
return(presence); // presence signal returned
} // 0=presence, 1 = no part

unsigned char read_bit(void)
{
set_tris_C(0);
DQ = 0; // pull DQ low to start timeslot
delay_us(1);
set_tris_C(0x01); //release DQ
delay_us(15);
return(DQ); // return value of DQ line
}

void write_bit(char bitval)
{
set_tris_C(0);
DQ = 0; // pull DQ low to start timeslot
delay_us(15);
if(bitval==1) set_tris_C(0x01); //release DQ
delay_us(50); // hold value for remainder of timeslot
}

// READ_BYTE - reads a byte from the one-wire bus.
//
unsigned char read_byte(void)
{
unsigned char i;
unsigned char value = 0;
for (i=0;i<8;i++)
{
if(read_bit()) value|=0x01<<i; // reads byte in, one byte at a time and then
// shifts it left
delay_us(150); // wait for rest of timeslot
}
return(value);
}

void write_byte(char val)
{
unsigned char i;
unsigned char temp;
for (i=0; i<8; i++) // writes byte, one bit at a time
{
temp = val>>i; // shifts val right 'i' spaces
temp &= 0x01; // copy that bit to temp
write_bit(temp); // write bit in temp into
}
delay_us(100);
}
/* Ham main */
void main (void)
{
unsigned char x;
set_tris_B(0); //PORTB = output
set_tris_D(0); //PORTD = output

ow_reset();
write_byte(0xCC); // skip ROM
write_byte(0x44); // Start conversion

delay_us(100);
ow_reset();
write_byte(0xCC);
x = read_byte();
lcd_init();
lcd_gotoxy(5,1);
printf(lcd_putc,"temp = %u",x);
lcd_gotoxy(4,2);
lcd_putc("PICVIETNAM!");
}

quocloc.pham
09-03-2009, 02:02 PM
bạn phải xem mình đã thực hiện đc qua trình gì trong DS1820?
Bạn init được chưa?
quá trình ghi 1byte ok chưa?
quá trình đọc 1 byte ok?

Thân!

longtu
09-03-2009, 02:33 PM
[QUOTE=notbadday;23330]Em đang viết 1 đoạn chương trình để hiển thị nhiệt độ lên LCD dùng cảm biến ds1820 và pic6f877a. Em đang gặp rắc rối trong việc giao tiếp với ds1820. Cụ thể là không hiện được nhiệt độ. Mấy anh xem giúp,có gì góp ý thì em cảm ơn rất nhiều.
Đây là code CCS, có mượn đoạn code phần LCD của bác nhh (hy vọng bác ko phản đối :) )

Đúng như bạn Quocloc.pham nói, bạn cần xác định lại xem đã đọc được nhiệt độ ĐÚNG từ DS1820 chưa?
Nếu chưa được, bạn thử Include file DS1820.c và file Temperature.c vao nhé (file đính kèm). Sau đó bạn,khai báo 1 biến: float temperature
và chép doạn chương trình này vào dầu chuong trình cùa bạn xem nó có đọc dúng nhiệt độ chua nhé.
temperature = ds1820_read();
printf("TEMP: %3.1f ", temperature);

longtu
09-03-2009, 02:38 PM
Minh chua biet gui file len:
Ban copy lai nhé:
DS1820.c:
//************* Reset *******************
void onewire_reset()
{
output_low(ONE_WIRE_PIN);
delay_us( 500 ); // pull 1-wire low for reset pulse
output_float(ONE_WIRE_PIN); // float 1-wire high
delay_us( 500 ); // wait-out remaining initialisation window.
output_float(ONE_WIRE_PIN);
}
//************* Write data to the chip*******************
void onewire_write(int data)
{
int count;

for (count=0; count<8; ++count)
{
output_low(ONE_WIRE_PIN);
delay_us( 2 ); // pull 1-wire low to initiate write time-slot.
output_bit(ONE_WIRE_PIN, shift_right(&data,1,0)); // set output bit on 1-wire
delay_us( 60 ); // wait until end of write slot.
output_float(ONE_WIRE_PIN); // set 1-wire high again,
delay_us( 2 ); // for more than 1us minimum.
}
}

//****************Read data from the chip********************
int onewire_read()
{
int count, data;

for (count=0; count<8; ++count)
{
output_low(ONE_WIRE_PIN);
delay_us( 2 ); // pull 1-wire low to initiate read time-slot.
output_float(ONE_WIRE_PIN); // now let 1-wire float high,
delay_us( 8 ); // let device state stabilise,
shift_right(&data,1,input(ONE_WIRE_PIN)); // and load result.
delay_us( 120 ); // wait until end of read slot.
}

return( data ) ;
}

và file Temperature.c

float ds1820_read()
{
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;

onewire_reset();
onewire_write(0xCC); //SkipRom:cho phep truy cap den DS1820
onewire_write(0x44); //Convert Command: chuyen doi gia tri nhiet do thanh so nhi phan
///////////////
delay_ms(100);
///////////////
while (busy == 0)
busy = onewire_read();

onewire_reset();
onewire_write(0xCC);
onewire_write(0xBE); //cho Phep MU doc data trong DS1820
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);

result = (float) temp3 / 2.0; //Calculation for DS18S20 with 0.5 deg C resolution
// result = (float) temp3 / 16.0; //Calculation for DS18B20 with 0.1 deg C resolution

// delay_ms(200);
return(result);
}

Thân,

namqn
09-03-2009, 04:48 PM
Gửi bạn longtu,

Bạn xem hướng dẫn upload tập tin lên diễn đàn ở đây:
http://www.picvietnam.com/forum/showthread.php?t=3289

Thân,

longtu
09-03-2009, 05:29 PM
Gửi bạn longtu,

Bạn xem hướng dẫn upload tập tin lên diễn đàn ở đây:
http://www.picvietnam.com/forum/showthread.php?t=3289

Thân,

Cám ơn anh Nam.

Thân chào anh.

longtu
09-03-2009, 05:35 PM
To Notbadday: gui ban File mình da upload len duoc roi.

Than,

notbadday
09-03-2009, 09:01 PM
Cảm ơn mọi người rất nhiều đã quan tâm vấn đề này.
to quocloc.pham: đoạn code mình đưa ra thực sự chưa làm gì đc, nhiệt độ hiển thị là 1 con số nào đó.
to longtu: đoạn code của bạn giúp ích mình rất nhiều. Mình đã build và mô phỏng thành công.

longtu
10-03-2009, 08:08 PM
[QUOTE=longtu;23373]Cám ơn anh Nam.

Gửi anh Nam,
Anh cho em hỏi, làm sao de mình có thể tạo 1 chủ đề mới dể mọi người cùng thao luận vậy anh? Ý em là: ngay khi vào Trang chủ của PICVietNam sẽ thấy tựa đề của mình mà muốn mọi người cùng trao đổi?
Cám ơn anh.

Thân chào anh.

namqn
10-03-2009, 08:59 PM
Gửi anh Nam,
Anh cho em hỏi, làm sao de mình có thể tạo 1 chủ đề mới dể mọi người cùng thao luận vậy anh? Ý em là: ngay khi vào Trang chủ của PICVietNam sẽ thấy tựa đề của mình mà muốn mọi người cùng trao đổi?
Cám ơn anh.

Thân chào anh.
Khi vào trang chủ của PIC Vietnam, bạn sẽ thấy một khung nhỏ bên tay trái, ngay dưới banner và thanh công cụ của diễn đàn. Khung nhỏ này có tên là "Cấu trúc diễn đàn", chứa các shortcut đến các mục thường được truy cập. Ở link đầu tiên của khung này (tên là "Diễn đàn") là đường dẫn đến trang cấu trúc của diễn đàn. Click vào link này bạn sẽ thấy được toàn bộ cấu trúc diễn đàn, với các subforum và box trong các subforum. Bạn chọn một box thích hợp cho bài viết sắp được post của bạn, và click vào link của box đó.

Chỉ ở trong một box cụ thể, bạn mới có thể tạo ra một luồng mới. Sau khi đã đến được box cần thiết, bạn sẽ thấy ngay bên dưới trang danh sách các bài viết của box là một nút mang tên "New Thread", đây là nút để các thành viên tạo ra luồng mới trong box. Bài viết mới của bạn cần có một chủ đề và nội dung nhất định.

Thân,

longtu
11-03-2009, 11:56 AM
Khi vào trang chủ của PIC Vietnam, bạn sẽ thấy một khung nhỏ bên tay trái, ngay dưới banner và thanh công cụ của diễn đàn. Khung nhỏ này có tên là "Cấu trúc diễn đàn", chứa các shortcut đến các mục thường được truy cập. Ở link đầu tiên của khung này (tên là "Diễn đàn") là đường dẫn đến trang cấu trúc của diễn đàn. Click vào link này bạn sẽ thấy được toàn bộ cấu trúc diễn đàn, với các subforum và box trong các subforum. Bạn chọn một box thích hợp cho bài viết sắp được post của bạn, và click vào link của box đó.

Chỉ ở trong một box cụ thể, bạn mới có thể tạo ra một luồng mới. Sau khi đã đến được box cần thiết, bạn sẽ thấy ngay bên dưới trang danh sách các bài viết của box là một nút mang tên "New Thread", đây là nút để các thành viên tạo ra luồng mới trong box. Bài viết mới của bạn cần có một chủ đề và nội dung nhất định.

Thân,

Rất cảm ơn anh Nam

Thân chào anh.

thientaisodo
27-05-2010, 04:17 PM
Có code và file hướng dẫn trong đó, bạn vào mà lấy nhé
http://www.dientuvietnam.net/forums/showthread.php?p=263404#post263404

tbk_05
28-05-2010, 05:16 PM
Các bạn cho mình hỏi mình định nghĩa ONE_WIRE_PIN một chân bất kì nào đó được không, tai sao khi mô phỏng, định nghỉa chân REx lại không được nhỉ. Mình phải định nghĩa chân khác ngoài Porte, nhưng kết quả không như mong muốn(hiển thị âm -0.5). Các bạn xem file đính kèm rối góp ý cho mình với nhé. Mình cám ơn nhiều.(thư viện DS1820.c,Temperature.c mình lấy nguyên của bạn longtu, chỉ sửa lại định nghĩa ONE_WIRE_PIN này thôi a`)

manucian1988
07-03-2011, 11:09 PM
@longtu,notbadday: các bác cho em hỏi là mô phỏng ds18b20 trên proteus có vấn đề gì ko vì em dùng code ở trên và rất nhiều code khác mô phỏng đều ko được >.<

mrtddiep
28-06-2012, 12:21 AM
cam on ban longtu rat nhieu code cua ban rat huu ich doi voi nguoi moi tap tanh choi voi pic nhu minh.cho minh hoi them la che do onewrite nay truyen duoc bao xa nhi ? va hay bi loi khong nhi ? thank's moi nguoi truoc nha !

khactinh88hn
13-10-2013, 11:43 AM
chào mọi người mình đang cân gấp tài liệu về giao tiếp onewire để báo cáo.mà tìm trên mạng thị ko chuẩn.bạn nào có tài liệu chuẩn về onewire cho mình xin đi.mình cảm ơn.

tuanbo555
17-09-2016, 10:37 PM
Cam´ ơn bạn, mình cũng đã giao tiếp đuoc̣ sensor 18b20, co´ một vấn đề em muốn hỏi khoảng cách kết nối từ MCU đến sensor laˋ bao nhiêu,khi em nối dai dây thiˋ không giao tiếp được với ds18b20, theo ly´ thuyêt em tìm hiểu giao tiếp 1 wire khoảng cách tối đa laˋ 300m.Mong nhận được giải đáp của các anh.

dungbetion
20-05-2018, 10:52 PM
bạn phải xem mình đã thực hiện đc qua trình gì trong DS1820?
Bạn init được chưa?
quá trình ghi 1byte ok chưa?
quá trình đọc 1 byte ok?

Thân!