Chào mừng đến với Câu Lạc Bộ Sáng Tạo
Chia sẻ kinh nghiệm
Kết nối đam mê
Đang cập nhật thời gian...
BÀI VIẾT NỔI BẬT
Xin chào! Tôi là Ếch Sáng Tạo :-)
Chia sẻ trang




Chuyên mục
Bài mới
Xem nhiều
Thống kê
    Đang tải..
Bài viết
Bài 14: Đo nhiệt độ dùng cảm biến DS18B20 với 8051 - SangTaoClub.Net
Bài 14: Đo nhiệt độ dùng cảm biến DS18B20 với 8051
Đăng bởi: Vũ Văn Thái - Thời gian: 19-10-2014, 10:11
Chuyên mục: Học lập trình 8051 - Lượt xem: 26.480

Đo nhiệt độ dùng cảm biến DS18B20 với 8051

1. Giới thiệu cảm biến nhiệt độ DS18B20

       DS18B20 là cảm biến nhiệt độ kỹ thuật số giao tiếp 1-Wire (1 dây duy nhất), bên trong IC được tích hợp sẵn cảm biến nhiệt và bộ chuyển đổi, khối xử lý, giao tiếp 1 wire, bộ nhớ ROM, EEPROM, báo thức nhiệt độ khi đạt ngưỡng...

       Thông số của cảm biến: 

                - Giải đo: -55 đến +125 độ C (sai số 0.5 độ C trong điều kiện -10 to +85 độ C)

                - Nguồn cung cấp: 3 - 5.5V

                - Độ phân giải: 9bit, 12bit

                - Môi trường làm việc: Mọi môi trường nếu có vỏ bảo vệ tốt.

      Cảm biến DS18B20 cho phép bạn kết nối nhiều cảm biến trên một đường dây DATA (DQ) và nó cho phép kết nối ít nhất là 2 dây DQ và GND không cần cấp VCC, lúc này chân VCC nối tắt sang GND, như vậy thì làm sao cấp nguồn được cho cảm biến hoạt động ??? Để cấp nguồn thì cảm biến được thiết kế có thể lấy trực tiếp áp từ dây tín hiệu DQ để duy trì hoạt động (xem mạch trong datasheet).

       Trong bài này ta chỉ xét xem làm thế nào để giao tiếp được với cảm biến, còn các bạn muốn tìm hiểu kỹ hơn thì vui lòng đọc datasheet gửi kèm trong đính kèm.

2. Sơ đồ chân và các kiểu đóng vỏ:

Đo nhiệt độ dùng cảm biến DS18B20 với 8051 - SangTaoClub.Net

3. Lập trình giao tiếp:

/****************Chương trình giao tiếp IC DS18B20***************************/
void delay_18B20(unsigned int ti){ //delay us
        while(ti--);
}
void Init_18B20(void){ //Khởi tạo cảm biến
        DQ = 1;
        delay_18B20(8);
        DQ = 0;
        delay_18B20(65);
        DQ = 1;
        delay_18B20(20);
}
unsigned char ReadOneChar(void){ //Đọc 1 byte từ IC
        unsigned char i=0;
        unsigned char dat = 0;
        for (i=8;i>0;i--){
                DQ = 0;
                dat>>=1;
                DQ = 1;
                if(DQ)
                dat |= 0x80;
                delay_18B20(4);
        }
        return(dat);
}
void WriteOneChar(unsigned char dat){ //Ghi một byte vào IC
        unsigned char i=0;
        for (i=8; i>0; i--){
                DQ = 0;
                DQ = dat&0x01;
                delay_18B20(5);
                DQ = 1;
                dat>>=1;
        }
}
void ReadTemperature(void){ //Hàm đọc nhiệt độ lưu vào biến temp
        unsigned char a=0;
        unsigned char b=0;
        //EA=0; //Nếu có ngắt thì cấm ngắt để tránh ảnh hưởng quá trình giao tiếp
        Init_18B20();
        WriteOneChar(0xCC); // Bỏ qua ROM
        WriteOneChar(0x44);
        delay_18B20(10);
        Init_18B20();
        WriteOneChar(0xCC);
        WriteOneChar(0xBE); //Đọc nhiệt độ
        delay_18B20(10);
        a=ReadOneChar(); //Read temp low value
        b=ReadOneChar(); //Read temp high value
        temp=((b*256+a)>>4); //Giá trị nhiệt độ lưu vào biến temp
        //EA=1; //Đọc xong thì cho phép ngắt
}//End code DS18B20

4. Mô phỏng giao tiếp với cảm biến

Đo nhiệt độ dùng cảm biến DS18B20 với 8051 - SangTaoClub.Net

* Các bạn tải code đầy đủ và mô phỏng về trong File đính kèm....

