📄 experiment_5.c
字号:
/******************************************************************************
实验五 多片ds18b20 温度采集 2005.1.13
*******************************************************************************/
#include <string.h>
#include "..\inc\option.h"
#include "..\inc\44b.h"
#include "..\inc\44blib.h"
#include "..\inc\def.h"
#include "..\inc\timer.h"
/***************************************************************************
Timer5 初始化
入口参数:Timing_count=定时时间常数,定时时间=定时时间常数*0.02ms
T5_int_Enable=1,T5 中断方式,T5_int_Enable=0,T5 查询方式
****************************************************************************/
Timer_Init(U16 timing_count,U8 T5_int_Enable)
{
rINTMSK=BIT_GLOBAL|BIT_TIMER5;
rTCFG0=0X0c70101;//prescaler=199 rTCFG0=0X010101;prescaler=1
rTCFG1=0X0100000; // DIV=4
rTCNTB5=timing_count;
//rTCMPB5=(timing_count/2); havn't rTCMPB5!!! but T0--T4 have.
rTCON=0X2000000;
rTCON=0X1000000;
if(T5_int_Enable)
{
rINTCON=0X05;
rINTMOD=0X0;
rINTMSK=~(BIT_GLOBAL|BIT_TIMER5);
}
}
/**********************************************************************************
匹配ROM(命令 55H),发8字节ROM代码
入口参数:*ROM_addr 为DS18B20-ID首地址
**********************************************************************************/
Match_Rom(U8 *ROM_addr)
{
U8 count;
U8 *p;
U8 temp=0x55; //匹配ROM 命令 55H
Write_Byte(temp);
p=ROM_addr; //发8字节ROM代码
count=8;
while(count)
{
Write_Byte(*p);
p++;
count--;
}
}
/***********************************************************************************
读ROM(命令 33H),读回8字节ROM代码
入口参数:Read_Addr=ROM代码首地址
出口参数:Read_Addr 地址开始的8个单元= 读回8字节ROM代码
***********************************************************************************/
Read_Rom(U8 *Read_Addr)
{
U8 count;
U8 *p;
U8 temp=0x33; //读ROM 命令 33H
Write_Byte(temp);
p=Read_Addr; //从18b20 读回8字节ROM代码
count=8;
while(count)
{
*p=Read_Byte();
p++;
count--;
}
}
/**********************************************************************************
发启动温度转换 命令(44h)
***********************************************************************************/
void Convert_Start(void)
{
Write_Byte(0x44);
// Write_Byte(0X01); //主机 发'1',释放总线,非窃电方式时可不用
}
/**********************************************************************************
发Skip ROM 命令(CCh)
***********************************************************************************/
void Skip_Rom(void)
{
Write_Byte(0xCC);
}
/**********************************************************************************
发 Read_Ram 命令,读回2字节12位转换结果
**********************************************************************************/
U16 Read_Ram()
{
U8 Temperature_L;
U8 Temperature_H;
U16 Temperature; //12位转换结果Temperature
float Celsius; //分辨度为 0.0625 度
Write_Byte(0xBE); //发Read_Ram 命令,
Temperature_L= Read_Byte(); //读回2字节12位转换结果
Temperature_H= Read_Byte();
Temperature=Temperature_H;
Temperature=(Temperature_H<<8)+Temperature_L;
Celsius=Temperature*0.0625;
return Temperature;
}
/***********************************************************************************
复位ds18b20
入口参数:无
返回参数:=1:总线上有18B20应答; =0:总线上无应答;
***********************************************************************************/
U8 Reset_18B20(void)
{
U8 temp;
rPCONG |= 0X0100; //PCONG[15:0]16位, G口配置寄存器.
rPCONG &= 0x0fdff; //PCONG[9:8]=01, 定义PG4 output。
rPUPG &=0xef; //PUPG[7:0]8位, PUPG[4]=0,pull up enabled
rPDATG |=0x0100; //置"1"总线,3.8us.
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
rPDATG &=0x0ef; //主机发复位脉冲"0",500 us.
temp=150; //500us
while(temp)
{
asm("nop");
temp--;
}
rPDATG |=0x10; //主机发"1",17 us.(ds18b20等候15--60us,实测25us)
temp=4;
while(temp)
{
asm("nop");
temp--;
}
rPCONG &=0xfcff; //PG4[9:8]=00,input
Timer_Init(12,0); //12*0.02ms=240 us
while(1)
{
temp=rPDATG;
temp &=0x10;
if(temp==0x0) //有应答?
{
rTCON=0x0; //停止T5计时
while(temp==0x0)
{
temp=rPDATG;//等应答结束
temp &=0x10;
}
temp=80; //250us
while(temp)
{
asm("nop");
temp--;
}
return 1; //有应答,返回1.
}
else
{
if(~(rTCNTO5))
return 0; //无应答,返回0.
}
}
}
/***********************************************************************************
主机读 1 Byte
入口参数: 无
返回参数: 读入的 1 Byte数据, 低位在先!!
***********************************************************************************/
U8 Read_Byte()
{
U8 count;
U8 temp_Byte=0;
U8 temp;
count=8; //读入1 Byte数据(=8bit)
temp_Byte;
while(count)
{
temp=Read_Bit(); //读入 1 Bit
temp_Byte=(temp_Byte>>1)|(temp&0x80);
count--;
}
return temp_Byte;
}
/**********************************************************************************
主机读 1 Bit
入口参数: 无
返回参数: 读入的 1 Bit数据(U8 temp的 Bit[0] )
***********************************************************************************/
U8 Read_Bit()
{
U8 temp;
U8 read_bit;
rPDATG &=0x0ef; //主机发"0",2.2us
asm("nop");
asm("nop");
rPDATG |=0x010; //主机发"1",3.8us.
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
rPCONG &=0xfcff; //PG4[9:8]=00,input.
asm("nop");
while(1)
{
read_bit=(rPDATG<<3)&0x80; //读总线 PG4
asm("nop");
if(read_bit==(rPDATG>>4)&0X01);//再读总线 PG4
break; //两次读相等?
}
temp=8; //30us
while(temp)
{
asm("nop");
temp--;
}
rPCONG |=0x0100; //PG4[9:8]=01,output
asm("nop");
rPDATG |=0x10; //发"1",2us.
asm("nop");
asm("nop");
return read_bit;
}
/**********************************************************************************
主机写 1 Byte
入口参数:欲写的 1 Byte数据
返回参数:无
***********************************************************************************/
void Write_Byte(U8 write_Byte)
{
U8 count;
U8 temp_bit;
count=0x08;
while(count)
{
temp_bit=write_Byte&0x01;
Write_Bit(temp_bit);
write_Byte=write_Byte>>1;
count--;
}
}
/***********************************************************************************
主机写 1 Bit
入口参数:欲写的 1 Bit数据(U8 temp的 Bit[0] )
返回参数:无
************************************************************************************/
U8 Write_Bit(U8 write_Bit)
{
U8 temp;
rPCONG |=0x100; //PG4[9:8]=01,output
asm("nop");
rPDATG &=0x0ef; //发"0",3us.
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
if((write_Bit &0x01)==0x01)
rPDATG |=0x10;
else
rPDATG &=0x0ef;
temp=8; //30us
while(temp)
{
asm("nop");
temp--;
}
rPDATG |=0x10; //发"1",2us.
asm("nop");
asm("nop");
}
void Main(void)
{
U8 temp;
U16 temperature[6];
float Celsius[6];
U8 count;
U8 ds18b20_Rom_1[8]={0x28,0x47,0x30,0x05f,0x0,0x0,0x0,0x28};
U8 ds18b20_Rom_2[8]={0x28,0x8f,0x44,0x05f,0x0,0x0,0x0,0x64};
U8 ds18b20_Rom_3[8]={0x28,0x00,0x45,0x05f,0x0,0x0,0x0,0x67};
U8 ds18b20_Rom_4[8]={0x28,0x35,0x3b,0x05f,0x0,0x0,0x0,0xae};
U8 ds18b20_Rom_5[8]={0x28,0x38,0x2d,0x05f,0x0,0x0,0x0,0x04};
while(1)
{
temp=Reset_18B20(); //复位
if(temp==1)
Skip_Rom(); //发 skip_Rom 命令
Convert_Start(); //发启动温度转换 命令(44h)
Timer_Init(50000,0); //延时 1s
asm("nop");
while(rTCNTO5);
count=5;
while(count)
{
temp=Reset_18B20(); //复位
if(temp==1)
switch(count)
{
case 1:
Match_Rom(ds18b20_Rom_1);//发 匹配 ROM_ID 命令(55h),及ds18b20_1 Rom地址
break;
case 2:
Match_Rom(ds18b20_Rom_2);
break;
case 3:
Match_Rom(ds18b20_Rom_3);
break;
case 4:
Match_Rom(ds18b20_Rom_4);
break;
case 5:
Match_Rom(ds18b20_Rom_5);
default:
break;
}
temperature[count]=Read_Ram(); // 发Read_Ram命令,读回温度值 12位
Celsius[count]=temperature[count]*0.0625;
count--;
}
/* rPCONG |= 0X0400; // PCONG[15:0]16位, G口配置寄存器.
rPCONG &= 0x0f7ff; // PCONG[11:10]=01, 定义PG5 output。
rPDATG |=0x020; // 断开加热棒
asm("nop");
rPDATG &=0x0df; //接通加热棒*/
asm("nop");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -