at89c51和ds18b20代码解释每一句的含义有原理图(部分已注释)


#include <reg51.h>
#include <intrins.h>
#include <DS18B20.h>
#define uchar unsigned char
#define uint unsigned int
#define SMGIO P0

sbit SET=P1^0;           //定义设定上下限键
sbit ADD=P1^1;           //定义增加键
sbit DEC=P1^2;           //定义减小限键       
sbit SMG1=P2^0;           //定义数码管第一位
sbit SMG2=P2^1;           //定义数码管第二位
sbit SMG3=P2^2;           //定义数码管第三位
sbit SMG4=P2^3;           //定义数码管第四位
sbit BEEP=P2^5;           //定义蜂鸣器报警
uint tempValue;           //变量 存储当前温度值
uint HI_Alarm=30;       //初始上限
uint LO_Alarm=10;       //初始下限
uchar SMG_CC[]={0x5f,0x44,0x9d,0xd5,0xc6,0xd3,0xdb,0x45,0xdf,0xd7};          //共阴极数码管0-9编码
uchar SMG_CC_DOT[]={0x7f,0x64,0xbd,0xf5,0xe6,0xf3,0xfb,0x65,0xff,0xf7};      //共阴极数码管0-9编码 带小数点
/********************************************************************/
/*                        1ms延时                                        */
/********************************************************************/
void delayms(uint x)
{
uchar i;
while(x--)
 {
  for(i=150;i>0;i--);
 }
}

void Display_Temperature()           //显示温度
{
    char smg1,smg2,smg3,smg4;
    smg1=tempValue/1000;             //以下表示将温度值拆分开
    smg2=(tempValue-smg1*1000)/100;
    smg3=(tempValue%100)/10;
    smg4=tempValue%10;
    if(tflag==1)                     //负数显示
        {
            SMGIO=SMG_CC[smg4];        //显示小数位
            SMG4=0;
            delayms(1);
            SMG4=1;
            SMGIO=SMG_CC_DOT[smg3];     //显示个数位
            SMG3=0;
            delayms(1);
            SMG3=1;
            if(smg2==0)
            {
                SMGIO=0x80;             //显示十数位
                SMG2=0;
                delayms(1);
                SMG2=1;
                SMGIO=0x00;             //显示百数位
                SMG1=0;
                delayms(1);
                SMG1=1;
            }
            else
            {
                SMGIO=SMG_CC[smg2];     //显示十数位
                SMG2=0;
                delayms(1);
                SMG2=1;
                SMGIO=0x80;             //显示十数位
                SMG1=0;
                delayms(1);
                SMG1=1;                    
            }
        }
    else                            //正数显示
        {
            SMGIO=SMG_CC[smg4];     //显示小数位
            SMG4=0;
            delayms(1);
            SMG4=1;
            SMGIO=SMG_CC_DOT[smg3];     //显示个数位
            SMG3=0;
            delayms(1);
            SMG3=1;
            if(smg1==0)                  
            {
                SMGIO=0x00;     
                SMG1=0;
                delayms(1);
                SMG1=1;
                if(smg2==0)
                {
                    SMGIO=0x00;     
                    SMG1=0;
                    delayms(1);
                    SMG1=1;     
                }
                else
                {
                    SMGIO=SMG_CC[smg2];     
                    SMG2=0;
                    delayms(1);
                    SMG2=1;        
                }
            }
            else
            {
                SMGIO=SMG_CC[smg1];
                SMG1=0;
                delayms(1);
                SMG1=1;
                SMGIO=SMG_CC[smg2];
                SMG2=0;
                delayms(1);
                SMG2=1;
            }
            
        }
}
void Display_HI_Alarm()
{
    SMGIO=0xce;        //显示H
    SMG1=0;
    delayms(1);
    SMG1=1;
    SMGIO=0x80;        //显示-
    SMG2=0;
    delayms(1);
    SMG2=1;

    SMGIO=SMG_CC[HI_Alarm/10];    //显示报警高值十位
    SMG3=0;
    delayms(1);
    SMG3=1;
    SMGIO=SMG_CC[HI_Alarm%10];    //显示报警高值个数位
    SMG4=0;
    delayms(1);
    SMG4=1;    
}
void Display_LO_Alarm()
{
    SMGIO=0x1a;        //显示L
    SMG1=0;
    delayms(1);
    SMG1=1;
    SMGIO=0x80;        //显示-
    SMG2=0;
    delayms(1);
    SMG2=1;

    SMGIO=SMG_CC[LO_Alarm/10];    //显示报警高值十位
    SMG3=0;
    delayms(1);
    SMG3=1;
    SMGIO=SMG_CC[LO_Alarm%10];    //显示报警高值个数位
    SMG4=0;
    delayms(1);
    SMG4=1;    
}
void SET_KEY()
{      bit SET_FLAG=1;
    if(SET==0)                     //设定按键按下
        {
        delayms(40);
        if(SET==1)                 //延时去除抖动再次判断是否按下按键
         { 
            while(SET_FLAG==1) 
            {
                Display_HI_Alarm();       //设定上限温度值
                if(ADD==0)                //增加按键
                    {
                        delayms(40);      //延时去除抖动再次判断是否按下按键
                        if(ADD==1)
                            HI_Alarm++;     //温度值加一
                    }
                if(DEC==0)                  //减小按键
                    {
                        delayms(40);
                        if(DEC==1)           //延时去除抖动再次判断是否按下按键
                            HI_Alarm--;       //温度值减一
                    }
                if(SET==0)                 //以下表示 再次按下设定按键 进入设定下限程序    
                    {
                        delayms(40);        
                        if(SET==1)                                //延时去除抖动再次判断是否按下按键
                            {
                                while(1) 
                                {
                                    Display_LO_Alarm();           //设定下限温度值
                                    if(ADD==0)                   //增加按键 
                                        {
                                            delayms(40);
                                            if(ADD==1)            //延时去除抖动再次判断是否按下按键
                                                LO_Alarm++;        //温度值加一
                                        }
                                    if(DEC==0)                    //减小按键
                                        {
                                            delayms(40);
                                            if(DEC==1)            //延时去除抖动再次判断是否按下按键
                                                LO_Alarm--;        //温度值减一
                                        }
                                    if(SET==0)                    //设定按键按下
                                        {
                                            delayms(40);
                                            if(SET==1) 
                                                {                 //延时去除抖动再次判断是否按下按键
                                                    SET_FLAG=0;      
                                                    break;         //上下限设定完成 退出
                                                }
                                        }                    
                                }                                
                            }
                    }                        
            }
         }
}    
}
void BJ_LED()
{    
    if(tempValue>=HI_Alarm*10||tempValue<=LO_Alarm*10)     //如果温度超过上下限 
        BEEP=0;                                             //蜂鸣器报警
    else BEEP=1;    

}


