找回密码
 立即注册

QQ登录

只需一步,快速开始

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

谁能帮忙看看这个18B20 温度数值无反应

[复制链接]
ID:125710 发表于 2016-7-4 15:06 | 显示全部楼层 |阅读模式
PIC18F25J10  4M晶振。 不知道哪里程序出错了,数码管一直初始化,预计应该是18B20失败了 大神帮忙看看程序可否谢谢

#include "p18cxxx.h"              //头文件
#include "delays.h"
#include "SEG.h"
//#define  nop  asm("nop")
#define uchar unsigned char
#define uint unsigned int
#define  uch unsigned char                     //给unsigned char起别名 uch
#define DQ LATCbits.LATC2                     //定义18B20数据端口
#define DQ_LOW() DQ = 0; DQ_DIR = 0           //设置数据口为输出
unsigned char  TLV=0 ;                        //采集到的温度高8位
unsigned char  THV=0;                         //采集到的温度低8位
unsigned char TZ=0;                           //转换后的温度值整数部分
unsigned char TX=0;                           //转换后的温度值小数部分
unsigned int wd;                              //转换后的温度值BCD码形式
unsigned char shi;                             //整数十位
unsigned char ge;                              //整数个位
unsigned char shifen;                          //十分位
unsigned char baifen;                          //百分位
unsigned char qianfen;                         //千分位
unsigned char wanfen;                          //万分位
#define TMR0HLOAD     0xf6        //4MHZ  2.5mS
#define TMR0LLOAD     0x4D
unsigned char TickClock = 0;      //系统时基
#define SCLK   LATBbits.LATB0     //74HC164时钟
#define SDAT   LATBbits.LATB1     //74HC164数据
const unsigned char SegCode[] =   //图型表
{
    Bmp0Map,Bmp1Map,Bmp2Map,Bmp3Map,Bmp4Map,Bmp5Map,
    Bmp6Map,Bmp7Map,Bmp8Map,Bmp9Map,BmpAMap,BmpBMap,
    BmpCMap,BmpDMap,BmpEMap,BmpFMap
};
const unsigned char SegCS[6] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};              //显示片选
unsigned char SegBuf[6] = {BmpPMap,Bmp1Map,BmpCMap,Bmp1Map,Bmp8Map,BmpFMap}; //显示缓冲
unsigned uint temper;
uchar a1,a2,a3,a4;
void disp();
//延时函数
void delay(char x,char y)
{
   char z;
   do{
       z=y;
       do{;}while(--z);
      }while(--x);
}
//其指令时间为:7+(3*(Y-1)+7)*(X-1)如果再加上函数调用的call 指令、页面设定、传递参数花掉的7 个指令。
//则是:14+(3*(Y-1)+7)*(X-1)。
//--------------------------------------------------
//------------------------------------------------------------------------------
//复位DS18B20函数
reset(void)
{
   char presence=1;
   while(presence)
   {
     DQ=0 ;                                //主机拉至低电平
    delay(2,70);                              //延时503us
     DQ=1;                                //释放总线等电阻拉高总线,并保持15~60us
     delay(2,8);                               //延时70us
     if(DQ==1) presence=1;                     //没有接收到应答信号,继续复位
    else presence=0;                          //接收到应答信号
    delay(2,60);                              //延时430us
    }
   }
