主函数
温度传感器可记录温度-55~125摄氏度
#include"reg52.h"
#include"temp.h"//这个头文件要写上,否则会报错!!!
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA=P2^2;//数码管用74LS138译码器来控制,所以有了这些东西
sbit LSB=P2^3;
sbit LSC=P2^4;
char num=0;//有用。在后面解释
u8 DisplayData[8];//工具数组,接受num转换过来的16进制数,传递给smg段数组
//上面这个数组这个要写成比5大的数因为要显示6位数码管,然后拼写注意一下!
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管段选,从0~9
void delay(u16 i)
{
//粗延时函数
while(i--);
}
void datapros(int temp)//参数表别忘了!!!因为你主函数调用这个函数是要传进实参的!!
{
float tp;//定义温度浮点数。因为数据处理有小数点所以将温度赋给一个浮点型变量
if(temp<0)
{//如果从温度传感器里读取的温度是负数
DisplayData[0]=0x40;//就让数码管显示1个负号在前头
//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
//读取的温度经一顿转换后变为真正的10进制温度
}
else//如果从温度传感器里读取的温度是0或者正数
{
DisplayData[0]=0x00;//那就不用在数码管最前头显示一个负号了
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
DisplayData[1]=smgduan[temp/10000];//因为数码管我们只用右边的6位,而且我们让temp多×了100,所以这里/10000
//所以这里剥离temp的百位给DisplayData数组存着 数组下标为0的数字你已经占用了,这里必须为1开始
DisplayData[2]=smgduan[temp%10000/1000];//剥离temp的十位给DisplayData数组存着
DisplayData[3]=smgduan[temp%1000/100]|0x80; //注意这些数字要写对!
//剥离temp的个位给DisplayData数组存着,因为还要显示小数点,所以
//我们必须让数码管的dp位亮着,就0x80(因为dp位为数码管段选位的最高位)即可。
DisplayData[4] = smgduan[temp % 100 / 10];//剥离temp的小数点后一位给DisplayData数组存着
DisplayData[5] = smgduan[temp % 10];//剥离temp的小数点后二位给DisplayData数组存着
}
void DigDisplay()
{
u8 i;
for(i=0;i<6;i++)//这个要改成6,因为你要显示6位数码管!!!!!!!
{
switch(i)//位选,选择点亮的数码管
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
}
P0=DisplayData[5-i];//发送disp数组里存着的num剥离出的位给P0管,注意,这里是5-i,因为
//数码管第0位是在最右侧,第7位在最左侧,所以遵循”千百十个小数点后1小数点后2“这样的从左至右顺序来让
//数码管显示数字
delay(100);//间隔1us扫描一次
P0=0x00;//数码管消隐
//从P0=DisplayData....到P0=0x00;这里,写在for循环里switch外!!!!记下
}
}
int main()
{
while(1)
{
datapros(DS18b20ReadTemp());//数据处理函数,实参是读取温度传感器里的温度
//调用datapros()函数的实参这个位置的函数读取温度值读取完毕,返回温度给datapro()
DigDisplay();//数码管显示函数
}
}
temp.c文件
#include"temp.h"
//#include "reg52.h"
void Delay1ms(uint y)
{
uint x;
for(;y>0;y--)
{
for(x=110;x>0;x--);
}
}
//较为精确的延时1ms的函数
//下面为温度传感器初始化函数
uchar Ds18b20Init()
{//代码模拟温度传感器的初始化时序
uchar i;
DSPORT=0;//将总线(数据线)拉低480us~960us
i=70;//为了延时642us,通过下面的while(i--);
while(i--);
DSPORT=1;//然后拉高总线,如果DS18B20温度传感器做出反应将会在15us~60us后将总线拉低
i=0;//下面还用到这个i
while(DSPORT)//等待DS18B20温度传感器自己拉低总线电位
//如果温度传感器存在,证明可以自己拉低总线电位,则直接跳过while循环
//返回一个1即可,证明温度传感器存在。否则就在while循环里返回一个0,证明不存在。
{
Delay1ms(1);//实参设置为1,就延时1个ms
i++;
if(i>5)//等待5ms(自定义愿意等待多少多长时间判定为超时),若5ms后温度传感器还没有作出反应,则初始化失败,证明
//温度传感器不存在或者坏了。
{
return 0;//初始化失败
}
}
return 1;//初始化成功,注意return1的位置!!别写while循环里!!
}//漏了个},注意
void Ds18b20WriteByte(uchar dat)
{//向温度传感器写入一个字节的数据的函数
//代码模拟温度传感器写入时序
uint i=0,j; //i=0是习惯,不初始化i也行
for(j=0;j<8;j++)
{
DSPORT=0;//每写入一位数据之前,先把总线拉低1us(时序就是这样的)
i++;
//注意DSPORT的拼写!!!!
DSPORT=dat&0x01;//然后写入一个数据,从最低位开始。只能一个一个位写入
//温度传感器。所以你必须先让dat的其他位为0,然后根据循环8次让位一个一个写入
i=6;//因为下面要用到i,你必须设定i
while(i--);//延时68us,时序图上写着延时最少60us
DSPORT=1;//然后释放(恢复)总线(拉高总线)。至少给总线1us的时间让总线拉高
//才能接着写入第二个数值(执行一行代码就是1us,所以不必再写个延时代码huo
//函数
dat>>=1;//因为这一位写完了,你要写dat的下一位数据给温度传感器(dat传进
//来的时候是8位),你就要给dat移位,把写完的这位给移走(写入位是从低位到
//高位写(规定))
}
}
uchar Ds18b20ReadByte()
{
//读取温度传感器的一个字节的函数
uchar byte,bi;//下面解释定义两个无符号字符型的目的
uint i,j;
for(j=8;j>0;j--)//这个循环和写入函数那个循环含义一致
//也是一位一位读(加起来相当于读了一个字节),从低位到高位读
{
DSPORT=0;//先将总线拉低1us(时序图规定)
i++;//执行一行代码就是1us
DSPORT=1;//然后释放(恢复)总线(时序图规定)
i++;
i++;//大约延时6us等待数据稳定
bi=DSPORT;//读取数据,从最低位开始读取。(根据时序图事实,此时DSPORT可能是0或者1)
byte=(byte>>1)|(bi<<7);
//先将byte右移一位,然后和左移7位后的bi或运算,移动byte后高位补0
//举个例子,如果byte读取的是0000 0000,然后移位是0000 0000,然后bi是1,左移七位
//就变成了1000 0000,然后这俩相或,存储在byte中,就变成了1000 0000
//然后再循环下来,bi=1,byte先右移1位让之前存储在byte的字节给移开把位置
//让给现在读取的位。然后bi又左移7位,然后再相或,byte就变成了1100 0000,
//如此循环,读取的位顺着byte>>1就往低位走了,符合从最低位开始读取的规则。
i=4;//读取完之后等待58us(下面的while循环可以实现)再接着读取下一个数
while(i--);
}
return byte;//读取完毕,返回读取的一个字节
}
void Ds18b20ChangeTemp()
{//温度传感器数据转温度函数,让温度传感器开始转换温度
Ds18b20Init();//初始化温度传感器
Delay1ms(1);//根据需要延时1ms
Ds18b20WriteByte(0xcc);//根据需要,跳过ROM操作命令
Ds18b20WriteByte(0x44);//发送一个温度转换命令给温度传感器
//Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}
void Ds18b20ReadTempCom()//函数名拼写问题。。。。所以会有警告,给老子注意!!!!!!!!!
{//发送读取温度传感器里的温度的命令
Ds18b20Init();//初始化温度传感器
Delay1ms(1); //根据需要延时1ms
Ds18b20WriteByte(0xcc);//根据需要,跳过ROM操作命令
Ds18b20WriteByte(0xbe);//发送读取温度传感器里的温度的命令
}
int DS18b20ReadTemp()
{//读取温度传感器里的温度。注意这些函数的功能!!!!
int temp=0;
uchar tmh,tml;//规定,只能这么分开存温度值,而且要接受读取温度传感器里的温度数据
Ds18b20ChangeTemp();//先发送让温度传感器数据转成温度的命令
//注意函数的拼写和变量的拼写!!!
Ds18b20ReadTempCom();//等待数据转换成温度后发送读取温度传感器里温度的命令
tml=Ds18b20ReadByte();//读取16位温度值,先读取温度的低8位给tml
tmh=Ds18b20ReadByte();//再读取高8位给tmh
temp=tmh;
temp<<=8;//先让返回的温度值(真正的温度)接收高8位的温度二进制值
//然后给把这高8位左移8位变成真正的高8位,以提供位置接收温度二进制值低8位
temp|=tml;//或一下就可以了,很方便省事。也能保证高8位的安全,高8位数据不被篡改
return temp;//读取温度值读取完毕,返回温度给主函数调用的地方。
}
temp.h文件
#ifndef _temp_H_
#define _temp_H_
#include"reg52.h"//这个别丢,很重要
#ifndef uchar //这少了c
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//两个重定义,ifndef 如果没有则定义的意思,然后下面就define,define完了别忘了endif
//来终止if(或说define),这个格式务必记好!!!
sbit DSPORT=P3^7;//定义温度传感器使用的IO口,这里DSPORT是温传器的名字
void Delay1ms(uint );
uchar Ds18b20Init();//温度传感器初始化函数
void Ds18b20WriteByte(uchar com);//写入温度传感器的数据函数
uchar Ds18b20ReadByte();//读取温度传感器里的一字节的数据函数
void Ds18b20ChangeTemp();//变换温度传感器数据的函数
void Ds18b20ReadTempCom();//发送读取温度传感器里的温度的命令
int DS18b20ReadTemp();//读取温度传感器里温度的数据函数
//这里定义为int是方便主函数的调用。
//以上声明全局函数
#endif
注意函数名的拼写,这里函数名又臭又长。
如果函数名在头文件、头文件附属c文件、主函数c文件不一致,则会报错:
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?DS18B20READTEMCOM?TEMP
*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
SYMBOL: DS18B20READTEMPCOM
MODULE: temp.obj (TEMP)
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
SYMBOL: DS18B20READTEMPCOM
MODULE: temp.obj (TEMP)
ADDRESS: 05F1H
翻译:
***警告L16:未调用段,忽略覆盖过程段:公关? DS18B20TEMPCOM ? TEMP
***警告L1:外部符号未解析
象征:DS18B20READTEMPCOM
模块:temp.obj(临时)
***警告L2:引用外部未解析
象征:DS18B20READTEMPCOM
模块:temp.obj(临时)
地址:05 f1h
这是头文件附属c文件和头文件两个文件的某个函数名没对应一致所产生的警告
气死,找这个bug找了半天!
转载:https://blog.csdn.net/weixin_45910408/article/details/105870763
查看评论