打印

各位,我刚学单片机,在做ds18b20的数码管显示时

[复制链接]
1439|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1005961242|  楼主 | 2015-9-22 10:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
各位,我刚学单片机,在做ds18b20温度显示时,要么转换出来的温度不对,要么就显示不出来,主要还有就是数码管动态扫描显示出转换温度时,延时长的话就一个个显示出来,短的话就只显示最后一个数码管,而且上电时,要过10秒左右才显示出来转换结果,求教啊,都琢磨了好久

相关帖子

沙发
1005961242|  楼主 | 2015-9-22 10:34 | 只看该作者
怎么都没人看啊

使用特权

评论回复
板凳
hehailun| | 2015-9-22 10:49 | 只看该作者
数码管扫描用定时器控制 设置一个标志位 到一定时间就给与显示   单片机delay函数尽量不要用

使用特权

评论回复
地板
皈依| | 2015-9-22 11:31 | 只看该作者
楼上讲的对,扫描最好用定时器,可以和内部其他程序很好的配合

使用特权

评论回复
5
HARRY007| | 2015-9-22 13:19 | 只看该作者
从楼主的描述来看,首先数码管的显示原理是利用了人眼的视觉暂留来实现的,其实几个数码管还是分时点亮的,只是由于扫描的块,给人的感觉就是几个同时点亮了。你出现只显示最后一位,还是延时没有弄好。另外楼上几位说的也是很对的,要利用定时器来做这个时间上的延时,而不要让单片机停在某处不停的减减某个变量来做延时。也许你得开机10S反应慢就是延时拖的你跑不好代码。
利用定时器做延时的好处就是,1S内主程序可以循环N圈,你用减减delay来做也许只循环了N/1000圈,差距太大了……

使用特权

评论回复
6
HARRY007| | 2015-9-22 13:21 | 只看该作者
你也贴个代码给大伙看看,别人才能更好的帮你啊。

使用特权

评论回复
7
1005961242|  楼主 | 2015-9-24 10:22 | 只看该作者
HARRY007 发表于 2015-9-22 13:19
从楼主的描述来看,首先数码管的显示原理是利用了人眼的视觉暂留来实现的,其实几个数码管还是分时点亮的, ...

现在显示方面是通过定时器中断来扫描的。
显示程序是好的,温度驱动也是完美的。但是放一块就不能正常显示了。
百度了一下,说是中断和18B20的驱动有冲突。但是该怎么解决呢?.

使用特权

评论回复
8
1005961242|  楼主 | 2015-9-24 10:23 | 只看该作者
皈依 发表于 2015-9-22 11:31
楼上讲的对,扫描最好用定时器,可以和内部其他程序很好的配合

现在显示方面是通过定时器中断来扫描的。
显示程序是好的,温度驱动也是完美的。但是放一块就不能正常显示了。
百度了一下,说是中断和18B20的驱动有冲突。但是该怎么解决呢?.

使用特权

评论回复
9
1005961242|  楼主 | 2015-9-24 10:23 | 只看该作者
hehailun 发表于 2015-9-22 10:49
数码管扫描用定时器控制 设置一个标志位 到一定时间就给与显示   单片机delay函数尽量不要用 ...

现在显示方面是通过定时器中断来扫描的。
显示程序是好的,温度驱动也是完美的。但是放一块就不能正常显示了。
百度了一下,说是中断和18B20的驱动有冲突。但是该怎么解决呢?.

使用特权

评论回复
10
1005961242|  楼主 | 2015-9-24 10:24 | 只看该作者
HARRY007 发表于 2015-9-22 13:21
你也贴个代码给大伙看看,别人才能更好的帮你啊。

#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char       
sbit DQ=P1^3;
sbit dula=P2^2;
sbit wela=P2^3;
uchar DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uint ReadTempFlag;
uchar TempData[8];
/*******************************************
          uS延时函数,大致延时
          长度 T=uS
*******************************************/
void Delay800us()                //@11.0592MHz
{
        unsigned char i, j;

        _nop_();
        _nop_();
        _nop_();
        i = 9;
        j = 151;
        do
        {
                while (--j);
        } while (--i);
}

void Delay100us()                //@11.0592MHz
{
        unsigned char i, j;

        _nop_();
        _nop_();
        i = 2;
        j = 15;
        do
        {
                while (--j);
        } while (--i);
}

void Delay10us()                //@11.0592MHz
{
        unsigned char i;

        _nop_();
        i = 25;
        while (--i);
}
void Delay10ms()                //@11.0592MHz
{
        unsigned char i, j;

        i = 108;
        j = 145;
        do
        {
                while (--j);
        } while (--i);
}

/*******************************************
函数名称:Init_18B20
功    能:对DS18B20进行复位操作
参    数:无
返回值  :初始化状态标志:1--失败,0--成功
********************************************/
bit Init_DS18B20()
{
        bit Error;
        DQ=1;
        Delay10us();
        DQ=0;
        Delay800us();
        DQ=1;
        Delay100us();
        Error=DQ;
        Delay10us();
        Delay10us();
        Delay10us();
        Delay10us();
        Delay10us();
        return Error;
}

/*******************************************
函数名称:Write_18B20
功    能:向DS18B20写入一个字节的数据
参    数:wdata--写入的数据
返回值  :无
********************************************/
void Write_DS18B20(uchar Wdat)
{
        uint i;
        for(i=0;i<8;i++)
        {
                DQ=0;
                DQ=Wdat&0x01;
                Delay10us();
                Delay10us();
                //Delay10us();                                //        ????
                //Delay10us();
                //Delay10us();
                DQ=1;
                Wdat>>=1;       
        }  
}

