找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1459|回复: 2
收起左侧

单片机程序功能:检测DS18B20并显示数码管上;求大神解答

[复制链接]
ID:323005 发表于 2019-3-5 00:37 | 显示全部楼层 |阅读模式
500黑币
程序功能:检车DS18B20并显示数码管上;晶振12hz

#include<STC8.h>
#include<intrins.h>
#define uchar unsigned char
#define uint  unsigned int
#define FOSC  12000000L
sbit w0=P1^0;
sbit w1=P1^1;
sbit w2=P1^2;
sbit w3=P1^3;
sbit w4=P1^4;
sbit w5=P1^5;
sbit w6=P1^6;
sbit w7=P1^7;
sbit w8=P5^4;
sbit w9=P5^5;
sbit s1=P2^1;
sbit s2=P2^2;
sbit s3=P2^3;
sbit s4=P2^4;
sbit s5=P2^0;
sbit l1=P4^0;
sbit l2=P4^1;
sbit l3=P4^2;//led
sbit l4=P4^3;//led
sbit l5=P4^4;
sbit  DQ=P2^5;//ds18b20
signed char m;         //温度全局变量
unsigned char tempL=0;  //全局变量
unsigned char tempH=0;
unsigned int sdata;  //车辆到的温度的整数部分
unsigned char xiaoshu1; //小数第一位
unsigned char xiaoshu2; //小数第二位
unsigned char xiaoshu;  //两位小数
bit  fg=1;              //温度正负标志
uchar code SM[]={
0x3f,0x06,0x5d,0x4f,
0x66,0x6b,0x7b,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void nb(uint z)   //??
{
uint x,y;
     x=z;
for(x;x>0;x--)
   for(y=110;y>0;y--);
}
void xs(uint tt)//显示函数
{
uint nn;
uchar ge , shi;
    nn=tt;
    ge=nn%10;
    shi=tt/10%10;
    w6=0;
    P3=SM[shi];
    nb(10);
    w6=1;
    w7=0;
    P3=SM[ge];
    nb(10);
    w7=1;
}
void delay(unsigned char i)
{
     while(i--);
   
}
void delay1ms(int n)
{
  unsigned int i;
  for(i=124*n;i>0;i--);  //延时124*8+10=1002us
}
/*****&sup3;初始化DS18B20*****/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ置高
delay(8); //稍延迟
DQ=0; //发送复位脉冲
delay(100); //延时(>480us)
DQ=1; //拉高数据线
delay(5); //等待(15~60us)
x=DQ; //用来判断DQ的值初始化有没有成功;存在x=0;否者x=1;
delay(20);
if(x==0)//成功led3亮
{
  l3=0;
}
if(x)//失败led4亮
{
  l4=0;
}//  问题led4常亮;感觉初始化失败求大神解答


}
/*****读一个字节*****/
ReadOneChar(void)  //住数据线先充高位拉低1us
{
unsigned char i=0; //每个走起最短持续时间60us,各个走起必须有1us以上的恢复;
unsigned char dat=0;
for (i=8;i>0;i--) //8位
{
  DQ=1;
  delay(1);
  DQ=0;
  dat>>=1;     //数据移位子
  DQ=1;
  if(DQ)
  dat|=0x80;     //得读取数据线得到一个状态
  delay(4);
} return(dat);
}
/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0; //数据线高拉低,产生写起始信号。15us之内将数据写的位数送到数据线上
for(i=8;i>0;i--) //
{
  DQ=0; //另一个写周期之前要有1us高电平
  DQ=dat&0x01;  //按低位发送数据
  delay(5);
  DQ=1;
  dat>>=1;
}
delay(4);
}
/*****读取温度*****/
void ReadTemperature(void)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过序列号
WriteOneChar(0x44); //启动温度转换
delay(125); //转换延时
Init_DS18B20();初始化
WriteOneChar(0xcc); //跳过读序号
WriteOneChar(0xbe); //读温度寄存器
tempL=ReadOneChar(); //温度高位
tempH=ReadOneChar(); //温度低位

if(tempH>0x7f)      //最高位为1温度为负
{
   tempL=~tempL;         //补码转换,取反加一
   tempH=~tempH+1;      
   fg=0;      //读取温度为负是fg=0
}
sdata = tempL/16+tempH*16;      //整数部分
xiaoshu1 = (tempL&0x0f)*10/16; //小数第一位
xiaoshu2 = (tempL&0x0f)*100/16%10;//小数第二位
xiaoshu=xiaoshu1*10+xiaoshu2; //小数两位
}
\
void main()
{   
unsigned int i;
while(1)
{
  ReadTemperature(); //读取温度
  for(i=0;i<20;i++)
  {
   xs(sdata);    //显示温度
  }
}
}


