×
单片机 > 单片机程序设计 > 详情

局域网控制系统-下位机-单片机

发布时间:2020-06-06 发布时间:
|

  1 /*-----------------------------------

  2            多功能下位机

  3     STC89C52RC   11.0592MHz

  4 

  5 -----------------------------------*/

  6 #include

  7 #include 

  8 

  9 char code huanhang[3]={0x0d,0x0a,0};   //  "\r\n"

 10 //-----------------普通输出端口---------------//

 11 sbit LED0=P1^0;

 12 sbit LED1=P1^1;

 13 sbit LED2=P1^2;

 14 sbit jdq_00=P1^3;

 15 sbit fmq_00=P2^5;

 16 

 17 /**********DS18B20***********/

 18 bit Temp_Symbol=0;

 19 //温度传感_0---------

 20 sbit DQ=P2^6;

 21 //------------------串口通信协议-----------------//

 22 /*

 23     客户端数据包格式解释(长度恒为15):

 24     例如:A01_fmq_01Off___#

 25     A--------数据包的开始标记(可以为A到Z)

 26     01-----设备代号

 27     fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部

 28     #---------数据包的结束标记

 29 

 30     服务器端数据包格式解释(长度恒为15):

 31     例如:A02_SenT010250#

 32     A--------数据包的开始标记(可以为A到Z)

 33     02-----设备代号

 34     SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部

 35     #---------数据包的结束标记

 36 */

 37 char buf_string[16];  //定义数据包长度为15个字符

 38 #define deviceID_1Bit '0'                //用于串口通信时,定义本地设备ID的第1位

 39 #define deviceID_2Bit '2'                //用于串口通信时,定义本地设备ID的第2位

 40 #define datapackage_headflag 'A'        //用于串口通信时,定义数据包头部的验证标记

 41 

 42 char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','S','e','n','T','_','_','_','_','_','_','#'};

 43 char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','B','e','a','t','_','_','_','_','_','_','#'};

 44 //----------------------------------------------//

 45 

 46 /**************************

 47         辅助函数

 48 ***************************/

 49 //改变要发送的DS18B20数据包

 50 void Change_DataPackage_DS18B20(int DS18B20_Value)

 51 {

 52     if(Temp_Symbol)

 53     {

 54         DataPackage_DS18B20[10] = '-'; 

 55     }

 56     else

 57     {

 58         DataPackage_DS18B20[10] = '0'; 

 59     }              

 60     DataPackage_DS18B20[11] = 0x30+DS18B20_Value % 10000 / 1000;     

 61     DataPackage_DS18B20[12] = 0x30+DS18B20_Value % 1000 / 100;       

 62     DataPackage_DS18B20[13] = 0x30+DS18B20_Value % 100 / 10;  

 63 }

 64 /********************************

 65             DS18B20

 66     若没有效果,意味着延时可能有问题

 67     测温范围 -55℃~+125℃

 68 

 69           单线通信接口

 70     1)边沿=触发    

 71     2)电平持续时间=信息

 72     3)一字节的电平组合=指令

 73 ********************************/

 74 //延时------

 75 void delay_DS18B20(unsigned int t)

 76 {

 77   for (;t>0;t--);

 78 }

 79 //复位,使得从设备可以接收指令-----------

 80 void Reset_DS18B20()

 81 {

 82     char presence=1;

 83     while(presence)

 84     {

 85         while(presence)

 86         {    

 87             DQ=1;_nop_();_nop_();//从高拉倒低

 88             DQ=0;                                       

 89             delay_DS18B20(50);           //550 us

 90             DQ=1;                                        

 91             delay_DS18B20(6);            //66 us

 92             presence=DQ;         //presence=0 复位成功,继续下一步

 93         } 

 94         delay_DS18B20(45);            //延时500 us

 95         presence=~DQ;         

 96     }

 97     DQ=1;                   //拉高电平

 98 }

 99 //写DS一个字节数据----------

100 void WriteByte_DS18B20(unsigned char val)