/*******************************************
函数名称:Read_18B20
功    能:从DS18B20读取一个字节的数据
参    数:无
返回值  :读出的一个字节数据
********************************************/
uchar Read_DS18B20()
{
        uint i;
        uchar Rdat=0;
        for(i=0;i<8;i++)
        {       
                DQ=0;               
                Rdat>>=1;
                DQ=1;
                if(DQ) Rdat|=0x80;
                Delay10us();
                Delay10us();
                Delay10us();
                Delay10us();
                Delay10us();
        }
        return Rdat;
}
/*******************************************
函数名称:Skip
功    能:发送跳过读取产品ID号命令
参    数:无
返回值  :无
********************************************/
void Skip(void)
{
    Write_DS18B20(0xcc);
}
/*******************************************
函数名称:Convert
功    能:发送温度转换命令
参    数:无
返回值  :无
********************************************/
void Convert(void)
{
    Write_DS18B20(0x44);
}
/*******************************************
函数名称:Read_SP
功    能:发送读ScratchPad命令
参    数:无
返回值  :无
********************************************/
void Read_SP(void)
{
    Write_DS18B20(0xbe);
}
/*******************************************

                功能:控制DS18B20完成一次温度转换
                返回测量的温度数

********************************************/
uint DS18B20_Convert()
{
        uint TempL,TempH,Temp;
        Init_DS18B20();
        Skip();
        Convert();       
        Delay10ms();       
        Init_DS18B20();
        Skip();
        Read_SP();
        TempL=Read_DS18B20();
        TempH=Read_DS18B20();
        TempH<<=8;
        Temp=TempH+TempL;
        return Temp;
}
void main()
{
        uint Tt;
        float f_Tt;
        TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
        TH0=(65536-2000)/256;              //给定初值
        TL0=(65536-2000)%256;
        EA=1;            //总中断打开
        ET0=1;           //定时器中断打开
        TR0=1;           //定时器开关打开
        while(1)
        {
                if(ReadTempFlag==1)
                {
                    ReadTempFlag=0;
                        Tt=DS18B20_Convert();
                        if(Tt&0x8000)                           //为负数时
                        {
                                TempData[0]=0x40;
                                Tt=~Tt;
                                Tt+=1;       
                        }
                        else
                                TempData[0]=0;
               
                        /*TtH=Tt>>4;
                        TtL=Tt&0x0f;
                        //TtL=TtL*6/10;
               
                        if(TtH/100==0)
                            TempData[1]=0;
                    else
                                TempData[1]=DuanMa[TtH/100];

                        TempData[2]=DuanMa[(TtH%100)/10];           //十位
                        TempData[3]=DuanMa[(TtH%100)%10]|0x80;   //个位
               
                        TempData[4]=DuanMa[TtL/10];
                        TempData[5]=DuanMa[TtL%10];
                        TempData[6]=0x3f;;                                */
                       
                        f_Tt=Tt*0.0625;
                        f_Tt=f_Tt*100+0.5;
                        Tt=f_Tt;

                        TempData[1]=DuanMa[Tt/10000];                   //百位

                        TempData[2]=DuanMa[(Tt%10000)/1000];           //十位
                        TempData[3]=DuanMa[(Tt%1000)/100]|0x80;   //个位
               
                        TempData[4]=DuanMa[(Tt%100)/10];                   //十分位
                        TempData[5]=DuanMa[Tt%10];                                   //百分位
                        TempData[6]=0x3f;;               
                                          
               
                        TempData[7]=0x39;         //显示C符号
            }
               
        }
}

void Display(uchar Num)
{
      static uchar i=0;                                  //???           改成uchar i;也行
          
      wela=1;
          P0=WeiMa;
          wela=0;

      dula=1;
          P0=TempData;
          dula=0;
      
          i++;
      if(i==Num) i=0;
}
void Timer0_isr(void) interrupt 1
{
        uint  num;
        TH0=(65536-2000)/256;                  //重新赋值 2ms
        TL0=(65536-2000)%256;
        Display(8);       // 调用数码管扫描
        num++;
    if(num==300)        
    {
            num=0;
            ReadTempFlag=1; //读标志位置1
        }
}

使用特权

评论回复
11
1005961242|  楼主 | 2015-9-24 10:27 | 只看该作者
HARRY007 发表于 2015-9-22 13:21
你也贴个代码给大伙看看,别人才能更好的帮你啊。

麻烦你帮我看看,为什么那个写时序放总线60us会错呢,然后我改成20us就是对的,大于都是错的

使用特权

评论回复
12
1005961242|  楼主 | 2015-9-24 12:05 | 只看该作者
楼楼刚学,望大家指导,谢谢

使用特权

评论回复
13
HARRY007| | 2015-9-24 18:46 | 只看该作者
1005961242 发表于 2015-9-24 10:24
#include
#include
#define uint unsigned int

DS18B20在读写时序的时候有可能会被中断打断,打断以后再回到时序处读写就有可能会发生错误。所以你读写DS18B20之前可以先关中断,ok之后再开启中断。你可以参考一下。

使用特权

评论回复
评论
maychang 2015-9-24 22:49 回复TA
正确。 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

11

帖子

1

粉丝