最佳答案

查看完整内容

stc8的单片机速度快,你的复位延时肯定短了,最好买个逻辑分析仪看一下,淘宝上20几块钱的就够了。
回复

使用道具 举报

ID:382826 发表于 2019-3-5 00:37 | 显示全部楼层
stc8的单片机速度快,你的复位延时肯定短了,最好买个逻辑分析仪看一下,淘宝上20几块钱的就够了。
回复

使用道具 举报

ID:164602 发表于 2019-3-5 08:01 | 显示全部楼层
STC8没用过,不知道程序中应该做哪些设置。不过STC89C52做过的,功能正常,程序给你参考
主程序:/*******************************************************************************
* 实验名                           :温度显示实验
* 使用的IO             :
* 实验效果       :数码管显示温度
*        注意                                         :
*******************************************************************************/

#include<reg51.h>
#include"temp.h"

//数码管IO
#define DIG        P0
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

unsigned char code DIG_CODE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char Num=0;
unsigned int disp[8]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};

void LcdDisplay(int);
void Timer0Configuration();

/*******************************************************************************
* 函数名         : main
* 函数功能                   : 主函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void main()
{
    Timer0Configuration();
        while(1)
        {
                LcdDisplay(Ds18b20ReadTemp());
        }
}

/*******************************************************************************
* 函数名         : LcdDisplay()
* 函数功能                   : LCD显示读取到的温度
* 输入           : v
* 输出                  : 无
*******************************************************************************/

void LcdDisplay(int temp)          //lcd显示
{

          unsigned char datas[] = {0, 0, 0, 0, 0}; //定义数组
        float tp;  
        if(temp< 0)                                //当温度值为负数
          {
        disp[2] = 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的就
                //算加上.5,还是在小数点后面。

          }
        else
          {       
        disp[2] = 0;               
                tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
                //如果温度是正的那么,那么正数的原码就是补码它本身
                temp=tp*0.0625*100+0.5;       
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算加上0.5,还是在小数点后面。
        }
    disp[0] = 0;
    disp[1] = 0;
    disp[3] = DIG_CODE[temp / 10000];
        disp[4] = DIG_CODE[temp % 10000 / 1000];
        disp[5] = DIG_CODE[temp % 1000 / 100] | 0x80;
        disp[6] = DIG_CODE[temp % 100 / 10];
        disp[7] = DIG_CODE[temp % 10];

}

/*******************************************************************************
* 函数名         : Timer0Configuration()
* 函数功能                   : 设置计时器
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void Timer0Configuration()
{
        TMOD=0X02;//选择为定时器模式,工作方式2,仅用TRX打开启动。

        TH0=0X9C;        //给定时器赋初值,定时100us
        TL0=0X9C;       
        ET0=1;//打开定时器0中断允许
        EA=1;//打开总中断
        TR0=1;//打开定时器               
}

/*******************************************************************************
* 函数名         : DigDisplay() interrupt 1
* 函数功能                   : 中断数码管显示
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void DigDisplay() interrupt 1
{
//定时器在工作方式二会自动重装初,所以不用在赋值。
//        TH0=0X9c;//给定时器赋初值,定时1ms
//        TL0=0X00;               
        DIG=0; //消隐
        switch(Num)         //位选,选择点亮的数码管,
        {
                case(7):
                        LSA=0;LSB=0;LSC=0; break;
                case(6):
                        LSA=1;LSB=0;LSC=0; break;
                case(5):
                        LSA=0;LSB=1;LSC=0; break;
                case(4):
                        LSA=1;LSB=1;LSC=0; break;
                case(3):
                        LSA=0;LSB=0;LSC=1; break;
                case(2):
                        LSA=1;LSB=0;LSC=1; break;
                case(1):
                        LSA=0;LSB=1;LSC=1; break;
                case(0):
                        LSA=1;LSB=1;LSC=1; break;       
        }
        DIG=disp[Num]; //段选,选择显示的数字。
        Num++;
        if(Num>7)
                Num=0;
}


18B20驱动程序temp.c:
#include"temp.h"
/*******************************************************************************
* 函数名         : Delay1ms
* 函数功能                   : 延时函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void Delay1ms(unsigned int y)
{
        unsigned int x;
        for(y;y>0;y--)
                for(x=110;x>0;x--);
}
/*******************************************************************************
* 函数名         : Ds18b20Init
* 函数功能                   : 初始化
* 输入           : 无
* 输出                  : 初始化成功返回1,失败返回0
*******************************************************************************/