Chúc các bạn học tốt...!


Tải về đính kèm:
Do_nhiet_do_DS18B20_8051.zip
Kích thước: 517.33 KB


  • Bạn chưa đăng nhập, không thể viết bình luận!
    Bấm vào đây để Đăng nhập hoặc Đăng ký!
  • Vũ Văn Thái lúc 17-05-2021, 16:48
    @hieu27_02_00: Vòng lặp nhận bit về thôi, mỗi lần lặp là một lần dịch bit sang phải, sau đó đưa chân DQ=1 (8051 input pull up), kiểm tra chân DQ nếu DQ=1 thì dat |= 0x80 (lệnh OR bit), cuối cùng delay để qua vòng lặp bit tiếp theo, đủ 8bit là thoát vòng lặp.
  • hieu27_02_00 lúc 11-05-2021, 16:37
    unsigned char ReadOneChar(void){ //Đọc 1 byte từ IC
             unsigned char i=0;
             unsigned char dat = 0;
             for (i=8;i>0;i--){
                    DQ = 0;
                    dat>>=1;
                    DQ = 1;
                    if(DQ)
                    dat |= 0x80;
                    delay_18B20(4);
             }
             return(dat);
    Ở PHẦN NÀY EM CHƯA HIỂU LẮM A CÓ THỂ GIẢI THÍCH GIUPSEM VỚI Ạ
  • huy195 lúc 02-10-2017, 15:21
    unsigned char ReadOneChar(void){ //Đọc 1 byte từ IC
             unsigned char i=0;
             unsigned char dat = 0;
             for (i=8;i>0;i--){
                    DQ = 0;
                    dat>>=1;
                    DQ = 1;
                    if(DQ)
                    dat |= 0x80;
                    delay_18B20(4);
             }
             return(dat);
    ở phần này e chưa hiểu lắm,mong a giải thích dùm em
    em cảm ơn!!
  • trantrunghieuvt1995 lúc 03-05-2017, 22:40
    Cho mình hỏi là sao file mô phỏng của bạn mình mở k được vậy?
  • bthanhkha lúc 22-04-2017, 00:08
    Anh Thái cho e nhờ chút ak! giờ em muốn thêm nhiệt đột vào mạch này thì làm thế nào ak? kính mong anh trợ giúp
    CODE đây ak!

    #include<reg52.h>
    sbit DATA1 = P3^0;
    sbit SCK1 = P3^1;
    sbit LACH1 = P3^2;
    sbit   set=P3^4;
    sbit   up=P3^5;
    sbit   down=P3^6;
    unsigned char hour, minute, second,c;
    unsigned char ma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    unsigned char kt=0,a=0,i,k,x=0;
    bit set0=1,set1=1,up1=1,up0=1,down0=1,down1=1;
    sbit SCL = P1^0;
    sbit SDA = P1^1;
    void delay(){
    unsigned char i;
    for (i = 0; i < 4; i++){};
    }

    //-----------------------------------------
    void SCL_high(){
    SCL = 1;
    delay();
    }

    //------------------------------------------
    void SCL_low(){
    SCL = 0;
    delay();
    }

    //-------------------------------------------
    void I2C_Start(){
    SDA = 1;
    SCL = 1;
    SDA = 0;
    delay();
    SCL = 0;
    SDA = 1;
    }

    //--------------------------------------------
    void I2C_Stop(){
    SDA = 0;
    SCL_high();
    SDA = 1;
    }

    //----------------------------------------------
    bit I2C_Write(unsigned char dat){
    unsigned char i;
    bit outbit;
    for (i = 1; i <= 8; i++){
    outbit=dat&0x80;
    SDA = outbit;
    dat = dat << 1;
    SCL_high();
    SCL_low();
    }
    SDA = 1;
    SCL_high();
    outbit = SDA;
    SCL_low();
    return(outbit);
    }

    //----------------------------------------------------
    unsigned char I2C_Read(bit ack){
    unsigned char i, dat;
    bit inbit;

    dat = 0;
    for(i=1;i<=8;i++) {
    SCL_high();
    inbit = SDA;
    dat = dat << 1;
    dat = dat | inbit;
    SCL_low();
    }
    if (ack) SDA = 0;
    else SDA = 1;
    SCL_high();
    SCL = 0;
    SDA = 1;
    delay();
    return(dat);
    }

    //-------------------------------------------------------------
    void rtc_write(unsigned char add, unsigned char dat){
    I2C_Start();
    I2C_Write(0xd0);
    I2C_Write(add);
    I2C_Write(((dat/10)<<4)|(dat));
    I2C_Stop();
    }

    unsigned char rtc_read(unsigned char add){
    unsigned char dat;
    I2C_Start();
    I2C_Write(0xd0);
    I2C_Write(add);
    I2C_Start();
    I2C_Write(0xd1);
    dat = I2C_Read(0);
    I2C_Stop();
    dat = (dat & 0x0f) + (dat>>4)*10;
    return (dat);
    }
    void writeds(){
    rtc_write(0x00, second);
    rtc_write(0x01, minute);
    rtc_write(0x02, hour);
    }

    void readds()
    {
    if(kt==0)
    {
    if(a==1)
    {writeds();a=0;
    }
    second = rtc_read(0x00);
    minute = rtc_read(0x01);
    hour = rtc_read(0x02);
    }
    }

    void hienthi(unsigned char x)
    {
    unsigned int i,temp;
    for(i=0;i<8;i++)
    {
    temp=x;
    temp=temp&0x80;
    if(temp==0x80)
    DATA1=1;   
    else
    DATA1=0;   
    x*=2;   
    SCK1=0;   
    SCK1=1;   
    }
    }
    void quetled()
    {

    if(kt==0)
    {
    hienthi(ma[second]);
    hienthi(ma[second/10]);
    hienthi(ma[minute]);
    hienthi(ma[minute/10]);
    hienthi(ma[hour]);
    hienthi(ma[hour/10]);
    LACH1=0;   
    LACH1=1;
    }
    if(kt==1)
    {
    hienthi(0xff);
    hienthi(0xff);
    hienthi(0xff);
    hienthi(0xff);
    hienthi(ma[hour]);
    hienthi(ma[hour/10]);
    LACH1=0;   
    LACH1=1;
    }
    if(kt==2)
    {
    hienthi(0xff);
    hienthi(0xff);
    hienthi(ma[minute]);
    hienthi(ma[minute/10]);
    hienthi(0xff);
    hienthi(0xff);
    LACH1=0;   
    LACH1=1;
    }
    if(kt==3)
    {
    hienthi(ma[second]);
    hienthi(ma[second/10]);
    hienthi(0xff);
    hienthi(0xff);
    hienthi(0xff);
    hienthi(0xff);
    LACH1=0;   
    LACH1=1;
    }
    }
    void ktphim()
    {
    set0=set1;set1=set;
    if((set0==1)&&(set1==0))
       {
        kt++;
        if(kt>3)kt=0;
       }
    switch(kt)
    {
       case 0:break;
       case 1:
        {
           up0=up1;up1=up; a=1;
           if((up0==1)&&(up1==0))
           {
              hour++;
                  if(hour>23)hour=0;
           }
           down0=down1;down1=down;
           if((down0==1)&&(down1==0))
             {
              hour--;
                   if(hour==-1)
                   hour=23;
             }
          break;
        }
       case 2:
        {
          up0=up1;up1=up; a=1;
          if((up0==1)&&(up1==0))
           {
              minute++;
                if(minute>59)
                minute=0;
           }
          down0=down1;down1=down;
          if((down0==1)&&(down1==0))
           {
              minute--;
                if(minute==-1)
                minute=59;
           }
           break;
        }

       case 3:
        {
          up0=up1;up1=up;a=1;
          if((up0==1)&&(up1==0))
           {
           second++;
                if(second>59)
                second++;
           }
           down0=down1;down1=down;
          if((down0==1)&&(down1==0))
           {
           second=0;
           }
          break;
        }
        }
    }

    void main()
    {
        I2C_Start();
        I2C_Write(0xD0);
        I2C_Write(0x07);
        I2C_Write(0x10);
        I2C_Stop();         
          while(1)
    {
    ktphim();
    readds();
    quetled();
    }
    }
  • tuanan lúc 04-03-2016, 11:34
    Khong thay file tai o dau!
    • Vũ Văn Thái lúc 04-03-2016, 13:02
      Ngay trên chỗ bạn viết bình luận
  • notail lúc 14-08-2015, 21:56
    bạn có thể giải thích hộ mình đoạn này được ko?
    for (i=8;i>0;i--){
                    DQ = 0;
                    dat>>=1;
                    DQ = 1;
                    if(DQ)
                    dat |= 0x80;
                    delay_18B20(4);
             }
    • notail lúc 16-08-2015, 20:30
      mình hiểu rồi
  • Vũ Văn Thái lúc 13-07-2015, 19:13
    uk nhưng phải xử lý nó thì mới hiển thị được vì nó là số sau dấu phẩy
  • hoangtruonghl lúc 13-07-2015, 13:10
    Vậy giờ muốn lấy cả phần thập phân thì bỏ đoạn >>4 đi phải ko bạn?
  • Vũ Văn Thái lúc 25-03-2015, 06:26
    Do cảm biến của ta có độ phân giải 12bit mà ta lại chỉ cần 8bit lưu vào biến temp tức ta bỏ giá trị thập phân đi chỉ lấy phần nguyên, b*256 a là tính gộp 2 thanh ghi 8bit lại thành kiểu 16bit, tiếp đó dịch phải 4bit để lấy 8bit cao, bỏ 4bit thấp của 12bit dữ liệu, thì ta sẽ được giá trị nhiệt độ nguyên.
    • trungcx lúc 02-04-2015, 16:20
      tks a
  • Trang 1/2: 12Sau

    Bài viết cùng chuyên mục
    Điều khiển tốc độ động cơ Motor DC sử dụng PWM Điều khiển tốc độ động cơ Motor DC sử dụng PWM
    Đăng bởi: kienvuce - Thời gian: 04-11-2021, 22:40
    Chuyên mục: Học lập trình 8051 - Lượt xem: 3.786
    Chia sẻ bộ thư viện Driver chuẩn cho LCD Gphone và Home Phone Chia sẻ bộ thư viện Driver chuẩn cho LCD Gphone và Home Phone
    Đăng bởi: Vũ Văn Thái - Thời gian: 22-02-2017, 14:54
    Chuyên mục: Học lập trình 8051 - Lượt xem: 7.016
    Led 7 thanh 4 số điều khiển bằng nút bấm Led 7 thanh 4 số điều khiển bằng nút bấm
    Đăng bởi: HoangQuan69 - Thời gian: 09-10-2016, 15:08
    Chuyên mục: Học lập trình 8051 - Lượt xem: 6.625
    Chia sẻ Code đồng hồ số hiển thị trên LED 7 đoạn dùng 89S52 và DS1307 Chia sẻ Code đồng hồ số hiển thị trên LED 7 đoạn dùng 89S52 và DS1307
    Đăng bởi: Vũ Văn Thái - Thời gian: 13-05-2015, 09:00
    Chuyên mục: Học lập trình 8051 - Lượt xem: 29.978
    Bài 15: Lập trình quét phím matrix 4x4 hiển thị lên LCD 16x2 Bài 15: Lập trình quét phím matrix 4x4 hiển thị lên LCD 16x2
    Đăng bởi: Vũ Văn Thái - Thời gian: 20-11-2014, 08:57
    Chuyên mục: Học lập trình 8051 - Lượt xem: 34.054
    [Share] Code giao tiếp Graphic LCD 12864 SPI của máy GPHONE ZTE [Share] Code giao tiếp Graphic LCD 12864 SPI của máy GPHONE ZTE
    Đăng bởi: Vũ Văn Thái - Thời gian: 12-11-2014, 22:06
    Chuyên mục: Học lập trình 8051 - Lượt xem: 20.179
    [Share] Code C đo nhiệt độ dùng DS18B20 hiển thị lên LED 7 thanh [Share] Code C đo nhiệt độ dùng DS18B20 hiển thị lên LED 7 thanh
    Đăng bởi: Vũ Văn Thái - Thời gian: 12-11-2014, 09:02
    Chuyên mục: Học lập trình 8051 - Lượt xem: 20.508
    Bài 13: Đo nhiệt độ dùng LM35 kết hợp IC ADC0808 với 8051 Bài 13: Đo nhiệt độ dùng LM35 kết hợp IC ADC0808 với 8051
    Đăng bởi: Vũ Văn Thái - Thời gian: 22-08-2014, 22:18
    Chuyên mục: Học lập trình 8051 - Lượt xem: 47.425
    Bài 12: Tạo xung PWM dùng ngắt timer 8051 Bài 12: Tạo xung PWM dùng ngắt timer 8051
    Đăng bởi: Vũ Văn Thái - Thời gian: 02-03-2014, 20:45
    Chuyên mục: Học lập trình 8051 - Lượt xem: 25.271
    Bài 11: Lập trình quét LED 7 đoạn và nút nhấn Bài 11: Lập trình quét LED 7 đoạn và nút nhấn
    Đăng bởi: Vũ Văn Thái - Thời gian: 19-12-2013, 11:02
    Chuyên mục: Học lập trình 8051 - Lượt xem: 54.668
    Chào mừng kkkk06 đã tham gia câu lạc bộ sáng tạo!
    Vũ Văn Thái - vuthai
    Hôm nay là sinh nhật của nkocvipvodoi, vietduy, nguyenkhachuy, dohoainhu94, phamtieuvi, hoavci36, nguyenkhachuy53ddt, teotetua, HaVan_93, huybean2609, vuthanh1971, thientubatpham, aq_codientu, Kiatythep, hocuongz95, haisonitu, boysontay, haisonwmn, thongvn_95, vietbmw1986, ← Gửi tin nhắn chúc mừng
    Múi giờ: UTC+07:00 - Asia/Ho Chi Minh ***** IP của bạn: 3.135.195.180 ***** Status: Cache Update thành công!