101 { 

102     unsigned char i;

103     for(i=8;i>0;i--)

104     {

105         DQ=1;_nop_();_nop_();                  //从高拉倒低

106         DQ=0;_nop_();_nop_();_nop_();_nop_();  //5 us

107         DQ=val&0x01;                           //最低位移出

108         delay_DS18B20(6);                      //66 us

109         val=val/2;                             //右移1位

110     }

111     DQ=1;

112     delay_DS18B20(1);

113 }

114 //读DS一个字节数据---------

115 unsigned char ReadByte_DS18B20()

116 {

117     unsigned char i;

118     unsigned char byte=0;

119     for(i=8;i>0;i--)

120     {

121         DQ=1;_nop_();_nop_();

122         byte>>=1;

123         DQ=0;_nop_();_nop_();_nop_();_nop_();         //4 us

124         DQ=1;_nop_();_nop_();_nop_();_nop_();         //4 us

125         if(DQ)byte|=0x80;

126         delay_DS18B20(6);                            //66 us

127     }

128     DQ=1;

129     return(byte);

130 }

131 //让DS18B20测量一次温度,并将测量结果存放在其内部RAM----------

132 void  MeasureTemp_DS18B20()

133 {

134     Reset_DS18B20();

135     delay_DS18B20(200);

136     WriteByte_DS18B20(0xcc);        //发送无条件选中命令,选中总线上仅有的DS18B20从设备         

137     WriteByte_DS18B20(0x44);        //温度转换命令

138    

139 }

140 //向DS18B20请求读取温度值--------------

141 void  ReadTemperature_DS18B20()

142 {    

143     Reset_DS18B20();

144     delay_DS18B20(1);

145     WriteByte_DS18B20(0xcc);     //发送无条件选中命令,选中总线上仅有的DS18B20从设备

146     WriteByte_DS18B20(0xbe);     //发送读取温度命令

147 }

148 //获取并返回DS18B20内部温度测量值--------

149 int GetTemperature_DS18B20()

150 {

151     int temp=0;

152     unsigned char temperature_H,temperature_L;     //需要连续读取2个字节数据并进行处理,才能得出一次温度值

153     MeasureTemp_DS18B20();                 //先写入转换命令

154     ReadTemperature_DS18B20();            //然后等待转换完后发送读取温度命令

155     temperature_L=ReadByte_DS18B20();        //读取温度值共16位,先读低字节

156     temperature_H=ReadByte_DS18B20();        //再读高字节

157     temp=temperature_H;

158     temp<<=8;

159     temp|=temperature_L;

160     if(temp<0)                //当温度值为负数(高5位为符号位)

161       {        

162            temp=~temp;

163         temp=temp+1;

164         temp=0.0625*temp*100+0.5;    //temp*100 意味着取2位小数,  +0.5 意味着四舍五入

165         Temp_Symbol=1;

166       }

167      else            //当温度值为正数

168       {            

169         temp=0.0625*temp*100+0.5;    

170         Temp_Symbol=0; 

171     }               

172     return temp;

173 }

174 /*******************************

175             串口通信

176     MCU:89C52RC        11.0592MHz

177 

178 //11.0592MHz 0xd0 1200bps

179 //12MHz 0xcc 1200bps

180 //11.0592MHz 0xfa 9600bps

181 //0xf4 11.0592MHz  0xf3 12MHz 4800bps

182 //均在SMOD=1的情况下(波特率倍增模式)

183 *******************************/

184 //串口发送函数

185 void PutString(unsigned char *TXStr)  

186 {                

187     ES=0;     

188      while(*TXStr!=0) 

189     {                      

190         SBUF=*TXStr;

191         while(TI==0);

192         TI=0;    

193         TXStr++;

194     }

195     ES=1; 

196 }                                                     

197 //串口接收函数

198 bit ReceiveString()    

