找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2713|回复: 6
打印 上一主题 下一主题
收起左侧

为什么我的ds18b20不显示,请大佬们解答

[复制链接]
跳转到指定楼层
楼主

#include <reg52.h>                 //调用单片机头文件
#include <intrins.h>
#define uchar unsigned char  //无符号字符型 宏定义        变量范围0~255
#define uint  unsigned int         //无符号整型 宏定义        变量范围0~65535

sbit clk = P1^3;          //ds1302时钟线定义
sbit io =  P1^4;          //数据线
sbit rst = P1^5;          //复位线
sbit DQ= P1^7;          //温度线                                                           //秒  分   时   日   月  年   星期         
uchar code write_add[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a};   //写地址
uchar code read_add[] ={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b};   //读地址
uchar code init_ds[]  ={0x55,0x17,0x15,0x01,0x01,0x13,0x13};   
uchar miao,fen,shi,ri,yue,week,nian;
uchar i;

uchar count = 0,count1 = 0,speed = 0,quan = 0;//中断次数计算,速度
unsigned long speed1,juli,time2;
float f_hz,speed_km,speed_m;

uchar flag_lc = 0;   //开始计算速度使能

uint juli_s;             //每秒走的距离

float zhijing = 1;  //直径 0.55M
uint s_zhijing = 100;


uchar menu_1;        //菜单设置变量
uchar menu_2;        //菜单设置变量



uchar flag_200ms;
uint shudu;   //定义速度的变量
uint bj_shudu = 70;         //报警速度


//这三个引脚参考资料
sbit rs=P1^0;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
sbit rw=P1^1;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
sbit e =P1^2;         //片选信号   下降沿触发

uchar code table_num[]="0123456789abcdefg";
uchar i;

sbit beep = P3^7;   //蜂鸣器IO口定义



/******************1ms 延时函数*******************/
void delay_1ms(uint q)
{
        uint i,j;
        for(i=0;i<q;i++)
                for(j=0;j<120;j++);
}

/********************************************************************
* 名称 : delay_uint()
* 功能 : 小延时。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
        while(q--);
}

/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
        i =0;
        e=0;
        rs=0;
        rw=0;
        P0=com;
        delay_uint(3);
        e=1;
        delay_uint(25);
        e=0;
}

/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
        i =0;
        e=0;
        rs=1;
        rw=0;
        P0=dat;
        delay_uint(3);
        e=1;
        delay_uint(25);
        e=0;        
}

/********************************************************************
* 名称 : write_sfm2(uchar hang,uchar add,uchar date)
* 功能 : 显示2位十进制数,如果要让第一行,第五个字符开始显示"23" ,调用该函数如下
                  write_sfm1(1,5,23)
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_sfm2(uchar hang,uchar add,uint date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(0x30+date/10%10);
        write_data(0x30+date%10);        
}

/********************************************************************
* 名称 : write_sfm4(uchar hang,uchar add,uchar date)
* 功能 : 显示2位十进制数,如果要让第一行,第五个字符开始显示"23" ,调用该函数如下
                  write_sfm1(1,5,23)
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_sfm4(uchar hang,uchar add,uint date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(0x30+date/10000%10);
        write_data(0x30+date/1000%10);
        write_data(0x30+date/100%10);        
        write_data(0x30+date/10%10);
        write_data(0x30+date%10);        
        write_data('k');        
        write_data('m');        
}

void write_sfm7(uchar hang,uchar add,uint date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(0x30+date/100000%10);
        write_data(0x30+date/100000%10);
        write_data(0x30+date/10000%10);
        write_data(0x30+date/1000%10);
        write_data('.');        
        write_data(0x30+date/100%10);        
        write_data(0x30+date/10%10);
        write_data('k');        
        write_data('m');        
}

/***********************lcd1602上显示两位十进制数************************/
void write_sfm1(uchar hang,uchar add,uchar date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(0x30+date % 10);        
}


/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
                  write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
                while(1)
                {
                        if(*p == '\0')  break;
                        write_data(*p);
                        p++;
                }        
}


/***********************lcd1602上显示两位十进制数************************/
void write_sfm2_ds1302(uchar hang,uchar add,uchar date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(table_num[date / 16]);
        write_data(table_num[date % 16]);        
}

