/**************************************
温度传感器程序
主芯片 : STC11F04 (1T)
工作频率: 11.0592MHz
开发人员:余焱民
**************************************/
/**********************************************************************/
typedef unsigned char uint8; // 无符号8位整型变量
typedef signed char int8; // 有符号8位整型变量
typedef unsigned short uint16; // 无符号16位整型变量
typedef signed short int16; // 有符号16位整型变量
typedef unsigned int uint32; // 无符号32位整型变量
typedef signed int int32; // 有符号32位整型变量
typedef float fp32; // 单精度浮点数(32位长度)
typedef double fp64; // 双精度浮点数(64位长度)
typedef unsigned char volatile xdata UINT8VX; //
/************************************************************************/
#include "REG51.H"
#include "INTRINS.H"
#define STX 0x02
#define ETX 0x03
#define ACK 0xfe
sfr AUXR=0x8e;
sfr BRT=0x9c;
sfr AUXR1=0xa2;
sfr WDT_CONTR=0xc1;
sbit IO_485 = P3^7; //485输入输出控制位P3.3
sbit DQ = P3^3; //DS18B20的数据口位P3.3
uint8 TPH; //存放温度值的高字节
uint8 TPL; //存放温度值的低字节
uint16 CRC_HL;
uint16 TEMP,HUMI;
uint16 TIME;
// 变量定义
unsigned char Sensor_Data[5]={0x00,0x00,0x00,0x00,0x00};
unsigned char Sensor_Check; //校验和
unsigned char Sensor_AnswerFlag; //收到起始标志位
unsigned char Sensor_ErrorFlag; //读取传感器错误标志
unsigned int Sys_CNT;
unsigned int Tmp;
struct bs1
{
uint8 IP;
uint8 NUM;
uint8 ADDR;
uint8 BUFF[10];
}T_485 ; //地址从 ;
struct bs2
{
uint8 TASK;
uint8 IP;
uint8 ADDR;
uint8 BUFF[10];
uint8 TIME;
}R_485 ; //地址从 ;
void UartInit(void); //9600bps@11.0592MHz
void Timer0Init(void); //10毫秒@11.0592MHz
uint8 read_addr(void);
void COM_TASK(void);
unsigned int crc16(unsigned char *ptr, unsigned char len);
/********************************************\
|* 功能: 延时 晶振为12M时 *|
|* t = 1 为 20us 然后成倍增加10us左右 *|
\********************************************/
void Delay10us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 24;
while (--i);
}
/********************************************\
|* 功能: 延时 晶振为12M时 *|
|* 延时大约 1ms *|
\********************************************/
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
/********************************************\
|* 功能: 读传感器发送的单个字节 *|
\********************************************/
unsigned char Read_SensorData(void)
{
uint16 cnt;
unsigned char i;
unsigned char buffer,tmp;
buffer = 0;
for(i=0;i<8;i++)
{
cnt=0;
while(!DQ) //检测上次低电平是否结束
{
if(++cnt >= 300)
{
break;
}
}
//延时Min=26us Max50us 跳过数据"0" 的高电平
Delay10us();
Delay10us();
Delay10us();//延时30us
//判断传感器发送数据位
tmp =0;
if(DQ)
{
tmp = 1;
}
cnt =0;
while(DQ) //等待高电平 结束
{
if(++cnt >= 200)
{
break;
}
}
buffer <<=1;
buffer |= tmp;
}
return buffer;
}
/********************************************\
|* 功能: 读传感器 *|
\********************************************/
unsigned char Read_Sensor(void)
{
unsigned char i;
//主机拉低(Min=800US Max=20Ms)
DQ = 0;
Delay1ms(); //延时2Ms
Delay1ms();
//释放总线 延时(Min=30us Max=50us)
DQ = 1;
Delay10us();//延时30us
Delay10us();
Delay10us();
//主机设为输入 判断传感器响应信号
DQ = 1;
Sensor_AnswerFlag = 0; // 传感器响应标志
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(DQ ==0)
{
Sensor_AnswerFlag = 1;//收到起始信号
Sys_CNT = 0;
//判断从机是否发出 80us 的低电平响应信号是否结束
while((!DQ))
{
if(++Sys_CNT>300) //防止进入死循环
{
Sensor_ErrorFlag = 1;
return 0;
}
}
Sys_CNT = 0;
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
while((DQ))
{
if(++Sys_CNT>300) //防止进入死循环
{
Sensor_ErrorFlag = 1;
return 0;
}
}
// 数据接收 传感器共发送40位数据
// 即5个字节 高位先送 5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和
// 校验和为:湿度高位+湿度低位+温度高位+温度低位
for(i=0;i<5;i++)
{
Sensor_Data[i] = Read_SensorData();
}
}
else
{
Sensor_AnswerFlag = 0; // 未收到传感器响应
}
return 1;
}
void main()
{
EA=0; //关中断
T_485.IP=0;
T_485.NUM=0;
T_485.ADDR=0;
R_485.TASK=0;
R_485.IP=0;
R_485.TIME=0;
UartInit();
Timer0Init(); //10毫秒@11.0592MHz
WDT_CONTR=0x2f;
Read_Sensor();
ES=1;//开串口中断
ET0=1;//开定时器0中断
EA=1; //开中断
while (1)
{
COM_TASK();
WDT_CONTR|=0x10;
}
}
//校验和计算
unsigned char Verify(unsigned char *p,unsigned char num)
{
unsigned char i,veri;
veri=0;
for(i=0;i<num;i++,p++)
veri+=*p;
return veri;
}
void Timer0Init(void) //10毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0xDC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //独立波特率发生器时钟为Fosc,即1T
BRT = 0xDC; //设定独立波特率发生器重装值
AUXR |= 0x01; //串口1选择独立波特率发生器为波特率发生器
AUXR1|= 0x80; //串口1切换到P1口
AUXR |= 0x10; //启动独立波特率发生器
IO_485=0;//设置485为接收
}
void TIME0_Server(void) interrupt 1
{
TL0 = 0x00; //设置定时初值
TH0 = 0xDC; //设置定时初值
R_485.TIME++;
TIME++;
if(TIME>1000)
{
TIME=0;
Read_Sensor();
}
}
uint8 read_addr(void)
{
uint8 i;
P1=0xff;
i=P1;
if(i&0x20)
i|=0x08;
else
i&=0x07;
i&=0x0f;
return i;
}
void CommReceive(void) interrupt 4
{
if( RI == 1 )
{
IO_485=0; //置485为接收
R_485.TIME=0;
R_485.BUFF[R_485.IP]=SBUF;
R_485.IP++;
RI=0;
}
else if(TI==1&&T_485.IP<T_485.NUM)
{
IO_485=1; //置485为发送
TI = 0;
SBUF = T_485.BUFF[T_485.IP];
T_485.IP++;
}
else if(TI==1)
{
IO_485=0; //置485为接收
TI = 0;
}
}
//接收命令处理
void COM_TASK(void)
{ uint16 i;
if(R_485.TIME>1&&R_485.IP==8&&(R_485.BUFF[0]==read_addr()||R_485.BUFF[0]==0xff)&&R_485.BUFF[1]==0x03&&R_485.BUFF[2]==0X00&&R_485.BUFF[3]==0X00//)
&&((crc16(R_485.BUFF,6)&0xff00)>>8)==R_485.BUFF[7]&&(crc16(R_485.BUFF,6)&0x00ff)==R_485.BUFF[6])
{
R_485.IP=0;
R_485.TIME=0;
T_485.IP=0;
T_485.NUM=0;
if((Verify(Sensor_Data,4)==Sensor_Data[4])&&(Sensor_AnswerFlag==1))
{
HUMI=Sensor_Data[0]*256+Sensor_Data[1];
TEMP=Sensor_Data[2]*256+Sensor_Data[3];
T_485.BUFF[0]=read_addr();
T_485.BUFF[1]=0X03;
T_485.BUFF[2]=0X04;
T_485.BUFF[3]=(TEMP&0xff00)>>8;//温度高
T_485.BUFF[4]=TEMP&0x00ff;//温度低
T_485.BUFF[5]=(HUMI&0xff00)>>8;//湿度高
T_485.BUFF[6]=HUMI&0x00ff;//湿度低
i=crc16(T_485.BUFF,7);
T_485.BUFF[7]=i&0x00ff;
T_485.BUFF[8]=(i&0xff00)>>8;
T_485.NUM=9;
IO_485=1; //置485为发送
SBUF=T_485.BUFF[0];
T_485.IP++;
}
else// if(Sensor_AnswerFlag==0||Sensor_ErrorFlag==1)
{
HUMI=1000;
TEMP=1000;
T_485.BUFF[0]=read_addr();
T_485.BUFF[1]=0X03;
T_485.BUFF[2]=0X04;
T_485.BUFF[3]=(TEMP&0xff00)>>8;//温度高
T_485.BUFF[4]=TEMP&0x00ff;//温度低
T_485.BUFF[5]=(HUMI&0xff00)>>8;//