打印
[程序源码]

kafeng初识嵌入式 4 - 串口传送温度

[复制链接]
1061|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kafeng|  楼主 | 2015-8-29 18:52 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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


相关帖子

沙发
IversonCar| | 2015-8-30 08:41 | 只看该作者
这是模拟的吧,也够经济的

使用特权

评论回复
板凳
跟屁虫| | 2015-8-30 10:29 | 只看该作者
楼主有没有做真实的电路呢

使用特权

评论回复
地板
dirtwillfly| | 2015-8-30 16:46 | 只看该作者
感谢分享

使用特权

评论回复
5
kafeng|  楼主 | 2015-8-31 12:51 | 只看该作者
跟屁虫 发表于 2015-8-30 10:29
楼主有没有做真实的电路呢

用面包板接出来检验过的,:lol

使用特权

评论回复
6
kafeng|  楼主 | 2015-8-31 12:54 | 只看该作者
IversonCar 发表于 2015-8-30 08:41
这是模拟的吧,也够经济的

模拟的单总线~:lol

使用特权

评论回复
7
kafeng|  楼主 | 2015-8-31 12:55 | 只看该作者
本帖最后由 kafeng 于 2015-8-31 12:56 编辑

发帖又忘记设置分数了,那就结贴大家分了吧:lol

使用特权

评论回复
8
小狗爱吃骨头| | 2015-8-31 20:50 | 只看该作者
不知道ds18b20的精度能达到多少

使用特权

评论回复
9
kafeng|  楼主 | 2015-8-31 21:31 | 只看该作者
小狗爱吃骨头 发表于 2015-8-31 20:50
不知道ds18b20的精度能达到多少

手册说的是,在 -10’C~+85’C之间,精度是正负0.5’C。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

54

帖子

3

粉丝