unsigned char Ds18b20Init()
{
        unsigned int i;
    EA = 0;
        DSPORT=0;                         //将总线拉低480us~960us
        i=70;       
        while(i--);//延时642us
        DSPORT=1;                        //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
        i=0;
    EA = 1;
        while(DSPORT)        //等待DS18B20拉低总线
        {
                i++;
                if(i>5000)//等待>5MS
                        return 0;//初始化失败       
        }
        return 1;//初始化成功
}

/*******************************************************************************
* 函数名         : Ds18b20WriteByte
* 函数功能                   : 向18B20写入一个字节
* 输入           : com
* 输出                  : 无
*******************************************************************************/

void Ds18b20WriteByte(unsigned char dat)
{
        unsigned int i,j;
    EA = 0;
        for(j=0;j<8;j++)
        {
                DSPORT=0;                        //每写入一位数据之前先把总线拉低1us
                i++;
                DSPORT=dat&0x01; //然后写入一个数据,从最低位开始
                i=6;
                while(i--); //延时68us,持续时间最少60us
                DSPORT=1;        //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
                dat>>=1;
        }
    EA = 1;
}
/*******************************************************************************
* 函数名         : Ds18b20ReadByte
* 函数功能                   : 读取一个字节
* 输入           : com
* 输出                  : 无
*******************************************************************************/


unsigned char Ds18b20ReadByte()
{
        unsigned char byte,bi;
        unsigned int i,j;
    EA = 0;       
        for(j=8;j>0;j--)
        {
                DSPORT=0;//先将总线拉低1us
                i++;
                DSPORT=1;//然后释放总线
                i++;
                i++;//延时6us等待数据稳定
                bi=DSPORT;         //读取数据,从最低位开始读取
                /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
                byte=(byte>>1)|(bi<<7);                                                  
                i=4;                //读取完之后等待48us再接着读取下一个数
                while(i--);
        }
    EA = 1;                               
        return byte;
}
/*******************************************************************************
* 函数名         : Ds18b20ChangTemp
* 函数功能                   : 让18b20开始转换温度
* 输入           : com
* 输出                  : 无
*******************************************************************************/

void  Ds18b20ChangTemp()
{
        Ds18b20Init();
        Delay1ms(1);
        Ds18b20WriteByte(0xcc);                //跳过ROM操作命令                 
        Ds18b20WriteByte(0x44);            //温度转换命令
//        Delay1ms(100);        //等待转换成功,而如果你是一直刷着的话,就不用这个延时了

}
/*******************************************************************************
* 函数名         : Ds18b20ReadTempCom
* 函数功能                   : 发送读取温度命令
* 输入           : com
* 输出                  : 无
*******************************************************************************/

void  Ds18b20ReadTempCom()
{       

        Ds18b20Init();
        Delay1ms(1);
        Ds18b20WriteByte(0xcc);         //跳过ROM操作命令
        Ds18b20WriteByte(0xbe);         //发送读取温度命令
}
/*******************************************************************************
* 函数名         : Ds18b20ReadTemp
* 函数功能                   : 读取温度
* 输入           : com
* 输出                  : 无
*******************************************************************************/

int Ds18b20ReadTemp()
{
        int temp=0;
        unsigned char tmh,tml;
        Ds18b20ChangTemp();                                 //先写入转换命令
        Ds18b20ReadTempCom();                        //然后等待转换完后发送读取温度命令
        tml=Ds18b20ReadByte();                //读取温度值共16位,先读低字节
        tmh=Ds18b20ReadByte();                //再读高字节
        temp=tmh;
        temp<<=8;
        temp|=tml;
        return temp;
}

18B20头文件temp.h:

#ifndef __TEMP_H_
#define __TEMP_H_

#include<reg51.h>

sbit DSPORT=P3^7;

void Delay1ms(unsigned int );
unsigned char Ds18b20Init();
void Ds18b20WriteByte(unsigned char com);
unsigned char Ds18b20ReadByte();
void  Ds18b20ChangTemp();
void  Ds18b20ReadTempCom();
int Ds18b20ReadTemp();

#endif


对应的电路图:
1.jpg

1.jpg

1.jpg


回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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