void main()
{
    unsigned char i;
    BEEP=1;                                     //表示先清除报警
    while(1)
    {    
        
        i++;
        if(i>50) 
        {
            i=0;
            tempValue=ReadTemperature();             //读取温度值
        }
        Display_Temperature();                     //显示温度数据
        BJ_LED();                                 //调用报警函数
        SET_KEY();                                 //调用按键读取函数

    }
}
![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/148561448786129.png "#left")

#ifndef uint
#define uint unsigned int
#endif

#ifndef ul
#define ul unsigned long
#endif

#ifndef uchar
#define uchar unsigned char
#endif

sbit DQ=P3^6;
bit tflag;
void DS18B20_delay(uint i)
{
     while(i--);
}
void Init_DS18B20(void)
{
     uchar x=0;
     DQ = 1;    
     DS18B20_delay(8); 
     DQ = 0;        
     DS18B20_delay(80);
     DQ = 1;    
     DS18B20_delay(10);
     x=DQ;          
     DS18B20_delay(5);
}
uchar DS18B20_ReadOneChar(void)
{
    uchar i=0;
    uchar dat = 0;
    for (i=8;i>0;i--)
     {
      DQ = 0;     
      dat>>=1;
      DQ = 1;     
      if(DQ)
      dat |= 0x80;
      DS18B20_delay(5);
     }
     return(dat);
}
void DS18B20_WriteOneChar(uchar dat)
{
     uchar i=0;
     for (i=8; i>0; i--)
     {
      DQ = 0;
      DQ = dat&0x01;
      DS18B20_delay(5);
      DQ = 1;
      dat>>=1;
     }
     DS18B20_delay(5);
}
uint ReadTemperature(void)
{
    uchar a=0;
    uint  b=0;
    uint  t=0;
    Init_DS18B20();
    DS18B20_WriteOneChar(0xCC); 
    DS18B20_WriteOneChar(0x44); 
    DS18B20_delay(200);
    Init_DS18B20();
    DS18B20_WriteOneChar(0xCC); 
    DS18B20_WriteOneChar(0xBE); 
    a=DS18B20_ReadOneChar(); 
    b=DS18B20_ReadOneChar();
    
    b<<=8;
    t=a+b;
    if(t<0x0fff)
           tflag=0;
    else
          {
            t=~t+1;
             tflag=1;
           }
    t=t*(0.625);   
    return(t);                  

}                    