199 {

200     char * RecStr=buf_string;

201     char num=0;

202     unsigned char count=0;

203     loop:    

204     *RecStr=SBUF;

205     count=0;

206     RI=0;    

207     if(num<14)  //数据包长度为15个字符,尝试连续接收15个字符

208     {

209         num++;

210         RecStr++;    

211         while(!RI)

212         {

213             count++;

214             if(count>130)return 0;    //接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现"数据包被分割",默认count=130

215         }

216         goto loop;

217     }

218     return 1;

219 }

220 //定时器1用作波特率发生器

221 void Init_USART()  

222 {

223     SCON=0x50;  //串口方式1,使能接收

224     TMOD|=0x20;  //定时器1工作方式2(8位自动重装初值)

225     TMOD&=~0x10;

226     TH1=0xfa;   //9600bps

227     TL1=0xfa;  

228     PCON|=0x80;  //SMOD=1

229     TR1=1;

230     TI=0;

231     RI=0;

232     //PS=1;   //提高串口中断优先级

233     ES=1;  //开启串口中断使能

234 }

235 //比较指令头部

236 bit CompareCMD_head(char CMD_head[])    

237 {

238     unsigned char CharNum;

239     for(CharNum=0;CharNum<4;CharNum++)  //指令长度为10个字符

240     {

241         if(!(buf_string[CharNum+4]==CMD_head[CharNum]))

242         {

243             return 0;  //指令头部匹配失败

244         }

245     }

246     return 1;        //指令头部匹配成功

247 }

248 //比较指令尾部(start:从哪里开始比较,quality:比较多少个字符,CMD_tail[]:要比较的字符串)

249 bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[]) 