/***********************lcd1602上显示两位十进制数************************/
void write_sfm3_ds18b20(uchar hang,uchar add,uchar date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(table_num[date / 16]);
        write_data(table_num[date % 16]);        
}

/*****************控制光标函数********************/
void write_guanbiao(uchar hang,uchar add,uchar date)
{               
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        if(date == 1)        
                write_com(0x0c);   //关闭光标
}         

/********************************************************************
* 名称 : init_1602()
* 功能 : 初始化1602液晶
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_1602()      //1602初始化
{
        write_com(0x38);
        write_com(0x0c);
        write_com(0x06);
        delay_uint(1000);
        write_string(1,0,"sd:00km/h  00:00:00  ");               
        write_string(2,0," 00 ");        
}


/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
        uchar i;
        for(i=0;i<8;i++)
        {                                         //写数据是低位开始
                DQ = 0;                         //把总线拿低写时间隙开始
                DQ = dat & 0x01; //向18b20总线写数据了
                delay_uint(5);         // 60us
                DQ = 1;                         //释放总线
                dat >>= 1;
        }        
}

/*************读取18b20内的数据***************/
uchar read_18b20()
{
        uchar i,value;
        for(i=0;i<8;i++)
        {
                DQ = 0;                         //把总线拿低读时间隙开始
                value >>= 1;         //读数据是低位开始
                DQ = 1;                         //释放总线
                if(DQ == 1)                 //开始读写数据
                        value |= 0x80;
                delay_uint(5);         //60us        读一个时间隙最少要保持60us的时间
        }
        return value;                 //返回数据
}

/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
        uint value;
        uchar low;                           //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
        write_18b20(0xcc);           //跳过64位ROM
        write_18b20(0x44);           //启动一次温度转换命令
        delay_uint(50);                   //500us


        write_18b20(0xcc);           //跳过64位ROM
        write_18b20(0xbe);           //发出读取暂存器命令

        EA = 0;
        low = read_18b20();           //读温度低字节
        value = read_18b20();  //读温度高字节
        EA = 1;
        value <<= 8;                   //把温度的高位左移8位
        value |= low;                   //把读出的温度低位放到value的低八位中
        value *= 0.625;               //转换到温度值 小数
        return value;                   //返回读出的温度 带小数
}
/*************写一个数据到对应的地址里***************/
void write_ds1302(uchar add,uchar dat)
{               
        rst = 1;                         //把复位线拿高
        for(i=0;i<8;i++)
        {                                     //低位在前
                clk = 0;                 //时钟线拿低开始写数据
                io = add & 0x01;            
                add >>= 1;                 //把地址右移一位
                clk = 1;                 //时钟线拿高
        }        
        for(i=0;i<8;i++)
        {
                clk = 0;                 //时钟线拿低开始写数据
                io = dat & 0x01;
                dat >>= 1;                 //把数据右移一位
                clk = 1;                 //时钟线拿高
        }
        rst = 0;                         //复位线合低
        clk = 0;
        io = 0;
}

/*************从对应的地址读一个数据出来***************/
uchar read_ds1302(uchar add)
{
        uchar value,i;
        rst = 1;                         //把复位线拿高
        for(i=0;i<8;i++)
        {                                     //低位在前
                clk = 0;                 //时钟线拿低开始写数据
                io = add & 0x01;            
                add >>= 1;                 //把地址右移一位
                clk = 1;                 //时钟线拿高
        }               
        for(i=0;i<8;i++)
        {
                clk = 0;                 //时钟线拿低开始读数据
                value >>= 1;
                if(io == 1)
                        value |= 0x80;
                clk = 1;                 //时钟线拿高
        }
        rst = 0;                         //复位线合低
        clk = 0;
        io = 0;
        return value;                 //返回读出来的数据
}



/*************把要的时间 年月日 都读出来***************/
void read_time()
{
        miao = read_ds1302(read_add[0]);        //读秒
        fen  = read_ds1302(read_add[1]);        //读分
        shi  = read_ds1302(read_add[2]);        //读时
        ri   = read_ds1302(read_add[3]);        //读日
        yue  = read_ds1302(read_add[4]);        //读月
        nian = read_ds1302(read_add[5]);        //读年
        week = read_ds1302(read_add[6]);        //读星期
}