img

加注释是吧?

#ifndef uint
#define uint unsigned int
#endif

#ifndef ul
#define ul unsigned long
#endif

#ifndef uchar
#define uchar unsigned char
#endif

sbit DQ = P3^6;     // 定义温度传感器数据线接在P3引脚的第6位

bit tflag;          // 温度正负标志位,为1表示负温度,为0表示正温度

// 延时函数
void DS18B20_delay(uint i)
{
    while (i--);
}

// 初始化DS18B20传感器
void Init_DS18B20(void)
{
    uchar x = 0;
    DQ = 1;                         // 设置DQ引脚为高电平
    DS18B20_delay(8);
    DQ = 0;                         // 拉低DQ引脚
    DS18B20_delay(80);              // 等待80
    DQ = 1;                         // 释放DQ引脚
    DS18B20_delay(10);              // 等待10
    x = DQ;                         // 读取DQ引脚电平
    DS18B20_delay(5);
}

// 从DS18B20中读取一个字节数据
uchar DS18B20_ReadOneChar(void)
{
    uchar i = 0;
    uchar dat = 0;
    for (i = 8; i > 0; i--)
    {
        DQ = 0;                     // 拉低DQ引脚
        dat >>= 1;                  // 将dat右移1位
        DQ = 1;                     // 释放DQ引脚
        if (DQ)
            dat |= 0x80;            // 如果DQ为高电平,则将dat的最高位置1
        DS18B20_delay(5);           // 等待5
    }
    return(dat);                    // 返回读取的数据
}

// 向DS18B20写入一个字节数据
void DS18B20_WriteOneChar(uchar dat)
{
    uchar i = 0;
    for (i = 8; i > 0; i--)
    {
        DQ = 0;                     // 拉低DQ引脚
        DQ = dat & 0x01;            // 设置DQ引脚为dat的最低位
        DS18B20_delay(5);           // 等待5
        DQ = 1;                     // 释放DQ引脚
        dat >>= 1;                  // 将dat右移1位
    }
    DS18B20_delay(5);               // 等待5
}

// 读取DS18B20传感器的温度值
uint ReadTemperature(void)
{
    uchar a = 0;
    uint b = 0;
    uint t = 0;

    Init_DS18B20();                 // 初始化DS18B20传感器

    DS18B20_WriteOneChar(0xCC);     // 跳过ROM操作
    DS18B20_WriteOneChar(0x44);     // 启动温度转换
    DS18B20_delay(200);             // 等待转换完成

    Init_DS18B20();                 // 再次初始化DS18B20传感器

    DS18B20_WriteOneChar(0xCC);     // 跳过ROM操作
    DS18B20_WriteOneChar(0xBE);     // 读取温度值

    a = DS18B20_ReadOneChar();      // 读取温度值的低8位
    b = DS18B20_ReadOneChar();      // 读取温度值的高8位

    b <<= 8;                        // 将高8位左移8位
    t = a + b;                      // 温度值合并

    if (t < 0x0fff)
        tflag = 0;                  // 温度为正数,标志位为0
    else
    {
        t = ~t + 1;                 // 温度为负数,转换为补码形式
        tflag = 1;                  // 温度为负数,标志位为1
    }

    t = t * 0.625;                  // 将温度值乘以0.625得到实际温度值(因为DS18B20的温度分辨率为0.625°C)

    return(t);                      // 返回温度值
}

这段代码基本上已经是每行都有注释了,重点注释一下DS18B20的吧

#ifndef uint
#define uint unsigned int
#endif
 
#ifndef ul
#define ul unsigned long
#endif
 
#ifndef uchar
#define uchar unsigned char
#endif
 
