下面是用ht46ru232芯片编写的温度(ds18b20)测量部分,用两位共阴数码管显示,可结果是十位出现“8”,个位没有显示,原代码如下,请高手大哥们指导一下
#include "HT46RU232.h"
const unsigned char table[]={0x03f,0x006,0x05b,0x04f,0x66,0x6d,0x7d,0x007,0x7f,0x6f};
bit f_Collection_Temperature; // 是否允许采集当前温度
bit f_Have_DS18B20; // 存在18B20标志位
// 字节定义
unsigned char g_Collection_Step; // 计录采集步骤
unsigned char DQ_Register; // 命令发送寄存器
unsigned char time; // 延时器的时间
unsigned char tempint; //存放温度的整数部分
// 组定义
unsigned char Temperature_Code[2]; // 存储从1 wire器件读
//************************************************************
// 以下为原函数声明
//************************************************************
//执行温度采集
void Collection_Temperature(void);
//初始化DS18B20子程序
bit Ow_Reset(void);
// 送读或写命令到1 wire 器件
void Command(unsigned char Write);
// 从1 wire 器件读多个字节
void Read(void);
//延迟时间为(time×3+9)μs
void _Delay_Us(void);
// 对单片机内部资源进行初始化操作
void Ini( void);
//************************************************************
// 以下为原函数
//************************************************************
void display(unsigned char result) //数码管显示当前温度子程序
{
unsigned char shi,ge;
shi=result/10;
ge=result%10;
_pa=0x00;
_pb=0x7c;
_pa=table[shi];
_delay(5000);
_pa=0x00;
_pb=0xbc;
_pa=table[ge];
_delay(5000);
}
//执行温度采集
void Collection_Temperature(void)
{
g_Collection_Step ++; //***第一步***
if(g_Collection_Step ==1) // 给DS18B20供电
{ //****************
_pbc &=0b11111110;
_pb0 = 1; // 设置pb6为输出方式且为高电平
_pbc |=0b00000001; // 设置 pb6为输入方式
time = 150; // 延时459us,等待S18B20启动
_Delay_Us( ); // 以完成整个时序
}
if(g_Collection_Step ==1) //***第二步***
{ //启动温度转换
//************
f_Have_DS18B20 =Ow_Reset( ); // 初始化程序
DQ_Register =0xCC; // 跳过ROM命令
Command(DQ_Register); // 发送命令
DQ_Register =0x44; // 启动温度转换命令
Command(DQ_Register); // 发送命令
}else if(g_Collection_Step ==2) //***第三步***
{ //读暂存存储器
//************
Ow_Reset( ); // 初始化程序
DQ_Register =0xCC; // 跳过ROM命令
Command(DQ_Register); // 发送命令
DQ_Register =0xBE; // 读暂存存储器命令
Command(DQ_Register); // 发送命令
Read( ); // 读暂存存储器
g_Collection_Step =0; //将采集步骤清零
_pb0 =1; // 释放单总线z
_pbc |=0b00000001; // 设置 pb0为输入方式
f_Collection_Temperature =0; //清采集温度请求标志
}else
{
g_Collection_Step =0; // 冗余
f_Collection_Temperature =0; //清采集温度请求标志
}
return ;
}
//******************************************************************
// 发送初始化信号
//功能描述:对DS18B20发送一个低电平为500us、高电平也为500us的初始化信号。
//入口参数:无
//出口参数:Ow_Reset
//影响参数:_PB0、PBC
//
//******************************************************************
bit Ow_Reset(void)
{
char Presence;
_pb0 =0; // 拉低单总线开始复位
_pbc &=0b11111110; // 设置 pb6为输出方式
time =180;
_Delay_Us( ); // 延迟549μs
_pb0 =1; // 释放单总线
_pbc |=0b00000001; // 设置 pb6平时为输入方式
time =17; // 延时60us
_Delay_Us( ); // 等待芯片应答信号
Presence =_pb0; // 获取应答信号
time =142; // 延时435us
_Delay_Us( ); // 以完成整个时序
return(Presence); // 返回应答信号
// 有芯片应答presence=0;无芯片应答presence=1
}
//******************************************************************
// 发送命令
//功能描述:发送指令给DS18B20。
//入口参数:Write
//出口参数:无
//影响参数:_PB0、PBC
//******************************************************************
void Command(unsigned char Write)
{
unsigned char i,j;
_pb0 =1;
_pbc &=0b11111110; // 设置pb0为输出方式且为高电平
for (j=0;j<=7;j++)
{
i =Write&1;
if (i==1) //写"1"
{
_pb0 =0; //总线拉低产生写时间隙
#asm // 延时8us
nop
nop
nop
nop
nop
nop
nop
nop
#endasm
_pb0 =1;
time =22;
_Delay_Us( ); // 延时80us
}else
{
_pb0 =0; //总线拉低产生写时间隙
time =26;
_Delay_Us( ); // 延时90us
_pb0 =1;
#asm // 延时8us
nop
nop
nop
nop
nop
nop
nop
nop
#endasm
}
Write =Write>>1; // 写一位合计约100us
} // 写一字节合计800us
}
//******************************************************************
// 读出多个字节
//功能描述:从DS18B20读出多个字节,通过设定f的大小来决定。
//入口参数:无
//出口参数:Temperature_Code[f]
//影响参数:_PB0、PBC
//******************************************************************
// 从1 wire 器件读出多个字节
void Read(void)
{
unsigned char j,f,Byte_Temp;
Byte_Temp =0x00;
for(f=0;f<1;f++)
{
for (j=0;j<=7;j++)
{
_pbc &=0b11111110; // 设置 pb0为输出方式
_pb0 =0; // 将单总线拉低开始读时序
#asm // 延时3us
nop
nop
nop
//nop
#endasm
_pb0 =1; // 释放单总线
_pbc |=0b01000000; // 设置 pb0平时为输入方式
#asm // 延时8us后再读数据
nop
nop
nop
nop
nop
nop
nop
nop // 为了保证可靠读数
#endasm // 将读时刻放在15us内
if (_pb0 ==1) // 以上为读一位的开头
{ // 1 wire器件数据协议是从低---->高
Byte_Temp =Byte_Temp>>1; // 右移一位
Byte_Temp =Byte_Temp|0x80; // 最高位置1
}else
{
Byte_Temp =Byte_Temp>>1; // 右移一位并自动置0
}
time =16;
_Delay_Us( ); // 延时60us
}
Temperature_Code[f] =Byte_Temp;
}
Temperature_Code[0]>>4; //将读取的数据转换成温度值,整数部分存tempint
Temperature_Code[1]<<4;
tempint=Temperature_Code[1]|Temperature_Code[0];
display(tempint);
}
//*********高效延时************************************
//入口参数:全局变量time
//出口参数:无
//使用说明:先定义全局变量
// unsigned char time;
//延迟时间:(time×3+9)μs
//约束条件:time>=1
//
//**********************************************************
void _Delay_Us( void )
{
#asm
loop: SDZ _time;
jmp loop;
#endasm
}
//18B20加电压后过26us输出端有一个100us的低平,在段期间不接受任何命令
//因此延时200us后再对它操作比较适合。
//************************************************************
// 对单片机内部资源进行初始化操作
//************************************************************
void Ini( void)
{
//关闭其它功能,降低功耗
_intc0 = 0x00; // 禁止所有中断
_intc1 = 0x00;
_tmr0c = 0x00; // 关闭定时器0
_tmr1c = 0x00; // 关闭定时器1
_adcr &= 0b01000111; // PB口全部配置为I/O,同时AD的电源也被关闭
//系统各I/O开始化子程序
_pac=0x00; //PA口输出,接数码管段选取
_pbc=0x00; //PB口输出
}
//************************************************************
// 主程序
//************************************************************
void main( )
{
Ini( ) ; // 调用系统配置模块
while(1)
{
f_Collection_Temperature = 1;
//************************************************************
// 申请温度采集
//************************************************************
if(f_Collection_Temperature)
{
Collection_Temperature( ); // 执行温度采集
}
}
} |