主函数
#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,然后取出原码 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
气死,找这个bug找了半天!