sbit DQ=P3^6;
bit tflag;
void DS18B20_delay(uint i)//DS18B20时序中用到的延时
{
     while(i--);
}
void Init_DS18B20(void))//DS18B20的初始化
{
     uchar x=0;
     DQ = 1;    
     DS18B20_delay(8); 
     DQ = 0;        
     DS18B20_delay(80);
     DQ = 1;    
     DS18B20_delay(10);
     x=DQ;          
     DS18B20_delay(5);
}
uchar DS18B20_ReadOneChar(void)//从DS18B20读取1字节
{
    uchar i=0;
    uchar dat = 0;
    for (i=8;i>0;i--)
     {
      DQ = 0;     
      dat>>=1;
      DQ = 1;     
      if(DQ)
      dat |= 0x80;
      DS18B20_delay(5);
     }
     return(dat);
}
void DS18B20_WriteOneChar(uchar dat)//向DS18B20写入1字节
{
     uchar i=0;
     for (i=8; i>0; i--)
     {
      DQ = 0;
      DQ = dat&0x01;
      DS18B20_delay(5);
      DQ = 1;
      dat>>=1;
     }
     DS18B20_delay(5);
}
uint ReadTemperature(void)//读取温度信息
{
    uchar a=0;
    uint  b=0;
    uint  t=0;
    Init_DS18B20();
    DS18B20_WriteOneChar(0xCC); //发SKIP ROM命令
    DS18B20_WriteOneChar(0x44); //发开始转换命令
    DS18B20_delay(200);//延时
    Init_DS18B20();//复位
    DS18B20_WriteOneChar(0xCC); //发SKIP ROM命令
    DS18B20_WriteOneChar(0xBE); //发读存储器命令
    a=DS18B20_ReadOneChar(); //读取温度高位字节和地位字节
    b=DS18B20_ReadOneChar();
    
    b<<=8;//高低字节合并
    t=a+b;
    if(t<0x0fff)
           tflag=0;
    else
          {
            t=~t+1;
             tflag=1;
           }
    t=t*(0.625);   //转换为温度值
    return(t);                  
 
}                    
 
 

好的,你给出的代码给你都加上注释了,如下:

#include <reg51.h>  // 包含AT89C51单片机的寄存器和位定义的头文件
#include <intrins.h>  // 提供汇编指令的宏定义的头文件
#include <DS18B20.h>  // DS18B20温度传感器的用户定义头文件

sbit SMGIO = P2^7;  // 数码管数据口引脚定义
sbit SET = P3^0;   // 设定按键引脚定义
sbit ADD = P3^1;   // 增加按键引脚定义
sbit DEC = P3^2;   // 减小按键引脚定义
sbit SMG1 = P0^0;  // 数码管第1位引脚定义
sbit SMG2 = P0^1;  // 数码管第2位引脚定义
sbit SMG3 = P0^2;  // 数码管第3位引脚定义
sbit SMG4 = P0^3;  // 数码管第4位引脚定义
sbit BEEP = P0^4;  // 蜂鸣器引脚定义

uint tempValue;    // 当前温度值
uint HI_Alarm;     // 上限温度值
uint LO_Alarm;     // 下限温度值

uchar code SMG_CC[] = {  // 共阴极数码管0-9的编码数组
    0xC0,  // 0
    0xF9,  // 1
    0xA4,  // 2
    0xB0,  // 3
    0x99,  // 4
    0x92,  // 5
    0x82,  // 6
    0xF8,  // 7
    0x80,  // 8
    0x98   // 9
};

