⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1820.c

📁 零基础单片机C语言设计全套教程
💻 C
字号:
#include <stdio.h>						//头文件
#include <reg52.h>

#define uchar unsigned char				//预定义
#define FALSE 0
#define TRUE 1

sbit ONEWIRE_DQ = P2^0;                	//定义P2^0引脚为DS18S20的DQ引脚

/******************************* 全局变量声明 ********************************/
uchar DS18S20ROM[8];          			// DS18S20 ROM位
uchar ROMFound[5][8];  					// DS18S20的ROM 代码表
uchar CRCdsc;							//用于CRC校验

/******************************* 子函数声明 ********************************/
void Delay(int useconds);
uchar Reset(void);
void WriteBit(char val);
void WriteByte(char val);
uchar ReadBit(void);
uchar ReadByte(void);
void ReadROMNumber(void);
uchar CRCCheck( uchar x);
uchar SearchDevice(uchar EndFlag, uchar LastData);
uchar FindFirstDevice(void);
void ReadData(void);
void FindDevices(void);
void ReadTemperature(void);

/******************************* 主函数 ********************************/
void main(void) 
{
uchar MenuOption; 					//功能选择
uchar LastData = 0; 
uchar EndFlag = 0; 

SCON=0x50;							//初始化串行口模式1
TMOD=0x20;							//初始化T1为定时功能,模式2
PCON=0x80;							//设置SMOD=1
TL1=0xF4;							//波特率4800bit/s,初值
TH1=0xF4;

  TR1 = 1;       						//启动T1
  TI = 1; 								//启动发送

  while(1)								//主循环
{ 						
  printf (" AT89S52 Control 1-Wire DS18S20\n");
  printf("\n*********************************************************\n");
  printf (" Select Control Menu Option\n");
  printf (" 1. Reset All 1-Wire Devices.\n");
  printf (" 2. Read DS18S20 ROM Number.\n");
  printf (" 3. Search DS18S20 ROM.\n");
  printf (" 4. Find All DS18S20 Devices.\n");
  printf (" 5. Read DS18S20 Scratch.\n");
  printf (" 6. Read Temperature.\n");
  printf (" 7. Exit Program.\n");
  printf (" Please Input Menu Option:\n");

	MenuOption = _getkey(); 				//从键盘输入选择数字
	switch(MenuOption)
{
		case '1': 						//复位1-Wire总线
			printf ("\n You Select 1. Reset All 1-Wire Devices .\n");
			printf("\nResetting!......\n");
			Reset();					//复位函数
			printf("\nReset Over!\n");
			break;
		case '2': 						//读DS18S20 ROM
			printf ("\n You Select 2. Read DS18S20 ROM Number. \n");
			printf("\nReading!......\n");
			ReadROMNumber();			//读取ROM代码函数
			printf("\nRead Over!\n");
			break;
		case '3': 						//搜索DS18S20
			printf("\n You Select 3. Search DS18S20 ROM \n");
			printf("\nSearching!......\n");
			FindFirstDevice();			//搜索第一个器件
			printf("\nDS18S20 ROM CODE =%02X%02X%02X%02X\n",
			  ROMFound[5][7],ROMFound[5][6],ROMFound[5][5],ROMFound[5][4],
			  ROMFound[5][3],ROMFound[5][2],ROMFound[5][1],ROMFound[5][0]);
			printf("\nSearch Over!\n");
			break;
		case '4': 						//搜索所有DS18S20
			printf ("\n You Select 4. Find All DS18S20\n");
			printf("\nFinding!......\n");
			FindDevices();				//查找器件函数
			printf("\nFind Over!\n");
			break;
		case '5': 						//读取高速暂存器
			printf ("\n You Select 5. Read DS18S20 Scratch \n");
			printf("\nReading!......\n");
			WriteByte(0xCC); 			//跳过ROM序列号命令(代码为CCH)
			ReadData();				//读取高速暂存器
			printf("\nRead Over!\n");
			break;
		case '6': 						//读取温度
			printf ("\n You Select 6. Read DS18S20 Temperatur\n");
			printf("\nReading!......\n");
			ReadTemperature(); 		//读取温度值
			printf("\nRead Over!\n");
			break;
		case '7': 						//退出程序
			printf ("\n You Select 7. Exit\n");
			goto Exit; 				//转向Exit标号处
			break;
		default: 
printf ("\n Error: Please Select Right Menu Option\n");
			break;
		}; 
  }
Exit: printf("Exit the program!");				//退出
}



 void Delay(int useconds) 
{
int s,t;
for (s=0; s<useconds;s++)					//双重循环
{
	for(t=0;t<10;t++);					//空循环语句实现延时
}
}