/*************把要写的时间 年月日 都写入ds1302里***************/
void write_time()
{
        write_ds1302(0x8e,0x00);                        //打开写保护
        write_ds1302(write_add[0],miao);        //写秒
        write_ds1302(write_add[1],fen);                //写分
        write_ds1302(write_add[2],shi);                //写时
        write_ds1302(write_add[3],ri);                //写日
        write_ds1302(write_add[4],yue);                //写月
        write_ds1302(write_add[5],nian);        //写年
        write_ds1302(write_add[6],week);        //写星期
        write_ds1302(0x8e,0x80);                        //关闭写保护
}

/*************定时器0初始化程序***************/
void init_1602_ds1302()
{
        write_sfm2_ds1302(1,11,shi);        
        write_sfm2_ds1302(1,14,fen);
        write_sfm2_ds1302(1,17,miao);        
        
}

/***********外部中断0初始化程序****************/
void init_int0()
{
        EX0=1;                          //允许外部中断0中断
        EA=1;                           //开总中断
        IT0 = 1;                   //外部中断0负跳变中断
}


/*************定时器0初始化程序***************/
void time_init()          //定时器0初始化程序
{
        EA   = 1;                   //开总中断
        TMOD=0x11;
  ET0=1;
  TR0=1;
  TH0=(65536-50000)/256;
  TL0=(65536-50000)%256;
}

/********************独立按键程序*****************/
uchar key_can;         //按键值

void key()         //独立按键程序
{
        static uchar key_new;
        key_can = 20;                   //按键值还原
        P3 |= 0x78;                     //对应的按键IO口输出为1
        if((P3 & 0x78) != 0x78)                //按键按下
        {
                delay_1ms(1);                     //按键消抖动
                if(((P3 & 0x78) != 0x78) && (key_new == 1))
                {                                                //确认是按键按下
                        key_new = 0;
                        switch(P3 & 0x78)
                        {
                                case 0x70:  key_can = 4;  break;         //得到按键值
                                case 0x68:  key_can = 3;  break;         //得到按键值
                                case 0x58:  key_can = 2;  break;         //得到按键值
                                case 0x38:  key_can = 1;  break;         //得到按键值
                        }
                }                        
        }
        else
                key_new = 1;        
}


