打印

ds18b20多点测温的程序

[复制链接]
6705|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1099789832|  楼主 | 2013-5-2 22:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Build target 'Target 1'
compiling bian.c...
linking...
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
    SYMBOL:  T
    MODULE:  bian.obj (BIAN)
Program Size: data=63.0 xdata=0 code=2022
Target not created
编译完总出现以上错误,无法生成hex文件

#include<reg52.h>
   #include<intrins.h>                                                                                    
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P1^0;             //DS18B20通信端口
//sbit dula=P2^4;                                //数码管段选线
//sbit wela=P2^5;                                //数码管位选线
sbit BEE=P2^0;                                 //蜂鸣器

char clear = 0xff;
sbit wela1=P2^7;
sbit wela2=P2^6;
sbit wela3=P2^5;
sbit wela4=P2^4;

sbit key2=P1^4;                                //DS18B20选择按键
sbit P11=P1^5;                                //报警上下限温度设置键
sbit P12=P1^6;                                //温度设置加1键       
sbit P13=P1^7;                                //温度设置减1键

uchar code table[]={
0x3f,0x06,0x5b,0x4f,                        //共阴极数码管字型码
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00};

uchar code table1[]={
0xbf,0x86,0xdb,0xcf,                        //共阴极数码管字型码,带小数点
0xe6,0xed,0xfd,0x87,
0xff,0xef,0x00};
uchar ba,sh,ge,aa;
uchar SN[3][8];        //3个DS18B20的序列号,先读出单个序列号填上才可以读取温度
uint temp1,T,t,xs,ID,keycon,max,min;
void display(uchar ba,uchar sh,uchar ge,uchar aa);  //数码管温度显示子程序,PO口输出
void alarm();             //上下限蜂鸣器报警
void delayms(int z);       //1ms延时子程序,延时时间以12MHz晶振为准1ms×z
void delay(unsigned int time); //20 延时子程序, 延时时间以12MHz晶振为准
               //用于DS18B20初始化
void change_start();         //发送18b20开始转换命令
void readtemp();   //读取温度,判断键值j,0,1,2分别发送三个DS18B20的序列号.
void increase();    //加1子函数,进入上限或者下限温度设定,max,min加1会有不同的限制,由环境要求灵活设定。
void decrease();    //减1子函数
void rom();       //读取器件序列号的子程序,调用时确保总线中只有一只器件
void key(void);     //上下限报警温度设置按键
void key_select(void); //选择要发送的DS18B20序列号,选择不同点的的传感器显示温度

void display1(int T);   //上下限报警温度设定显示子程序,显示范围0℃~70℃,均为整数         */