uchar Reset(void) 
{
uchar PresencePalse;
ONEWIRE_DQ = 0;  					//拉低数据线DQ
Delay(3); 								//延时
ONEWIRE_DQ = 1; 						//置数据线DQ为高电平
Delay(1); 								//延时
PresencePalse = ONEWIRE_DQ; 			//读取存在信号
Delay(3); 								//延时,等待时间隙结束
if(PresencePalse) 						//返回存在信号
	return 1;
else
	return 0;
}

void WriteBit(char val) 
{
ONEWIRE_DQ = 0; 						//写时间隙
if(val==1)
 ONEWIRE_DQ =1; 					//数据线DQ置1,写1 
else
 ONEWIRE_DQ=0;						//数据线DQ置0,写0
Delay(1); 								//延时,在时间隙内保持电平值,
ONEWIRE_DQ = 1; 						//拉高数据线DQ
}

void WriteByte(char val) 
{
uchar i;
uchar temp;
for (i=0; i<8; i++)						//循环写入字节,每次写入一位
{ 
	temp = val>>i; 						//移位
	temp &= 0x01; 		
	WriteBit(temp); 					//逐位写
}
}

uchar ReadBit(void) 
{
ONEWIRE_DQ = 0;     		 			//读时间隙
ONEWIRE_DQ = 1; 						//DQ置1
Delay(1);								//延时
if(ONEWIRE_DQ) 						//返回数据总线DQ上的位数据
	return 1;
else
	return 0;
}

uchar ReadByte(void) 
{
uchar i;
uchar value = 0;
for (i=0;i<8;i++) 						//读取字节,每次读取一位
{
if(ReadBit()) 
value|=0x01<<i; 					//循环左移
else
	;								//空语句
Delay(1); 					
}
return(value);							//返回字节数据
}

void ReadROMNumber(void) 
{
int n;
char dat[9];
printf("\nReading DS18S20 ROM Number\n");	//输出信息
Reset();								//复位子函数
WriteByte(0x33);						//读出ROM序列号命令
for (n=0;n<8;n++)
{
	dat[n]=ReadByte();					//循环读ROM序列号
}
printf("\nDS18S20 ROMNumber= ");			//输出ROM序列号
printf("%X%X%X%X%X%X%X%X \n",		//输出ROM序列号
dat[7],dat[6],dat[5],dat[4],dat[3],dat[2],dat[1],dat[0]);
}

uchar CRCCheck( uchar x) 
{
uchar code dsc[] = 						//CRC校验表
{
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
};

CRCdsc = dsc[CRCdsc^x];				//查表校验
return CRCdsc;							//返回
}

uchar SearchDevice(uchar EndFlag, uchar LastData) 
{
uchar m = 1; 							//DS18S20 ROM 位索引
uchar n = 0;   							//DS18S20 ROM 字节索引
uchar k = 1;    
uchar x = 0;
uchar disMarker = 0; 
uchar g;
uchar nxt; 
int flag;
nxt =0; 								//初始化
CRCdsc = 0; 
flag = Reset(); 							//复位函数
if(flag||EndFlag) 						//如果没有其它器件
{									
LastData = 0; 	
return 0; 							//返回0
}
WriteByte(0xF0); 						//搜索ROM 命令
do 									//循环
{					
x = 0;
if(ReadBit()==1) 
x = 2;
Delay(1);
if(ReadBit()==1) 
x |= 1; 	
if(x ==3) 
break;
else 
{
if(x>0) 				
g = x>>1; 			
else 
{					
if(m<LastData) 
g = ((DS18S20ROM[n]&k)>0);
else 
g = (m==LastData); 
if (g==0) 
disMarker = m;
}
if(g==1) 
DS18S20ROM[n] |= k;
else 
DS18S20ROM[n] &= ~k;
WriteBit(g); 						//位写入函数
m++; 
k = k<<1; 
if(k==0) 
{ 
CRCCheck(DS18S20ROM[n]); 	//CRC校验
n++; 
k++;
}
}
}while(n<8); 							//直到全部ROM字节0~7都完成
if(m<65||CRCdsc)  
LastData=0; 
else 								//搜索成功
{									
LastData = disMarker; 				//置位LastData, lastOne和nxt
EndFlag = (LastData==0);
nxt = 1; 							//表示总线上还有其它器件,搜索未结束
}
return nxt;
}