/**********************设置函数************************/
void key_with()
{
        if(key_can == 1)        //设置键
        {
                menu_1++;
                if(menu_1 == 1)          //设置时间
                {
                        menu_2 = 1;
                        write_string(1,0,"   W:  ");                        
                        write_string(2,0," 20  -  -       ");        
                }
                if(menu_1 == 2)          //设置报警速度
                {
                        menu_2 = 1;
                        write_string(1,0,"set-sd:00km/h   ");                        
                        write_string(2,0,"zlc:             ");        
                }
                if(menu_1 == 3)          //设置直径
                {
                        menu_2 = 1;
                        write_string(1,0,"  wen du  ");                        
                        write_string(2,0,"               ");        
                }
                menu_2 = 1;

                if(menu_1 > 2)    //回到正常显示
                {
                        menu_1 = 0;
                        write_guanbiao(1,2,0);          //关闭光标
                        init_1602();      //1602初始化     //初始化液晶显示               
                }
        }
        if(key_can == 2)        //选择键
        {
                if(menu_1 == 1)                  //设置时间
                {
                        menu_2 ++;
                        if(menu_2 > 7)
                                menu_2 = 1;
                }
                if(menu_1 == 2)                 //设置
                {
                        menu_2 ++;
                        if(menu_2 > 2)
                                menu_2 = 1;                                
                }

        }
        if(menu_1 == 1)
        {
                if(menu_2 == 1)                  //设置时
                {
                        if(key_can == 3)        //加
                        {
                                shi+=0x01;
                                if((shi & 0x0f) >= 0x0a)
                                        shi = (shi & 0xf0) + 0x10;
                                if(shi >= 0x24)
                                        shi = 0;
                        }               
                        if(key_can == 4)        //减
                        {
                                if(shi == 0x00)
                                        shi = 0x24;
                                if((shi & 0x0f) == 0x00)
                                        shi = (shi | 0x0a) - 0x10;
                                shi -- ;
                        }                                          
                }
                if(menu_2 == 2)                  //设置分
                {
                        if(key_can == 3)        //加
                        {
                                fen+=0x01;
                                if((fen & 0x0f) >= 0x0a)
                                        fen = (fen & 0xf0) + 0x10;
                                if(fen >= 0x60)
                                        fen = 0;
                        }               
                        if(key_can == 4)        //减         
                        {
                                if(fen == 0x00)
                                        fen = 0x5a;
                                if((fen & 0x0f) == 0x00)
                                        fen = (fen | 0x0a) - 0x10;
                                fen -- ;
                        }        
                }
                if(menu_2 == 3)                  //设置秒
                {
                        if(key_can == 3)        //加
                        {
                                miao+=0x01;
                                if((miao & 0x0f) >= 0x0a)
                                        miao = (miao & 0xf0) + 0x10;
                                if(miao >= 0x60)
                                        miao = 0;
                        }        
                        if(key_can == 4)        //减         
                        {
                                if(miao == 0x00)
                                        miao = 0x5a;
                                if((miao & 0x0f) == 0x00)
                                        miao = (miao | 0x0a) - 0x10;
                                miao -- ;                        
                        }
                }
                if(menu_2 == 4)                  //设置星期
                {
                        if(key_can == 3)        //加
                        {
                            week+=0x01;
                                if((week & 0x0f) >= 0x0a)
                                        week = (week & 0xf0) + 0x10;
                                if(week >= 0x08)
                                        week = 1;
                        }               
                        if(key_can == 4)        //减         
                        {
                                if(week == 0x01)
                                        week = 0x08;
                                if((week & 0x0f) == 0x00)
                                        week = (week | 0x0a) - 0x10;
                                week -- ;
                        }        
                }
                if(menu_2 == 5)                  //设置年
                {
                        if(key_can == 3)        //加
                        {
                            nian+=0x01;
                                if((nian & 0x0f) >= 0x0a)
                                        nian = (nian & 0xf0) + 0x10;
                                if(nian >= 0x9a)
                                        nian = 1;
                        }               
                        if(key_can == 4)        //减         
                        {
                                if(nian == 0x01)
                                        nian = 0x9a;
                                if((nian & 0x0f) == 0x00)
                                        nian = (nian | 0x0a) - 0x10;
                                nian -- ;               
                        }        
                }
                if(menu_2 == 6)                  //设置月
                {
                        if(key_can == 3)        //加
                        {
                            yue+=0x01;
                                if((yue & 0x0f) >= 0x0a)
                                        yue = (yue & 0xf0) + 0x10;
                                if(yue >= 0x13)
                                        yue = 1;
                        }               
                        if(key_can == 4)        //减         
                        {
                                if(yue == 0x01)
                                        yue = 0x13;
                                if((yue & 0x0f) == 0x00)
                                        yue = (yue | 0x0a) - 0x10;
                                yue -- ;                                       
                        }        
                }
                if(menu_2 == 7)                  //设置日
                {
                        if(key_can == 3)        //加
                        {
                    ri+=0x01;
                        if((ri & 0x0f) >= 0x0a)
                                ri = (ri & 0xf0) + 0x10;
                        if(ri >= 0x32)
                                ri = 0;                        
                        }               
                        if(key_can == 4)        //减         
                        {
                                if(ri == 0x01)
                                        ri = 0x32;
                                if((ri & 0x0f) == 0x00)
                                        ri = (ri | 0x0a) - 0x10;
                                ri -- ;                        
                        }        
                }
                write_sfm2_ds1302(1,2,shi);           //显示时
                write_sfm2_ds1302(1,5,fen);           //显示分
                write_sfm2_ds1302(1,8,miao);           //显示秒
                write_sfm1(1,14,week);           //显示星期                                       
                write_sfm2_ds1302(2,3,nian);           //显示年
                write_sfm2_ds1302(2,6,yue);           //显示月
                write_sfm2_ds1302(2,9,ri);           //显示日
               
                switch(menu_2)           // 光标显示
                {
                        case 1:  write_guanbiao(1,2,1);  break;
                        case 2:  write_guanbiao(1,5,1);  break;
                        case 3:  write_guanbiao(1,8,1);  break;
                        case 4:  write_guanbiao(1,14,1); break;
                        case 5:  write_guanbiao(2,3,1);  break;
                        case 6:  write_guanbiao(2,6,1);  break;
                        case 7:  write_guanbiao(2,9,1);  break;
                }
                write_time();           //把时间写进去
        }        

        if(menu_1 == 2)
        {               
                if(menu_2 == 1)                  //设置速度
                {
                        if(key_can == 3)        //加
                        {
                                bj_shudu++;
                                if(bj_shudu >= 99)
                                        bj_shudu = 99;
                        }        
                        if(key_can == 4)        //减         
                        {
                                if(bj_shudu != 0)
                                        bj_shudu -- ;                        
                        }
                }        
        
                }        
                write_sfm2(1,7,bj_shudu);   //显示报警速度
               
               
                switch(menu_2)           // 光标显示
                {
                        case 1:  write_guanbiao(1,6,1);  break;
                        case 2:  write_guanbiao(2,3,1);  break;
                }
                }