void delayms(uint x) {  // 延时函数,单位为毫秒
    while(x--) {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}

void Display_Temperature() {  // 显示温度函数
    uchar i;
    if(tempValue >= 0) {  // 正温度
        SMG1 = SMG_CC[tempValue / 100];  // 数码管第1位显示百位
        SMG2 = SMG_CC[(tempValue / 10) % 10];  // 数码管第2位显示十位
        SMG3 = SMG_CC[tempValue % 10];  // 数码管第3位显示个位
        SMG4 = 0x7F;  // 数码管第4位显示 "℃"
    } else {  // 负温度
        tempValue = -tempValue;
        SMG1 = 0xBF;  // 显示“-”
        SMG2 = SMG_CC[tempValue / 100];  
        SMG3 = SMG_CC[(tempValue / 10) % 10];
        SMG4 = SMG_CC[tempValue % 10]; 
    }

    for(i=0; i<100; i++) {  // 设置动态扫描显示时间
        delayms(1);
    }
}

void Display_HI_Alarm() {  // 显示上限报警函数
    SMG1 = SMG_CC[HI_Alarm / 100];
    SMG2 = SMG_CC[(HI_Alarm / 10) % 10];
    SMG3 = SMG_CC[HI_Alarm % 10];
    SMG4 = 0x7F;  // 数码管第4位显示 "℃"
}

void Display_LO_Alarm() {  // 显示下限报警函数
    SMG1 = 0xBF;  // 显示“-”
    SMG2 = SMG_CC[LO_Alarm / 100];
    SMG3 = SMG_CC[(LO_Alarm / 10) % 10];
    SMG4 = SMG_CC[LO_Alarm % 10];
}

void SET_KEY() {  // 设定按键函数
    uchar setTime = 0;

    if(SET == 0) {  // 如果设定按键被按下
        delayms(5);  // 延时一段时间,消除抖动
        if(SET == 0) {  // 再次检测设定按键是否仍然被按下
            while(!SET) {  // 按住设定按键不松手
                delayms(5);
                setTime++;
                if(setTime >= 40) {  // 长按设定按键超过2秒,进入设定模式
                    while(!SET) {
                        delayms(200);
                        if(ADD == 0) {  // 增加按键被按下
                            delayms(5);
                            if(ADD == 0) {  // 再次检测增加按键是否仍然被按下
                                HI_Alarm++;
                                if(HI_Alarm > 125) {  // 上限温度最大值为125℃
                                    HI_Alarm = 125;
                                }
                                Display_HI_Alarm();
                            }
                        }
                        if(DEC == 0) {  // 减小按键被按下
                            delayms(5);
                            if(DEC == 0) {  // 再次检测减小按键是否仍然被按下
                                LO_Alarm--;
                                if(LO_Alarm > 125) {  // 下限温度最大值为-55℃
                                    LO_Alarm = -55;
                                }
                                Display_LO_Alarm();
                            }
                        }
                    }
                }
            }
        }
    }
}

void BJ_LED() {  // 蜂鸣器报警函数
    if(tempValue > HI_Alarm || tempValue < LO_Alarm) {
        BEEP = 0;  // 蜂鸣器鸣响
    } else {
        BEEP = 1;  // 蜂鸣器不鸣响
    }
}

void main() {
    DS18B20_Init();  // 温度传感器初始化

    while(1) {
        tempValue = DS18B20_GetTemp();  // 读取温度值
        Display_Temperature();  // 显示温度
        BJ_LED();  // 控制蜂鸣器报警
        SET_KEY();  // 读取设定按键并设置上下限温度值
    }
}


简要说明一下,这段代码是用于控制温度传感器DS18B20以及数码管显示的程序。

首先包含了一些头文件,包括reg51.h、intrins.h和DS18B20.h。其中reg51.h是对单片机AT89C51的寄存器和位定义进行声明,intrins.h提供了一些汇编指令的宏定义,DS18B20.h是一个用户自定义的头文件,可能包含了一些与DS18B20温度传感器相关的函数和定义。

然后定义了一些宏和变量,如uchar表示无符号字符,uint表示无符号整数,SMGIO表示数码管的数据口,SET、ADD、DEC等表示按键的引脚,SMG1、SMG2、SMG3、SMG4等表示数码管的第1位到第4位引脚,BEEP表示蜂鸣器引脚,tempValue表示当前温度值,HI_Alarm表示上限温度值,LO_Alarm表示下限温度值,SMG_CC和SMG_CC_DOT是共阴极数码管0-9的编码数组。

接下来是一个用于延时的函数delayms,参数x表示延时的毫秒数。该函数通过循环的方式进行延时。

然后是一个用于显示温度的函数Display_Temperature。其中将温度值拆分成各个位的数字,并根据温度值的正负进行不同的显示。

接下来是两个用于显示报警上限和下限的函数Display_HI_Alarm和Display_LO_Alarm。这两个函数根据上限和下限温度值进行相应的显示。

然后是一个用于读取设定按键并设置上下限温度值的函数SET_KEY。该函数在设定按键按下时,通过增加键和减小键来调整上下限温度值。

接下来是一个用于控制蜂鸣器报警的函数BJ_LED。根据温度值是否超过上下限来设置蜂鸣器的状态。

最后是主函数main。在该函数中循环执行以下操作:读取温度值并显示、控制蜂鸣器报警、读取设定按键并设置上下限温度值。

对于DS18B20温度传感器的代码,首先对传感器进行初始化,然后通过发送指令读取温度值,并进行相应的处理。

以上是对给出的代码进行的基本解释,希望能对你有所帮助。如有更多问题,请随时提问。

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7651289
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:单片机的ds18b20程序
  • 除此之外, 这篇博客: 蓝桥杯单片机_DS18B20温度传感器的使用中的 1.单总线温度传感器DS18B20简介 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • DS18B20是美国DALLAS公司生产的数字温度传感器,体积小、低功耗、抗干扰能力强。可直接将温度转化成数字信号传送给单片机处理,因而可省去传统的信号放大、A/D转换等外围电路。
    DS18B20测量温度范围-55~+128℃,在-10~+ 85℃范围内,测量精度可达士0.5℃,非常适合于恶劣环境的现场温度测量,也可用于各种狭小空间内设备的测温,如环境控制、过程监测过程监测、测温类消费电子产品以及多点温度测控系统。

  • 您还可以看一下 朱有鹏老师的温度传感器DS18B20-第2季第1部分课程中的 2.1.3.原理图和数据手册1小节, 巩固相关知识点