首页 > 代码库 > 51单片机-PC数据传输 温度 距离 监控系统设计

51单片机-PC数据传输 温度 距离 监控系统设计

 

>_<:功能概述:

通过串口PC和单片机通信,可以询问单片机测得的温度,可以询问声呐测距的测量距离,同时把测量温度显示在数码管上。

 

>_<:PC部分

这里com.cppcom.h是串口通信的函数封装,在主函数中:

  • 刚开始调用封装好的串口通信函数,设置打开串口COM4,波特率设置为9600,超时设置:

 

1 if(openport("com4"))2     printf("open comport success\n");3 if(setupdcb(9600))4     printf("setupDCB success\n");5 if(setuptimeout(0,0,0,0,0)) //如果所有写超时参数均为0,那么就不使用写超时6     printf("setuptimeout success\n");7 clearall();//全清

 

  • 接着循环接收控制台命令来与串口通信:这里用了串口通信函数WriteChar和ReceiveChar来与串口进行信息传送,注意这里的读写应和单片机的一致,否则就会出现错误。这里举a==5的例子说明:

    [命令5表示改变距离阈值,当输入5时,PC将向串口发送字符’5’,然后等待输入改变后的温度,当输入改变温度时,将该温度传给串口[因为我们这里的范围是0-100]所以一个char类型就能表示,将这个值发送给串口,当单片机改变好距离阈值后会返回改好的命令,所以调用ReceiveChar接收返回信息。其他类似。]
 1 while(1){ 2     scanf("%d",&a);//1表示要温度,2表示要距离,3表示距离警报关闭,4温度警报关闭,5改变距离阈值,6改变温度阈值 3     if(a==5){ 4         m_szWriteBuffer[0]=5; 5         WriteChar(m_szWriteBuffer,1); 6         printf("Please enter the num:(0-100cm) \n"); 7         scanf("%d",&a); 8         m_szWriteBuffer[0]=(BYTE)(a); 9         WriteChar(m_szWriteBuffer,1);10         ReceiveChar(m_szReceiveBuffer,20);11         printf("%s\n",m_szReceiveBuffer);12     }else if(a==6){13         m_szWriteBuffer[0]=6;14         WriteChar(m_szWriteBuffer,1);15         printf("Please enter the num:(0-100℃) \n");16         scanf("%d",&a);17         m_szWriteBuffer[0]=(BYTE)(a);18         WriteChar(m_szWriteBuffer,1);19         ReceiveChar(m_szReceiveBuffer,20);20         printf("%s\n",m_szReceiveBuffer);21     }else{22         m_szWriteBuffer[0]=(BYTE)(a+0);23         WriteChar(m_szWriteBuffer,1);24 25         ReceiveChar(m_szReceiveBuffer,20);26         printf("%s\n",m_szReceiveBuffer);27     }28 }

 

>_<:单片机部分

设备:

  •  18B20温度传感器
  •  8位数码管显示
  •  串口通信
  •  HC-SR04超声波测距仪
  •  STC89C52[11.0952MHz]
  •  蜂鸣器

连线:

  这里选用11.0592MHz的晶振,将8位7段数码管公共线接P0的8个端口,P2.3接位码,P2.2接段码;串口通信采用MAX232连接如图所示。

main函数介绍:

#初始化部分介绍:


1 unsigned int TempH,TempL,temp;2 Init_Timer0();3 UART_Init(); // 串口初始化4 Init_Timer1();5 6 ReadTemperature();//这里放置3个温度读取,防止出现初始化温度不稳定情况7 ReadTemperature();8 ReadTemperature();
  • 第2行:初始定时器:MOD |= 0x01---T0定时16位模式
  • 第3行:串口初始化:具体信息见注释
1 void UART_Init(void)2 {3     SCON = 0x50;         // 设定串行口工作方式,8位数据位,允许接收4     T2CON = 0x34;         //设置定时器2,作为波特率发生器5     RCAP2L = 0XDC;      //9600波特率的低8位6     RCAP2H = 0XFF;        //9600波特率的高8位    7     ES = 1;                 //允许串口中断8     EA = 1;                 //允许总中断9 }
  • 第6-8行: 在系统初始前先读取3次温度,防止系统初始时温度的值不正常而触发报警

#主循环介绍:

  1 while (1)      2 {  3     if(isInclude || isAbove){  4         //LED_Show(2);  5         //if(freq==200);  6         SPK=!SPK;  7     }  8     if(uart_flag==1)   //接收到  9     { 10         ES=0;       //关串口中断 11         if(come==1){//接收并改变距离阈值 12             maxJuLi=(unsigned int)a; 13             come=0; 14             UART_Send_Byte(O); 15             UART_Send_Byte(K); 16             UART_Send_Byte(#); 17             UART_Send_Byte(\n); 18         }else if(come==2){//接收并改变温度阈值 19             maxWenDu=(unsigned int)a; 20             come=0; 21             UART_Send_Byte(O); 22             UART_Send_Byte(K); 23             UART_Send_Byte(#); 24             UART_Send_Byte(\n); 25         }else//其他操作 26         switch(a){//要温度 27         case 1: 28             for(i=0;i<17;i++) 29             { 30                 UART_Send_Byte(SendData[i]);//将数据发给串口 31             } 32             UART_Send_Byte(\n); 33             break; 34         case 2://要距离 35             for(i=0;i<16;i++) 36             { 37                 UART_Send_Byte(SendData1[i]);//将数据发给串口 38             } 39             UART_Send_Byte(\n); 40             break; 41         case 3: 42             if(isInclude){ 43                 isInclude=0; 44                 UART_Send_Byte(c); 45                 UART_Send_Byte(l); 46                 UART_Send_Byte(o); 47                 UART_Send_Byte(s); 48                 UART_Send_Byte(e); 49                 UART_Send_Byte(#); 50                 UART_Send_Byte(\n); 51             }else{ 52                 UART_Send_Byte(n); 53                 UART_Send_Byte(o); 54                 UART_Send_Byte( ); 55                 UART_Send_Byte(p); 56                 UART_Send_Byte(e); 57                 UART_Send_Byte(r); 58                 UART_Send_Byte(s); 59                 UART_Send_Byte(o); 60                 UART_Send_Byte(n); 61                 UART_Send_Byte(#); 62                 UART_Send_Byte(\n); 63             } 64             break; 65         case 4: 66             if(isAbove){ 67                 isAbove=0; 68                 UART_Send_Byte(c); 69                 UART_Send_Byte(l); 70                 UART_Send_Byte(o); 71                 UART_Send_Byte(s); 72                 UART_Send_Byte(e); 73                 UART_Send_Byte(#); 74                 UART_Send_Byte(\n); 75             }else{ 76                 UART_Send_Byte(n); 77                 UART_Send_Byte(o); 78                 UART_Send_Byte( ); 79                 UART_Send_Byte(f); 80                 UART_Send_Byte(i); 81                 UART_Send_Byte(r); 82                 UART_Send_Byte(e); 83                 UART_Send_Byte(#); 84                 UART_Send_Byte(\n); 85             } 86             break; 87         case 5: 88             come=1; 89             break; 90         case 6: 91             come=2; 92             break; 93         default://错误操作 94             for(i=0;i<16;i++) 95             { 96                 UART_Send_Byte(SendData2[i]);//将数据发给串口 97             } 98             UART_Send_Byte(\n); 99             break;100         }101         ES=1;    //允许串口中断102         uart_flag=0;  //中断标志位置0103     }104     else if(ReadTempFlag==1)//通过定时器,每隔1200ms扫描一次温度105     {106         ReadTempFlag=0;107         temp=ReadTemperature();108         if(temp&0x8000)//第一位为1就表示为负要取反加1第一位弄个负号109         {110             TempData[0]=0x40;//负号标志111             temp=~temp;  // 取反加1112             temp +=1;113         }114         else115             TempData[0]=0;//其他情况就该显示负号的不显示116         117         TempH=temp>>4;//去除低四位118         TempL=temp&0x0F;//获取温度低四位119         TempL=TempL*6/10;//小数近似处理!120 121         if(TempH>0 && TempH>maxWenDu)isAbove=1;//界限判断122 123         if(TempH/100==0)//百位数据124             TempData[1]=0;125         else126             TempData[1]=DuanMa[TempH/100]; //百位温度127         if((TempH%100)/10==0)//十位温度128             TempData[2]=0;129         else130             TempData[2]=DuanMa[(TempH%100)/10];131         TempData[3]=DuanMa[(TempH%100)%10]|0x80; //个位温度,带小数点132         TempData[4]=DuanMa[TempL];133         TempData[6]=0x39;         //显示C符号134 135         136         SendData[11]=(unsigned char)(TempH/100+0);137         SendData[12]=(unsigned char)(TempH%100/10+0);138         SendData[13]=(unsigned char)(TempH%100%10+0);139         SendData[14]=.;140         SendData[15]=(unsigned char)(TempL+0);141     }else if(ReadTempFlag==2){142         ReadTempFlag=0;143         StartModule();        //测距144         while(!RX);            //当RX为零时等待145         TR1=1;                //开启计数146         while(RX);            //当RX为1计数并等待147         TR1=0;                //关闭计数148         Conut();            //计算149     }150 }
  • 第3-7行:当温度在阈值外或者距离在阈值内时就响铃
  • 第8-103行:当串口通信发生串口中断时,会把uart_flag标志位置1,然后主程序就会处理PC端传送过来的数据,这里采用串口中断来检测是否收到PC发来的数据的:
1 void UART(void) interrupt 42 {3     if(RI)                   //检测接收完成标志位置14     {5         RI=0;            //清零接收完成标志位6         a=SBUF;            //读取接收到的数据7         uart_flag = 1;    //中断标志位置18     }9 }
  • 第11-25行:这里是要修改温度或者距离的阈值时用到的特殊处理,因为当收到修改阈值的命令之后还要等待要改成的值,为了区别这个值和命令值,于是用come标记是否是要修改阈值,如果不是修改阈值,就正常判断命令,否则就做相应的阈值修改。
  • 第27-33行:将温度发送给PC,最后要发送一个换行,当做结束标志位[这是和PC端的接收程序有关,2个通信的协议要一致],其他类似,不做详解。
  • 第41-86行:关闭报警命令,如果正在报警,就关闭报警,返回给电脑已经关闭的信息;如果没有报警,就回复电脑相应信息。
  • 第87-92行:要修改阈值,就把come置成相应的值,等待接受要修改值,与第11-25行相对应
  • 第104-141行:如果没有电脑命令传过来就进行温度采集和距离测试:
 1 void Timer0_isr(void) interrupt 1  2 { 3     static unsigned int num; 4     TH0=(65536-2000)/256;//重新赋值 2ms 5     TL0=(65536-2000)%256; 6      7     Display(0,8);  // 调用数码管扫描 8     num++; 9     if(num==100){10         ReadTempFlag=1;//读温度标志位置211     }else if(num==150)      12     {13         num=0;14         ReadTempFlag=2;//读距离标志位置1 15     }16 }
  •  第143-147行:测量时间差[用定时器TH1,TL1]
  •  第148行:计算超声波测距的距离[根据上面计算的声波来回的时差]
 1 void Conut(void) 2 { 3     time=TH1*256+TL1; 4     TH1=0; 5     TL1=0; 6     S=(time*1.87)/100;     //算出来是CM 7     if(flag==1)            //超出测量 8     { 9         flag=0;10         //printf("-----\n"); 11     }12     if(S<maxJuLi)isInclude=1;//界限判断13     //.......14 }

  

全部资源连接:http://pan.baidu.com/s/1ntukZ8l