/****************报警函数***************/
void clock_h_l()
{   
        if(shudu >= bj_shudu)
        {
                beep = ~ beep;           //蜂鸣器报警                        
        }
        else
        {
                beep = 1;        
        }                        
}

/******************主程序**********************/           
void main()
{
        init_1602();      //1602初始化
        init_int0();
        time_init();          //定时器0初始化程序
        while(1)
        {         
                key();                         //按键程序
                if(key_can < 10)
                {
                        key_with();        
                }
               
                read_time();                  //读时间
                init_1602_ds1302();   //显示时钟
               
                clock_h_l();        //报警函数
                write_sfm2(1,3,shudu);//显示速度,单位米每秒        
        }
}

/*********************外部中断0中断服务程序************************/
void int0() interrupt 0
{
        f_hz ++;
}

/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{        
        TH0 = (65536-50000)/256;
  TL0 = (65536-50000)%256;
        count ++;
        if(count == 20)//定时一秒
        {
                EX0 = 0;//关闭外部中断
                count = 0;//清空计数
                //1s = 1 / 1000000us;          // 1m/s=0.001km除以1/3600h=3.6km/h
                speed_m = (f_hz * zhijing * 3.14) / 2 ;        //算出来的是m/s
                speed_km = speed_m * 3.6 ;        //(带个小数点) km/s
                shudu = (uint)speed_km;
                        
        
                f_hz = 0;//圈数清零
                TH0 = 0x3c;//重新赋值
    TL0 = 0xb0;  
                EX0 = 1;//打开外部中断
        }
}

/*************定时器1中断服务程序***************/
void time1_int() interrupt 3
{
        TH0 = 0x3c;
        TL0 = 0xb0;     // 50ms
        count1++;
        if(count1  == 20)
        {
                count1 = 0;
                flag_lc=1;
                TH0 = 0x3c;
          TL0 = 0xb0;
        }
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:390416 发表于 2021-3-16 12:06 | 只看该作者
你的编程思路就有问题,第一步,应该先把显示部分做好,假设一个值 显示出来。只有显示正常了 再去研究后面,再去慢慢研究DS18B20。时序很关键,建议用分析仪和示波器调试。这个贴子 仅供参考
http://www.51hei.com/bbs/dpj-200968-1.html
回复

使用道具 举报

板凳
ID:96682 发表于 2021-3-17 07:40 来自手机 | 只看该作者
做实物这仿真图是有问题的,复位电路,温度探头,LCD,蜂鸣器
回复

使用道具 举报

地板
ID:824490 发表于 2021-3-17 11:05 | 只看该作者
调试新产品要有步骤与方法
比如你现在1820不显示,就要分别查:
1、显示其它内容(时间、日期)正常与否?
2、1820的底层驱动有没有问题?
3、线路是不是有问题?器件是不是错了?代码与实物有对应上了吗?
4、供电正常不?

你把整份代码发上来,除非人家有闲,或手上刚好有板,不然很少人会认真去读代码的,因为牵扯的地方太多了。。你先把问题定位好了,才可能有更精确的回答。不然就是你猜我猜大家猜。。
回复

使用道具 举报

5#
ID:213173 发表于 2021-3-17 17:07 | 只看该作者
名字不是重点 发表于 2021-3-17 11:05
调试新产品要有步骤与方法
比如你现在1820不显示,就要分别查:
1、显示其它内容(时间、日期)正常与否 ...

读取温度值的函数read_temp()没有被调用,怎么显示温度?
回复

使用道具 举报

6#
ID:893175 发表于 2021-3-17 18:22 | 只看该作者
时序很重要,液晶屏一般都是分时显示。
回复

使用道具 举报

7#
ID:917252 发表于 2021-5-26 10:09 | 只看该作者
ds18b20的负数部分是怎么处理的啊,可以说一下嘛
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表