//-----------------------------------------------
//写18b20写字节函数
void write_byte(uch val)
{
uch i;
uch temp;
for(i=8;i>0;i--)
{
    temp=val&0x01;                            //最低位移出
   DQ=0;
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();                                    //从高拉至低电平,产生写时间隙
   if(temp==1)  DQ=1;                   //如果写1,拉高电平
   delay(2,7);                               //延时63us
    DQ=1;
    Nop();
    Nop();
    val=val>>1;                               //右移一位
  }
}
//------------------------------------------------
//18b20读字节函数
uch read_byte(void)
{
uch i;
uch value=0;                                //读出温度
static j;
for(i=8;i>0;i--)
{
    value>>=1;
    DQ=0;
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();                                   //6us
    DQ=0;                               //拉至高电平
    Nop();
    Nop();
    Nop();  
    Nop();
    Nop();                                 //4us
    j=DQ;
    if(j) value|=0x80;
    delay(2,7);                             //63us
   }
   return(value);
}
//-------------------------------------------------
//启动温度转换函数
void get_temp()
{
int i;
DQ=1;
reset();                                 //复位等待从机应答
write_byte(0XCC);                        //忽略ROM匹配
write_byte(0X44);                        //发送温度转化命令  
for(i=20;i>0;i--)
     {
         
         disp();                       //调用多次显示函数,确保温度转换完成所需要的时间
    }
reset();                                 //再次复位,等待从机应答
write_byte(0XCC);                        //忽略ROM匹配
write_byte(0XBE);                        //发送读温度命令
TLV=read_byte();                         //读出温度低8
THV=read_byte();                         //读出温度高8位
DQ=1;                               //释放总线
TZ=(TLV>>4)|(THV<<4)&0X3f;               //温度整数部分
TX=TLV<<4;                               //温度小数部分
if(TZ>100) TZ/100;                       //不显示百位
ge=TZ%10;//个位                          //整数部分个位
shi=TZ/10;//十位                         //整数十位
wd=0;  
if (TX & 0x80) wd=wd+5000;
if (TX & 0x40) wd=wd+2500;
if (TX & 0x20) wd=wd+1250;
if (TX & 0x10) wd=wd+625;                //以上4条指令把小数部分转换为BCD码形式            
shifen=wd/1000;                          //十分位                    
baifen=(wd%1000)/100;                    //百分位
qianfen=(wd%100)/10;                     //千分位
wanfen=wd%10;                            //万分位
Nop();
}
//-------------------------------------------------------------------------------
// 数码管显示驱动
//-------------------------------------------------------------------------------
void SegDisplay(void)
{
static unsigned char i = 0;
unsigned char j;
unsigned char tep;
tep = SegCS[i];         //片选输出
for(j=0;j<8;j++)        //8位
{
  if(tep&0x80) SDAT = 1;
  else         SDAT = 0;
  SCLK = 1;
  SCLK = 0;
  tep = tep<< 1;
}
tep = SegBuf[i];        //数据输出
for(j=0;j<8;j++)        //8位
{
  if(tep&0x80) SDAT = 1;
  else         SDAT = 0;
  SCLK = 1;
  SCLK = 0;
  tep = tep<< 1;
}

if(i < 5) i ++;        //扫描6位
else      i = 0;
}
/*
//-------------------------------------------------------------------------------
// ADC采集程序
//-------------------------------------------------------------------------------
unsigned int  SampleADValue[8];    // 8次采样
unsigned int  AvgADValue = 0;      // AD采样平均值
unsigned char ADConverStep = 0;    // AD采样频步
void GET_ADValue(void)
{
unsigned char i;
unsigned int ConverValue;
do
{
}while(ADCON0bits.GO_DONE);   //等待转换完成
ConverValue = ADRESH;         //处理10位结果
ConverValue = (ConverValue << 8) + ADRESL;
SampleADValue[ADConverStep] = ConverValue;
if (ADConverStep == 7)  
{
  ConverValue = 0;
  for (i = 0; i < 8 ; i++)
  {
   ConverValue += SampleADValue[i];
  }
  AvgADValue = ConverValue >> 3;
  ADConverStep = 0;
}
else
{
  ADConverStep++;
}
}
*/
//-------------------------------------------------------------------------------
// TMR1定时器初始化
//-------------------------------------------------------------------------------
void TMR1_Init(void)
{   
TMR1H = 0xF0;             //4mS 4MHz
TMR1L = 0x98;        
T1CONbits.RD16 = 1;       //16位定时方式
T1CONbits.TMR1CS = 0;     //内部FOSC/4
PIE1bits.TMR1IE = 1;      //T1中断 ON
}
/*
//-------------------------------------------------------------------------------
// ADC初始化
//-------------------------------------------------------------------------------
void ADC_Init(void)               // ADC 初始化
{
ADCON0 = 0b00000001;          // ADC模块使能
ADCON1 = 0b00001110;          // AN0 ADC输入
ADCON2 = 0b10111111;          // 右对齐  FRC
}
*/
//-------------------------------------------------------------------------------
// 高优先级中断向量
//-------------------------------------------------------------------------------
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void)
{
_asm
goto  Interrupt_High        //跳到中断程
_endasm
}
//-------------------------------------------------------------------------------
// 高优先级中断服务程序
//-------------------------------------------------------------------------------
#pragma interrupt Interrupt_High
void Interrupt_High(void)
{
if(PIR1bits.TMR1IF)          //T1中断
{
  PIR1bits.TMR1IF = 0;     //清除标志位
  TMR1H = 0xF0;            //4MS
  TMR1L = 0x98;
  SegDisplay();            //扫描显示
  TickClock = 1;          //置位
}
if(PIR1bits.RCIF)            // 接收中断
{
  PIR1bits.RCIF = 0;
  TXREG = RCREG;           // 将收到的数据发出
  if(RCSTAbits.OERR)       // 接收溢出错误处理
  {
   RCSTAbits.CREN = 0;
   RCSTAbits.CREN = 1;
  }
}
}
//-------------------------------------------------------------------------------
// 计算温度值
/*//-------------------------------------------------------------------------------
int GET_TempValue(unsigned int ADCValue)
{
ADCValue = (32*ADCValue)/10;     // y = (3300/1024)* x

if(ADCValue >500)   ADCValue = (ADCValue - 500);   //零上   500mV时 零度
else                ADCValue = (500 - ADCValue);   //零下

return ADCValue;
} */
void initled()//初始化数码管
{
SegBuf[0] = Bmp0Map;               // "T"
SegBuf[1] = Bmp0Map;                  // "P"
SegBuf[2] = Bmp0Map;    //千位
SegBuf[3] = Bmp0Map;//百位
SegBuf[4] = Bmp0Map;
SegBuf[5] = Bmp0Map;
}
//-------------------------------------------------------------------------------
// 数码管分段显示函数
//-------------------------------------------------------------------------------
void disp()
{
SegBuf[0] =SegCode[6];               // "T"
SegBuf[1] =SegCode[5];                 // "P"
SegBuf[2] =SegCode[4];//千位
SegBuf[3] =SegCode[baifen];//百位
SegBuf[4] =SegCode[qianfen]; //十位 有小数点
SegBuf[5] =SegCode[wanfen];//个位
}
void delay1(uint x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
//-------------------------------------------------------------------------------
// 主程序部分
//-------------------------------------------------------------------------------
void main(void)
{
unsigned int SystemTick = 0; // 串口发数据定时
TRISC = 0b11010011;          //RA2 RA3 RA5 输出
TRISB = 0b11111100;          //RB0 RB1 输出
TMR1_Init();                 //定时器1初始化  
// ADC_Init();                  //ADC初始化
  disp();//
INTCONbits.PEIE = 1;         //外设中断允许
INTCONbits.GIE  = 1;         //总中断允许
T1CONbits.TMR1ON= 1;         //使能T1
// initled();
// disp();  

while(1)
{
get_temp();
   disp();                   //显示温度值
   
}
}

回复

使用道具 举报

ID:125710 发表于 2016-7-5 15:25 | 显示全部楼层
有没有可以帮忙的朋友
回复

使用道具 举报

ID:111634 发表于 2016-7-5 19:28 | 显示全部楼层
本帖最后由 zl2168 于 2016-7-5 19:30 编辑

原因是你那个程序不靠谱!这么长的程序谁会逐条耐心看呢?给你个靠谱案例(程序在书中)参考,自己下功夫研读吧!!!


实例97 一线式DS18B20测温


Proteus仿真一下,确认有效。
实例97 DS18B20测温.rar (51.78 KB, 下载次数: 16)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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