📄 ds1820.c
字号:
#include <stdio.h> //头文件
#include <reg52.h>
#define FALSE 0
#define TRUE 1
#define uchar unsigned char //预定义
sbit DS18S20_DQ = P2^0; //定义P2^0引脚为DS18S20的DQ引脚
/******************************* 全局变量声明 ********************************/
uchar DS18S20ROM[8]; // DS18S20 ROM位
uchar LastData = 0;
uchar EndFlag = 0;
uchar ROMFound[5][8]; // DS18S20的ROM 代码表
uchar numROMs;
uchar CRCdsc; //用于CRC校验
uchar code dsc[] = {
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};
void Delay(int useconds)
{
int s;
for (s=0; s<useconds;s++); //空循环语句实现延时
}
uchar Reset(void)
{
uchar PresenceSignal;
DS18S20_DQ = 0; //拉低数据线DQ
Delay(30); //延时
DS18S20_DQ = 1; //置数据线DQ为高电平
Delay(3); //延时
PresenceSignal = DS18S20_DQ; //读取存在信号
Delay(30); //延时,等待时间隙结束
return PresenceSignal; //返回存在信号
}
void WriteBit(char val)
{
DS18S20_DQ = 0; //拉低数据线DQ开始写时间隙
if(val==1)
DS18S20_DQ =1; //数据线DQ置1,写1
else
DS18S20_DQ=0; //数据线DQ置0,写0
Delay(5); //延时,在时间隙内保持电平值,
DS18S20_DQ = 1; //拉高数据线DQ
}
void WriteByte(char val)
{
uchar i;
uchar temp;
for (i=0; i<8; i++) //循环写入字节,每次写入一位
{
temp = val>>i; //移位
temp &= 0x01;
WriteBit(temp); //调用位写入函数
}
Delay(5);
}
uchar ReadBit(void)
{
uchar i;
DS18S20_DQ = 0; //拉低数据总线DQ开始读时间隙
DS18S20_DQ = 1; //DQ置1
for (i=0; i<3; i++); //延时
return DS18S20_DQ ; //返回数据总线DQ上的位数据
}
uchar ReadByte(void)
{
uchar i;
uchar value = 0;
for (i=0;i<8;i++) //读取字节,每次读取一位
{
if(ReadBit())
value|=0x01<<i; //循环左移
Delay(7);
}
return(value); //返回字节数据
}
void ReadROMSerialNumber(void)
{
int n;
char dat[9];
printf("\nReading DS18S20 ROM Code\n"); //输出信息
Reset(); //复位函数
WriteByte(0x33); //读出ROM序列号命令
for (n=0;n<8;n++)
{
dat[n]=ReadByte(); //循环读ROM序列号
}
printf("\nDS18S20 ROMCode=%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)
{
CRCdsc = dsc[CRCdsc^x]; //查表校验
return CRCdsc;
}
uchar SearchDevice(void)
{
uchar m = 1; //DS18S20 ROM 位索引
uchar n = 0; //DS18S20 ROM 字节索引
uchar k = 1;
uchar x = 0;
uchar discrepMarker = 0;
uchar g;
uchar nxt;
int flag;
nxt = FALSE;
CRCdsc = 0;
flag = Reset(); //复位函数
if(flag||EndFlag) //如果没有其它器件
{
LastData = 0;
return FALSE; //返回"假"
}
WriteByte(0xF0); //搜索ROM 命令
do //循环
{
x = 0;
if(ReadBit()==1) x = 2;
Delay(8);
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) discrepMarker = 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 = discrepMarker; //置位LastData, lastOne和nxt
EndFlag = (LastData==0);
nxt = TRUE; //表示总线上还有其它器件,搜索未结束
}
return nxt;
}
uchar FindFirstDevice(void)
{
LastData = 0;
EndFlag = FALSE;
return SearchDevice(); //搜索器件函数SearchDevice
}
void ReadData(void)
{
int j;
char pad[10];
printf("\nReading ScratchPad Data\n");
WriteByte(0xBE); //读暂存器命令(代码为BEH)
for (j=0;j<9;j++) //循环读取暂存器中9个字节的数据
{
pad[j]=ReadByte(); //字节读取函数
}
printf("\n ScratchPAD DATA =%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 m;
if(!Reset()) //复位总线
{ //如果存在器件则开始处理
if(FindFirstDevice()) //调用FindFirstDevice函数
{
numROMs=0;
do //循环
{
numROMs++;
for(m=0;m<8;m++)
{ //识别ROM代码
ROMFound[numROMs][m]=DS18S20ROM[m];
}
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]);
}while (SearchDevice()&&(numROMs<10)); //直到没有发现其它器件
}
}
}
void ReadTemperature(void)
{
char get[10];
char temp_lsb,temp_msb;
int k;
char Ftemperature,Ctemperature;
Reset(); //复位
WriteByte(0xCC); //跳过ROM序列号命令(代码为CCH)
WriteByte(0x44); //启动温度转换命令(代码为44H)
Delay(5);
Reset();
WriteByte(0xCC); //跳过ROM序列号命令(代码为CCH)
WriteByte(0xBE); //读暂存器命令(代码为BEH)
for (k=0;k<9;k++)
{
get[k]=ReadByte(); //循环读取
}
printf("\n Scratch DATA = %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取补
}
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 );//华氏温度值输出
}
void main(void)
{
uchar Select_Menu; //功能选择
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 DS18S20\n"); //输出信息
printf("\n*********************************************************\n");
printf (" Select Control Menu Option\n");
printf (" 1. Reset 1-Wire.\n");
printf (" 2. Read DS18S20 ROM Code.\n");
printf (" 3. Search DS18S20 ROM.\n");
printf (" 4. Find All DS18S20.\n");
printf (" 5. Read DS18S20 Scratch.\n");
printf (" 6. Read DS18S20 Temperature.\n");
printf (" 7. Exit.\n");
printf (" Please Input Menu Option:\n");
Select_Menu = _getkey(); //从键盘输入选择数字
switch(Select_Menu)
{
case '1': //复位1-Wire总线
printf ("\n You Select 1. Reset 1-Wire\n");
Reset(); //复位函数
break;
case '2': //读DS18S20 ROM
printf ("\n You Select 2. Read DS18S20 ROM Code \n");
Reset();
ReadROMSerialNumber(); //读取ROM代码函数
break;
case '3': //搜索DS18S20
printf("\n You Select 3. Search DS18S20 ROM \n");
Reset();
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]);
break;
case '4': //搜索所有DS18S20
printf ("\n You Select 4. Find All DS18S20\n");
Reset();
FindDevices(); //查找器件函数
break;
case '5': //读取高速暂存器
printf ("\n You Select 5. Read DS18S20 Scratch \n");
Reset();
WriteByte(0xCC); //跳过ROM序列号命令(代码为CCH)
ReadData(); //读取高速暂存器
break;
case '6': //读取温度
printf ("\n You Select 6. Read DS18S20 Temperatur\n");
ReadTemperature(); //读取温度值
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!"); //退出
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -