首页 > 代码库 > 51单片机-PC数据传输 温度 距离 监控系统设计
51单片机-PC数据传输 温度 距离 监控系统设计
>_<:功能概述:
通过串口PC和单片机通信,可以询问单片机测得的温度,可以询问声呐测距的测量距离,同时把测量温度显示在数码管上。
>_<:PC部分
这里com.cpp和com.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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。