250 {

251     unsigned char CharNum;

252     for(CharNum=0;CharNum

253     {

254         if(!(buf_string[start+CharNum]==CMD_tail[CharNum]))

255         {

256             return 0; 

257         }

258     }

259     return 1;

260 }

261 //处理串口接收数据包函数(成功处理数据包则返回1,否则返回0)

262 bit Deal_UART_RecData()   

263 {

264     //PutString(buf_string);

265     if(buf_string[0]==datapackage_headflag&&buf_string[14]=='#')  //进行数据包头尾标记验证

266     {        

267         switch(buf_string[1])        //识别发送者ID的第1位数字

268         {

269             case '0':

270                 switch(buf_string[2])        //识别发送者ID的第2位数字

271                 {

272                     case '3':

273                         if(CompareCMD_head("Ligt"))    //判断指令头部是否为"Ligt"

274                         {

275                             //下面是指令尾部分析

276                             switch(buf_string[8])

277                             {

278                                 case '0':

279                                     switch(buf_string[9])

280                                     {

281                                         case '0':            

282                                             if(CompareCMD_tail(10,3,"Off"))       //A03_Ligt01Off_#

283                                             {

284                                                 LED0=1;

285                                                 return 1;

286                                             }

287                                             if(CompareCMD_tail(10,3,"On_"))

288                                             {

289                                                 LED0=0;

290                                                 return 1;

291                                             }

292                                             return 0;

293                                         case '1':

294                                             if(CompareCMD_tail(10,3,"Off"))       //A03_Ligt01Off_#

295                                             {

296                                                 LED1=1;

297                                                 return 1;

298                                             }

299                                             if(CompareCMD_tail(10,3,"On_"))

300                                             {

301                                                 LED1=0;

302                                                 return 1;

303                                             }

304                                             return 0;

305                                         case '2':

306                                             if(CompareCMD_tail(10,3,"Off"))       //A03_Ligt01Off_#

307                                             {

308                                                 LED2=1;

309                                                 return 1;

310                                             }

311                                             if(CompareCMD_tail(10,3,"On_"))

312                                             {

313                                                 LED2=0;

314                                                 return 1;

315                                             }

316                                             return 0;

317                                         default:

318                                             return 0;

319                                     }                                                    

320                                 default:

321                                     return 0;

322                             }            

323                         }

324                         if(CompareCMD_head("SenT"))  

325                         {

326                             //下面是指令尾部分析

327                             DataPackage_DS18B20[8]=buf_string[8];

328                             DataPackage_DS18B20[9]=buf_string[9];

329                             switch(buf_string[8])    

330                             {

331                                 case '0':

332                                     switch(buf_string[9])    

333                                     {

334                                         case '0':    

335                                             Change_DataPackage_DS18B20(GetTemperature_DS18B20());

336                                             PutString(DataPackage_DS18B20);

337                                             return 1;

338                                         default:

339                                             return 0;

340                                     }

341                                 default:

342                                     return 0;

343                             }    

344                             

345                         }

346                         if(CompareCMD_head("jdq_"))  

347                         {

348                             //下面是指令尾部分析

349                             switch(buf_string[8])    

350                             {

351                                 case '0':

352                                     switch(buf_string[9])    

353                                     {

354                                         case '0':    

355                                             if(CompareCMD_tail(10,3,"Off"))

356                                             {

357                                                 jdq_00=1;

358                                                 return 1;

359                                             }

360                                             if(CompareCMD_tail(10,3,"On_"))

361                                             {

362                                                 jdq_00=0;

363                                                 return 1;

364                                             }

365                                             

366                                             return 0;

367                                         default:

368                                             return 0;

369                                     }

370                                 default:

371                                     return 0;

372                             }

373                         }

374                         if(CompareCMD_head("fmq_"))  

375                         {

376                             //下面是指令尾部分析

377                             switch(buf_string[8])    

378                             {

379                                 case '0':

380                                     switch(buf_string[9])    

381                                     {

382                                         case '0':    

383                                             if(CompareCMD_tail(10,3,"Off"))

384                                             {

385                                                 fmq_00=1;

386                                                 return 1;

387                                             }

388                                             if(CompareCMD_tail(10,3,"On_"))

389                                             {

390                                                 fmq_00=0;

391                                                 return 1;

392                                             }

393                                             

394                                             return 0;

395                                         default:

396                                             return 0;

397                                     }

398                                 default:

399                                     return 0;

400                             }

401                         }

402                         if(CompareCMD_head("Try!"))  

403                         {

404                             PutString(HeartBeat);

405                             return 1;

406                         }

407                         

408                         return 0;

409                     

410                     default:

411                         return 0;

412                 }

413             default:

414                 return 0;

415         }

416     }

417     return 0;

418 }

419 /************************

420         中断函数

421 ************************/

422 //串口中断服务函数-----------

423 void USART() interrupt 4   //标志位TI和RI需要手动复位,TI和RI置位共用一个中断入口

424 {

425     if(ReceiveString())    

426     {

427         //数据包长度正确则执行以下代码

428         Deal_UART_RecData();   

429     }

430     else

431     {

432         //数据包长度错误则执行以下代码

433         //LED1=~LED1;                

434     }

435     RI=0;  //接收并处理一次数据后把接收中断标志清除一下,拒绝响应在中断接收忙的时候发来的请求

436 }

437 /***************************

438         主函数

439 ***************************/

440 //空格20H,回车0DH,'\n'对应ASCLL码:0x0a

441 void main()

442 {    

443     EA=1;

444     Init_USART();

445     while(1)

446     {

447 

448     }

449 }      


硬件电路要求不高,准备好一个51最小系统,外加一些自己想要的外围设备,当然最重要的是准备一个透传模块(ESP8266),其电路接法如下:

这个模块具体有什么用呢?

简单来说就是这个模块可以跟单片机进行串口通信,也可以跟其它终端进行socket通信,那么我们现在就是利用其跟手机进行socket通信,接收手机的数据,再把数据发送到单片机,实现手机控制单片机。而手机是以客户端的形式与透传模块ESP8266进行连接,因此我们需要对ESP8266进行简单的配置,才能保证手机能跟ESP8266进行连接,具体做法请自行百度。

请另外观看项目的2个部分:

1)局域网控制系统-上位机-Android手机

2)局域网控制系统-上位机-PC机

让我们从项目,从代码中可以更快地提高自己!



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多