uchar FindFirstDevice(void) 
{
uchar LastData = 0; 
uchar EndFlag = 0;
return SearchDevice(EndFlag,LastData); 		//搜索器件函数SearchDevice
}

void ReadData(void) 
{
int j;
char pad[10];
printf("\nReading DS18S20 ScratchPad Data\n");
WriteByte(0xBE);						//读暂存器命令(代码为BEH)
for (j=0;j<9;j++)							//循环读取暂存器中9个字节的数据
{
pad[j]=ReadByte();						//字节读取函数
}
printf("\n ScratchPAD DATA =");
printf("\n%X%X%X%X%X%X%X%X%X \n",	//输出结果
pad[8],pad[7],pad[6],pad[5],pad[4],pad[3],pad[2],pad[1],pad[0]);
}

void FindDevices(void) 
{
uchar numROMs;
uchar m;
uchar LastData = 0; 
uchar EndFlag = 0;
numROMs=0;

  if(!Reset()) 							//复位总线
{ 									//如果存在器件则开始处理
	if(FindFirstDevice()) 					//调用FindFirstDevice函数
{
		do 							//循环
{
			numROMs++;
			for(m=0;m<8;m++) 
{						//识别ROM代码
				ROMFound[numROMs][m]=DS18S20ROM[m]; 
			}
		 printf("\nDS18S20 ROM CODE = ");
		 printf("\n%02X%02X%02X%02X%02X%02X%02X%02X \n",
		 ROMFound[5][7],ROMFound[5][6],ROMFound[5][5],ROMFound[5][4],
		 ROMFound[5][3],ROMFound[5][2],ROMFound[5][1],ROMFound[5][0]);
		 }while (SearchDevice(EndFlag,LastData)&&(numROMs<10)); 
									//直到没有发现其它从器件
  	}
  }
}


void ReadTemperature(void) 
{
char get[10];
char temp_lsb,temp_msb;
int k;
char Ftemperature,Ctemperature;
Reset();								//复位
WriteByte(0xCC); 						//跳过ROM序列号命令
WriteByte(0x44); 						//启动温度转换命令
Delay(1);
Reset();
WriteByte(0xCC); 						//跳过ROM序列号命令
WriteByte(0xBE); 						//读暂存器指令
for (k=0;k<9;k++)
{
get[k]=ReadByte();						//循环读取
}
printf("\n Scratch DATA = %X%X%X%X%X%X%X%X%X \n",
get[8],get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);
temp_msb = get[1];
temp_lsb = get[0];
if (temp_msb <= 0x80)
{         
temp_lsb = (temp_lsb/2);    				//移位,得到完整的温度值
} 								
temp_msb = temp_msb & 0x80;     		//屏蔽符号位之外的所有数据位
if (temp_msb >= 0x80) 
{
temp_lsb = (~temp_lsb)+1; 				// temp_lsb取补,再加1
} 
if (temp_msb >= 0x80) 
{
temp_lsb = (temp_lsb/2);					//移位,得到完整的温度值
}
if (temp_msb >= 0x80) 
{
temp_lsb = ((-1)*temp_lsb); 				//符号位
} 
printf( "\nTempC= %d degrees C\n", (int)temp_lsb );//摄氏温度值输出
Ctemperature = temp_lsb; 
Ftemperature = (((int) Ctemperature)* 9)/5 + 32;
printf( "\nTempF= %d degrees F\n", (int)Ftemperature );//华氏温度值输出
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -