基于ARM的多片ds18b20 温度采集系统/******************************************************************************实验五多片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.02msT5_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=1rTCFG1=0X0100000; // DIV=4rTCNTB5=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 命令55HWrite_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 命令33HWrite_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位转换结果Temperaturefloat 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 enabledrPDA TG |=0x0100; //置"1"总线,3.8us.asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");rPDA TG &=0x0ef; //主机发复位脉冲"0",500 us.temp=150; //500uswhile(temp){asm("nop");temp--;}rPDA TG |=0x10; //主机发"1",17 us.(ds18b20等候15--60us,实测25us) temp=4;while(temp){asm("nop");temp--;}rPCONG &=0xfcff; //PG4[9:8]=00,inputTimer_Init(12,0); //12*0.02ms=240 uswhile(1){temp=rPDA TG;temp &=0x10;if(temp==0x0) //有应答?{rTCON=0x0; //停止T5计时while(temp==0x0){temp=rPDA TG;//等应答结束temp &=0x10;}temp=80; //250uswhile(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 Bittemp_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;rPDA TG &=0x0ef; //主机发"0",2.2usasm("nop");asm("nop");rPDA TG |=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=(rPDA TG<<3)&0x80; //读总线PG4asm("nop");if(read_bit==(rPDA TG>>4)&0X01);//再读总线PG4break; //两次读相等?}temp=8; //30uswhile(temp){asm("nop");temp--;}rPCONG |=0x0100; //PG4[9:8]=01,outputasm("nop");rPDA TG |=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,outputasm("nop");rPDA TG &=0x0ef; //发"0",3us.asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");if((write_Bit &0x01)==0x01)rPDA TG |=0x10;elserPDA TG &=0x0ef;temp=8; //30uswhile(temp){asm("nop");temp--;}rPDA TG |=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); //延时1sasm("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。