/****************************************************************
函数名:delayms()
描述:1ms延时子程序,延时时间以12MHz晶振为准1ms×z
******************************************************************/
void delayms(int z)
{
        int x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
/****************************************************************
函数名:delay()
描述:20 延时子程序, 延时时间以12MHz晶振为准20 ×time
******************************************************************/
void delay(unsigned int time)   
{
        unsigned int n=2;
        unsigned char m=2;
                for (n=0;n<time;n++)
                        for(m=0;m<2;m++);
}



/****************************************************************
函数名:reset()
描述:用于DS18B20初始化
******************************************************************/
unsigned char reset(void)
{
        uchar tdq;
                
        DQ=1;
        _nop_();
        _nop_();
        DQ=0;                                                        //拉低DQ总线开始复位
        delay(24);                                                //保持低电平480  
        DQ=1;                                                        //释放总线
        delay(4);                                                //等待芯片应答信号80  
        tdq=DQ;                                        //获取应答信号
        delay(24);                                                //完成整个时序
        return tdq;
}  
/****************************************************************
函数名:read_bit()
描述:读一位数据子程序******************************************************************/
unsigned char read_bit(void)   
{
        unsigned char tdq;          
    _nop_();
        DQ=0;                                                        //拉低DQ,开始读时序
        _nop_();
        DQ=1;
        _nop_();                                                //释放总线
        tdq=DQ;
        delay(3);                                         //延时60 ,等待读操作结束
        return tdq;
}  
/****************************************************************
函数名:read_byte()
描述:读一字节数据子程序******************************************************************/
unsigned char read_byte(void)     
{
        unsigned char i,tmp,dat=0;
        for(i=0;i<8;i++)
        {
        tmp=read_bit();
                            //读一字节数据,一个时序中读一次,并作移位处理
        dat|=tmp<<i;
        }
        delay(4);                        //延时80 以完成此次时序,之后再读下一数据
        return dat;
}
/****************************************************************
函数名:write_bit()
描述:写一位数据子程序******************************************************************/
void write_bit(unsigned char bitval)
{
    _nop_();
        DQ=0;
        _nop_();                                                //拉低DQ以开始一个写时序
        if(bitval)
                {
                DQ=1;
                delay(4);
                }
            else
                {
                 delay(4);
             DQ=1;
                }                                //延时80 供DS18B20采样
                                                        //释放DQ总线
               
}         
/****************************************************************
函数名:write_byte()
描述:写一字节数据子程序******************************************************************/
void write_byte(unsigned char dat)   
{
        unsigned int i;
        unsigned char j;
        for(i=0;i<8;i++)                                        //写一字节数据,一次写一位
                {
            j=dat>>i;                                                 //移位操作,将本次要写的位移到最低位
                        j=j&0x01;
                        write_bit(j);
                }
                delay(6);
}  
/****************************************************************
函数名:alarm()
描述:上下限蜂鸣器报警
******************************************************************/
void alarm()
{
        BEE=1;                       
        if(t>=max)                                                //温度大于设定最大值进入报警循环
                {
                        BEE=0;                                        //打开蜂鸣器
                        delayms(500);                        //延时       
                        BEE=1;                                        //关闭蜂鸣器
                        delayms(500);                         //延时
                }
        if(t<=min)                                                //温度小于设定最小值进入报警循环
                 {
                        BEE=0;
                        delayms(500);
                        BEE=1;
                        delayms(500);
                }
}
/****************************************************************
函数名:change_start()
描述:发送18b20开始转换命令
******************************************************************/
void change_start(void)
{
        reset();
        delayms(1000);
        write_byte(0xcc);                //跳过序列号命令,对所有器件有效
        write_byte(0x44);                //发送转换命令44H 所有器件转换
}
/****************************************************************
函数名:readtemp()
描述:读取温度,判断键值j,0,1,2分别发送三个DS18B20的序列号.
******************************************************************/
void readtemp()
{
        uchar i,j;
        uchar a,b,t;
                i=0;
                if(keycon==0)                        //按键寻址,选择要显示的检测器件
                {
                   j=1;
                }
                if(keycon==1)
                {
                         j=2;
                }
                if(keycon==2)
                {
                        j=3;
                }                  
                reset();          //复位       
                delayms(1000);                 //延时
                write_byte(0x55);                           //发送ROM匹配命令
                for(i=0;i<8;i++)
                {
                        write_byte(SN[j][i]);              //发送64位序列号
                }
                write_byte(0xbe);                         //发送读取命令
                a=read_byte();                                //读取温度值低位
                b=read_byte();                                //度取温度值高位
                b=(i<<4)&0x7f;                                //屏蔽最高位(一位符号位)
                a=a>>4;                                                //低位右移,舍弃小数位。
                t=b|a;                                                //实际温度整数部分
                temp1=a&0x0f;
                xs=temp1*0.0625*10;                 //小数部分,若为0.5则算为了5来显示
       
}
/****************************************************************
函数名:rom()
描述:读取器件序列号的子程序,调用时确保总线中只有一只器件 ,
若多个器件时则读取出来的序列号号码无效            
使用时先调用"ROM()"子程序读出每个器件的序列号
再将各个序列号填入SN数组中才能读出各个温度
******************************************************************/
void rom()
{
        uchar sn1;                                        //以下是定义8个序列号变量
        uchar sn2;
        uchar sn3;
        uchar sn4;
        uchar sn5;
        uchar sn6;
        uchar sn7;
        uchar sn8;

        reset();                //复位
        delayms(1000);                                //延时1S
        write_byte(0x33);                         //发送读序列号子程序
        sn1=read_byte();                        //读取第一个序列号,
        sn2=read_byte();                        //读取第二个序列号
        sn3=read_byte();                               
        sn4=read_byte();
        sn5=read_byte();
        sn6=read_byte();
        sn7=read_byte();
        sn8=read_byte();
}
/****************************************************************
函数名:key()
描述:上下限报警温度设置按键
******************************************************************/
void key(void)
{
        do                                                       
{
if(P11==0)                                                        //判断SET键是否按下
        {
                delayms(20);                                 //延时去抖
                if(P11==0)                                               
                        {
                                 ID++;
                                if(ID>=3)
                                {
                                ID=0;
                                }
                                while(P11==0);
                        }
        }               
                                if(ID==1)                                        //ID=1进入报警温度上限值设定
                                {
                                        display1(max);                                //显示报警温度上限值
                                        if(P12==0)
                                        {       
                                                delayms(20);
                                                if(P12==0)                                //判断加1键是否按下
                                                {
                                                 increase();                                //加"1"
                                                display1(max);                        //重新显示报警温度上限值
                                            }
                                        while(P12==0);
                                        }
                                        if(P13==0)                                       
                                        {
                                                delayms(20);
                                                if(P13==0)                                 //判断减1键是否按下
                                                {
                                                decrease();                                //减"1"
                                                display1(max);                        //重新显示报警温度上限值
                                                }
                                         while(P13==0);                                //知道释放按键,退出循环
                                        }
                                }
                         if(ID==2)                                                //ID=2进入报警温度下限值设定
                                {
                                        display1(min);                //重新显示报警温度下限值
                                        if(P12==0)
                                        {       
                                                delayms(20);
                                                if(P12==0)                                //判断加1键是否按下
                                                {
                                                 increase();                                //加"1"
                                                display1(min);       
                                            }
                                        while(P12==0);
                                        }
                                        if(P13==0)
                                        {
                                                delayms(20);
                                                if(P13==0)                                //判断减1键是否按下
                                                {
                                                decrease();                                //减"1"
                                                display1(min);                        //重新显示报警温度下限值
                                                }
                                         while(P13==0);
                                        }
       }
}while(ID==0);        //进入循环,知直到D=0,即SET按键要按第三下才能退出该温度设定程序
}
/****************************************************************
函数名:key_select ()
描述:选择要发送的DS18B20序列号,选择不同点的的传感器显示温度
******************************************************************/
void key_select(void)
{
        keycon=0;                                                        //器件选择标志位
        if(key2==0)                                                       
        {
                delayms(20);                           
                if(key2==0)                                               
                        {
keycon++;        //通过器件选择按键自加,标志位值代表三个不同器件
                                if(keycon>=3)
                                {
                                keycon=0;
                                }
                                while(key2==0);
                        }
        }               
}                                                       
/****************************************************************
函数名:increase()
描述:加1子函数,进入上限或者下限温度设定,max,min加1会有不同的限                   制,由环境要求灵活设定。
******************************************************************/
void increase()
{
        if(ID==1)                               
        {
                max++;
                if(max>=70)                                //设定上限温度不得超过70,超过就默认为70
                {
                        max=70;
                }
        }
        if(ID==2)
        {
                if(min<max-10)                       
                {
                min++;
                }
                else
                {
                        min=max-10;
                }
                }
        }

/****************************************************************
函数名:decrease()
描述:减1子函数,进入上限或者下限温度设定,max,min减1会有不同的限                   制,由环境要求灵活设定。
******************************************************************/
void decrease()
{
        if(ID==1)
        {
                if(max<min+10)               
                {
                max--;
                }
                else
                {
                        max=min+10;
                }
        }
        if(ID==2)
        {
                min--;
                if(min<=0)                                //下限设定不得低于0,若低于就默认为0
                {
                        min=0;
                }
        }       
}
/****************************************************************
函数名:display()
描述:数码管温度显示子程序,PO口输出,P2.4、P2.5分别为段选、位选口
                  采用共阴极4-LED动态扫描显示。显示段为0.0℃~125.0℃。
******************************************************************/
void display(uchar ba,uchar sh,uchar ge,uchar aa)
{
        wela1 = wela2 = wela3 = wela4 = 1;  
       
          P0 = clear;
      P0 = table[ba];
          wela1 = 0;  
          delayms(5);
          wela1 = 1;
          
        P0 = clear;
        P0 = table[sh];
        wela2 = 0;
        delayms(5);
        wela2 = 1;

        P0 = clear;
        P0 = table[ge];   
    wela3 = 0;     
        delayms(5);  
        wela3 = 1;

        P0 = clear;
        P0 = table[aa];   
    wela4 =0;     
    delayms(5);
        wela4 =1;

       
}



/****************************************************************
函数名:display1(int T)
描述:上下限报警温度设定显示子程序,显示范围0℃~70℃,均为整数,不显           示小数部分,这个范围可由作者自定设置, ******************************************************************/
void display1(int T)
{       
          wela1 = wela2 = wela3 = wela4 = 1;  

         P0 = clear;
        P0 = table[11];   
    wela1 =0;     
    delayms(1);
        P0 = clear;
        wela1 =1;
         P0=0xfe;
         wela1 =0;
          delayms(2);


       
         P0 = clear;
        P0 = table[T/10];   
    wela2 =0;     
    delayms(1);
        P0 = clear;
        wela2 =1;
         P0=0xfd;
         wela2 =0;
          delayms(2);

        /*dula=1;                                //段选打开,让十位要显示字符的代码传到所有位中
        P0=table[T/10];                        
        //dula=0;
        delayms(1);
        P0=0xff;
        //wela=1;                                        //位选打开,选择第二个数码管,即十位显示
        P0=0xfd;
        //wela=0;

        delayms(2);        */

          P0 = clear;
        P0 = table[T%10];   
    wela3 =0;     
    delayms(1);
        P0 = clear;
        wela3 =1;
         P0=0xfb;
         wela3 =0;
          delayms(2);

        /*/dula=1;                                        //段选打开,让个位要显示字符的代码传到所有位中
        P0=table1[T%10];
        //dula=0;
        delayms(1) ;
        P0=0xff;
        //wela=1;                                        //位选打开,选择第三个数码管,即个位显示
        P0=0xfb;
        //wela=0;
        delayms(2);        */

         P0 = clear;
        P0 = table[1];   
    wela4 =0;     
    delayms(1);
        P0 = clear;
        wela4 =1;
         P0=0xf7;
         wela4 =0;
          delayms(2);
       
    /*/dula=1;                                //段选打开,让小数位要显示字符的代码传到所有位中
        P0=table[1];                                //小数位一直显示0
        //dula=0;
        delayms(1);
        P0=0xff;
        //wela=1;                                        //位选打开,选择第四个数码管,即小数位显示
        P0=0xf7;
        //wela=0;

        delayms(2);        */

}
/****************************************************************
函数名:main()
描述: 主函数 ******************************************************************/
void main(void)
{
        max=40;             //上下限初始化
        min=20;
        ID=0;
        keycon=0;                       
        rom();         //调用读序列号子程序
        while(1)
                {        
key();        //判断是否上下限温度报警设置键是否有按下。有就进入温度设置程序
                        key_select();                //DS18B20选择按键,在三个测温点切换
                        change_start();                //所有器件开始温度度转换
                        delayms(5);      //延时,如果是不断的读取的话可以不延时
readtemp();        //读取程序,执行完毕温度进入报警程序
                        alarm();                                //进行检测是否越限程序,
                        ba=t/100;                               
                        sh=t%100/10;
                        ge=t%10;
                        aa=xs%10;       
                        if(ID==0)                                //没有任何设定按键按下,显示温度
                        {
display(ba,sh,ge,aa);
}
                }
}
求高手指导

相关帖子

沙发
叶伤| | 2013-5-2 23:38 | 只看该作者
uint temp1,T,t,xs,ID,keycon,max,min;

………………把T删掉,重复定义。

使用特权

评论回复
板凳
liub_2014| | 2013-5-3 00:11 | 只看该作者
看不懂

使用特权

评论回复
地板
dfgdfgfdg| | 2013-5-3 00:33 | 只看该作者
斯蒂芬森的

使用特权

评论回复
5
ayb_ice| | 2013-5-3 07:54 | 只看该作者
这样的程序加上中断就死悄悄

使用特权

评论回复
6
原野之狼| | 2013-5-3 09:12 | 只看该作者
提示信息写的很清楚了:
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
    SYMBOL: T

使用特权

评论回复
7
bstele| | 2014-4-22 11:10 | 只看该作者
楼主弄好了吗?

使用特权

评论回复
8
ayb_ice| | 2014-4-23 10:18 | 只看该作者
nngogogo 发表于 2014-4-23 10:07
WHY
?

关键时序是不能被打断的

使用特权

评论回复
9
ayb_ice| | 2014-4-23 10:18 | 只看该作者
nngogogo 发表于 2014-4-23 10:07
WHY
?

关键时序是不能被打断的

使用特权

评论回复
10
畅想天子| | 2014-12-12 10:21 | 只看该作者
T与t属于重复定义,大小写都属于一个字符,把T换成别的字母,绝对正确。
但你的程序试过了,运行可能不好

使用特权

评论回复
11
h41845224| | 2016-2-1 11:28 | 只看该作者
读取序列号应该是0x55

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

4

帖子

0

粉丝