本帖最后由 kafeng 于 2015-8-29 19:14 编辑
一个简单的STC89C52RC由串口接收PC的指令,通过DS18B20获取温度,然后经串口传递给PC。
#include<reg52.h>
#include<stdio.h>
#include<string.h>
unsigned char order=9; //指令编号初始值
unsigned char code text0[28]={"\r\n\rMCU 1:\r\nSystem Online!\r\n\r"}; //固定字符串
unsigned char code text1[28]={"\r\n\rMCU 1:\r\nFormat Error! \r\n\r"}; //固定字符串
unsigned char r_flag=0; //接收数据标志位,有数据置1
unsigned char success_flag=0;//接收数据标志位,接收到格式正确指令置1
unsigned char s_flag=0; //发送数据标志位,指令指示的单片机为本机置1
unsigned char receive[4]; //完整指令存储数组,0~3位,第0和第3位为固定帧头和帧尾,第1位为单片机选择位,第2位为指令编号
sbit DQ=P2^0; // DS18B20 连线端口
float temp;//十进制有符号温度
void delay(unsigned int i) //DS18B20延时函数
{
while(i--);
}
void InitDS(void) //DS18B20初始化函数
{
unsigned char x=0;
DQ = 1; //单片机将DQ复位
delay(8); //稍做延时
DQ = 0; //单片机将DQ置低电平
delay(80); //精确延时大于480us
DQ = 1; //单片机将DQ置高电平
delay(10);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay(5);
}
unsigned char ReadC(void) // DS18B20读一个字节函数
{
unsigned char ir=0;
unsigned char byte=0;
for (ir=8;ir>0;ir--)
{
DQ = 0; //单片机将DQ置低电平
byte>>=1;
DQ = 1; //单片机将DQ置高电平
if(DQ)
byte|=0x80;
delay(5);
}
return(byte);
}
void WriteC(unsigned char byte) //DS18B20写一个字节函数
{
unsigned char iw=0;
for (iw=8; iw>0; iw--)
{
DQ = 0;
DQ = byte&0x01;
delay(5);
DQ = 1;
byte>>=1;
}
delay(5);
}
float ReadT(void) //读取温度操作主函数
{
unsigned char a=0;
unsigned char b=0;
int c=0;
float t;
InitDS();
WriteC(0xcc); //不读取器件序列号
WriteC(0x44); //启动温度转换
while(!DQ); //等待转换完成
InitDS();
WriteC(0xcc); //不读取器件序列号
WriteC(0xbe); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadC(); //读温度低八位,其中低四位为小数部分
b=ReadC(); //读温度高八位
c=b;
c<<=8;
c=c|a;
t=c*0.0625;
return t; //返回十进制有符号温度值
}
void Send(unsigned char *a)//字符发送函数
{
unsigned char i;
ES=0; //关闭串口中断响应,注意:此举将导致发送过程中无法接收,全双工变半双工!解决办法需探究
for(i=0;i<28;i++)
{
SBUF=*(a+i);
while(!TI) ; //等待TI置位,即数据发送完成
TI=0; //对TI软件清零
}
ES=1; //打开串口中断响应
}
void main()
{
SCON=0x50; //设置串口工作于方式1,TI位清0
PCON=0x00; //PCON.7是SMOD位,SMOD=0
TMOD=0x20; //选择定时器T1工作于方式2
TH1=0xe8; //设置波特率为1200,晶振频率11.0592Mhz
TL1=0xe8;
TR1=1; //开启定时器T1
ES=1;
EA=1;
temp=ReadT();//初次读取温度
Send(text0); //发送上线信号,直接连双机需取消本信息,否则会有冲突
while(1)
{
if(r_flag==1) //接收到格式正确指令
{
r_flag=0; //取消标志位
if(success_flag==1&&receive[1]==0x31) //判断指令是否针对本机
{
order=receive[2]; //获取指令编号
TI=1;
printf("\n\rMCU 1:\nGet Order %c!\r",order); //返回接收信息
TI=0;
success_flag=0; //取消标志位
s_flag=1; //接收到针对本机的正确指令,标志位置1
}
else if(success_flag==1) //接收到不针对本机的正确指令,不进行任何操作
{
success_flag=0; //取消标志位
}
else
{
Send(text1); //接收到错误格式信息,进行反馈
}
}
if(s_flag==1) //接收到针对本机的指令
{
s_flag=0; //取消标志位
switch(order)
{
case 0x30://指令0,查询单片机是否正常连接
{
Send(text0); //发送上线信息
}break;
case 0x31: //指令1,获取温度
{
temp=ReadT();//读取温度
TI=1;
printf("\n\rMCU 1:\nTemperature is:%5.1f\n\r",temp); //发送温度
TI=0;
}break;
default: //其他,错误指令
{
TI=1;
printf("\n\rMCU 1:\nWrong Order!\n\r");
TI=0;
}
}
}
}
}
void randd(void)interrupt 4
{
static unsigned char count=0;//串口接收帧数的计数变量
if(RI==1)//如果收到新数据
{
RI=0; //清除标志.
receive[count]=SBUF; //接收指令
if(count==0&&receive[count]==0x23)//判断指令第0位是否为要求的'#'
{
count=1;
}
else if(count==1)//接收指令第1位
{
count=2;
}
else if(count==2)//接收指令第2位
{
count=3;
}
else if(count==3&&receive[count]==0x24) //判断指令第3位是否为要求的'$'
{
count=0;
success_flag=1;//接收到格式正确指令
r_flag=1; //接收到数据
}
else
{
count=0;//接收到错误格式信息
r_flag=1; //接收到数据
}
}
}
编号:WY - 7
|