物联网综合练习之单片机TCP服务器


来源:http://blog.chinaunix.net/uid-29270124-id-4681894.html  

点击“阅读原文”进入

/**********************************************************************
PROJECT:     wifi遥控小车
HARDWARE:    STC89C52RC单机, L239D直流电机驱动器, ESP8266安信可wifi模块
SOFTWARE:    Eclipse安卓开发环境
AUTHOR:       DDDDD
DATE:       2014-12-5
**************************************************************************/


本文介绍,如何利用wifi模块在单片机上建立TCP服务器,从而用android客户端来操作单片机。wifi模块采用安信可ESP8266,价格低,性能稳定。通过串口传输与单片机通信,波特率115200

1、STC89C52RC单片机波特率设置,由于波特率为115200,这个传输速率已经非常高,必须用T2定时器作为波特率发生器


    波特率:串口每秒钟发送或者接收的位数,
    设发送一位需要的时间是T,则波特率buad=1/T
    串口发送条件:向SBUF写入数据,则立马回发送
                 发送完成后 TI 由硬件置1,需要手动清0
    串口接受收件:REN = 1,允许接收
                 RI = 0;
    接收完毕后RI会由硬件置1,需要手动清零


串口初始化配置: 

  1. void serial_init()

  2. {

  3.     EA = 0;    //关闭所有中断

  4.     SCON = 0x40  //工作方式 1, 8位异步串行收发,波特率由定时器 1 控制

  5.     PCON = 0;

  6.     RCAP2H = 0xff;

  7.     RCAP2L = 0xfd; //方式1和方式3的波特率=fosc/(32-(65535-(RCAP2H,RCAP2L))

  8.     TH2=0xFF;

  9.     TL2=0xFD;      //设置波特率为115200

  10.     T2CON=0x34;   //将定时器2设置为波特率发生器(接收和发送都用Timer2) 

  11.     ET2 = 0;    //关闭定时器1中断

  12.     TI = 0;

  13.     RI = 0;

  14.     REN = 1;    //允许接收

  15.     ES = 1;   //开启串口中断

  16.     EA = 1;   //开启总中断

  17.     TR2 = 1;   //开启定时器 2

  18. }

2、直流电机驱动芯片L293D
     
  L293D是一款典型的直流电机控制芯片,可以很轻松的控制电机的正反转。IN1、IN2、IN3、IN4是输入引脚,对应的输出引脚是OUT1、OUT2、OUT3、OUT4。EN1是1、2号引脚的是能控制端,EN2是3、4号引脚的是能控制端,高电平是能。当输入为1时,输出为0;当输入为0时,输出为1。


3、单片机供电部分:


   采用两节3.7v锂电池串联供电,7805输出5v稳压给单片机供电,直流电机直接由7.4v供电。必要说明:单片机和直流电机分别用俩组电池供电,因为直流电机在启动时会将电池电压拉低,如果用同一组电池供电,单片机会复位。 
      


4、ESP8266WIFI模块
   模块已经集成一些指令,采用串口通讯将指令发送过去,模块就会有相应的响应,ESP8266指令集: 


  1. 9、AT+CWMODE=3  设置为模式3

  2.         OK

  3. 10、AT+RST   重启生效

  4. 11、AT+CIPMUX=1  开启多链接

  5.         OK

  6. 12、AT+CIPSERVER=1,8765 配置为TCP服务器,端口号8765

  7.         OK

  8. 13、AT+CIPSTO=600 设置超时时间

  9.         OK

  10. 以上是需要发送的指令,当上述操作完成之后,就可以等待android客户端的命令了,下面是模块收到一条指令的格式

  11. 14、+IPD,7:hello
        OK     收到数据hello

   必要说明:给模块发送指令时,必须以回车符作为结尾,否则模块无响应。因此在串口发送数据的时候,采用十六进制发送。
   当模块收到指令时,会将指令通过串口发送给MCU,发送的格式
            

  1.         +IPD,7:hello
            OK   

    这代表收到服务器的数据hello    


5、源代码
   car.h

  1. #include <reg52.h>

  2. sbit zq1 = P0^0;

  3. sbit zq2 = P0^1;

  4. sbit yq1 = P0^2;

  5. sbit yq2 = P0^3;

  6. sbit zh1 = P0^4;

  7. sbit zh2 = P0^5;

  8. sbit yh1 = P0^6;

  9. sbit yh2 = P0^7;

  10. #define FAN_ZHUAN {zq1 = 1; zq2 = 0; yq1 = 1; yq2 = 0; zh1 = 1; zh2 = 0; yh1 = 1; yh2 = 0;}

  11. #define ZHENG_ZHUAN {zq1 = 0; zq2 = 1; yq1 = 0; yq2 = 1; zh1 = 0; zh2 = 1; yh1 = 0; yh2 = 1;}

  12. #define ZUO_ZHUAN {zq1 = 0; zq2 = 0; yq1 = 0; yq2 = 1; zh1 = 0; zh2 = 0; yh1 = 0; yh2 = 1;}

  13. #define YOU_ZHUAN {zq1 = 0; zq2 = 1; yq1 = 0; yq2 = 0; zh1 = 0; zh2 = 1; yh1 = 0; yh2 = 0;}

  14. #define TING_CHE     {zq1 = 0; zq2 = 0; yq1 = 0; yq2 = 0; zh1 = 0; zh2 = 0; yh1 = 0; yh2 = 0;}

   main.c

  1. /****************************************************

  2. 串口程序serial UART

  3. 波特率:串口每秒钟发送或者接收的位数,

  4. 设发送一位需要的时间是T,则波特率buad=1/T

  5. 串口发送条件:向SBUF写入数据,则立马回发送

  6. 发送完成后 TI 由硬件置1,需要手动清0

  7. 串口接受收件:REN = 1,允许接收

  8.        RI = 0;

  9. 接收完毕后RI会由硬件置1,需要手动清零

  10. *********************************************************/

  11. #include <car.h>

  12. #include <intrins.h>

  13. #define uchar unsigned char

  14. #define uint unsigned int

  15. sbit dula=P2^0;        //段选信号的锁存器控制

  16. sbit wela=P2^1;        //位选信号的锁存器控制

  17. sbit cs88=P2^2;        //点阵管的锁存器控制 cs88=0;//关点阵管

  18. sbit DS1302=P2^7;      //定义DS1302时钟使能端,用于HJ-C52实验板复位,与本实验无关

  19. sbit SD=P2^6;         //定义SD卡使能端,用于HJ-C52实验板复位,与本实验无关

  20. void cmg88()          //关数码管,点阵函数 cmg88();//关数码管,点阵函数

  21.     dula=1; 

  22.     P0=0x00;

  23.     dula=0;

  24.     cs88=0x00;

  25.     P0=0x00;

  26.     cs88=1;

  27. }

  28. sbit LED6 = P1^6;

  29. sbit LED5 = P1^5;

  30. sbit LED4 = P1^4;

  31. sbit LED0 = P1^0;

  32. uchar buf;

  33. uchar idata tcp_buf[55];

  34. uchar tcp_flag = 0;

  35. uchar rcv_flag = 0;

  36. uchar count = 0;

  37. uchar cnt = 0;

  38. extern void delay_3s();

  39. extern void delay_ms();

  40. extern void delay_10ms();

  41. extern void delay_s();

  42. extern void delay_10s();

  43. extern void lcd_1602_init();

  44. extern void lcd_1602_write_char(uchar x, uchar y, uchar *ch);

  45. extern void lcd_1602_write_string(uchar x, uchar y, uchar *string);

  46. extern int lcd_1602_busy();

  47. extern void lcd_1602_write_cmd(uchar cmd);

  48. extern void lcd_1602_write_data(uchar dat);

  49. extern void delay();

  50. void serial_init();

  51. unsigned char code AT_RST[8] = {0x41, 0x54, 0x2B, 0x52, 0x53, 0x54, 0x0D, 0x0A };     //AT+RST 复位

  52. unsigned char code AT_CWMOD2E[13] = {0x41, 0x54, 0x2B, 0x43, 0x57, 0x4D, 0x4F, 0x44, 0x45, 0x3D, 0x32, 0x0D, 0x0A}; //AT+CWMODE=2 设置为AP模式

  53. unsigned char code AT_CIPSTART[40] = {0x41, 0x54, 0x2B, 0x43, 0x49, 0x50, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3D, 0x22, 

  54.                                  0x54, 0x43, 0x50, 0x22, 0x2C, 0x22, 0x31, 0x39, 0x32, 0x2E, 0x31, 0x36, 0x38, 

  55.                                  0x2E, 0x34, 0x2E, 0x31, 0x30, 0x30, 0x22, 0x2C, 0x38, 0x37, 0x36, 0x35, 0x0D, 0x0A};

  56.                                  //AT+CIPSTART="TCP","192.168.4.100",8765,设置模块为TCP客户端,链接192.168.4.100,端口8765

  57. unsigned char AT_CIPSEND[14] = {0x41, 0x54, 0x2B, 0x43, 0x49, 0x50, 0x53, 0x45, 0x4E, 0x44, 0x3D, 0x34, 0x0D, 0x0A};

  58.     //AT+CIPSEND=4 发送4个字节

  59. uchar code AT_CWMODE3[13] = {0x41, 0x54, 0x2B, 0x43, 0x57, 0x4D, 0x4F, 0x44, 0x45, 0x3D, 0x33, 0x0D, 0x0A};    //AT+CWMODE=3

  60. uchar code AT_CIPMUX[13] = {0x41, 0x54, 0x2B, 0x43, 0x49, 0x50, 0x4D, 0x55, 0x58, 0x3D, 0x31, 0x0D, 0x0A}; //AT+CIPMUX=1 开启多链接

  61. uchar code AT_CIPSERVER[21] = {0x41, 0x54, 0x2B, 0x43, 0x49, 0x50, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x3D, 0x31, 0x2C, 0x38, 0x37, 0x36, 

  62.                                0x35, 0x0D, 0x0A};    

  63.           //AT+CIPSERVER=1,8765 开启tcp服务器,端口号8765

  64. uchar code AT_CIPSTO[15] = {0x41, 0x54, 0x2B, 0x43, 0x49, 0x50, 0x53, 0x54, 0x4F, 0x3D, 0x36, 0x30, 0x30, 0x0D, 0x0A};    

  65.            //AT+CIPSTO=600 设置服务器超时时间600s

  66. void main()

  67. {

  68.     int i = 0;

  69.     WDT_CONTR = 0;

  70.     DS1302=0;  //关DS1302模块,与本实验无关

  71.     SD=0;    //关SD卡模块,与本实验无关

  72.     cmg88();  //关数码管,点阵函数

  73.     delay_10ms();

  74.     TING_CHE

  75.     serial_init(); //tomd = 0x20

  76.      for(i=0; i<8; i++)

  77.     {

  78.         SBUF = AT_RST[i];

  79.         delay_ms();

  80.     }

  81.     delay_s();

  82.     rcv_flag++;

  83.      for(i=0; i<13; i++) //设置模式3

  84.     {

  85.         SBUF = AT_CWMODE3[i];

  86.         delay_ms();

  87.     }

  88.     delay_s();

    结构、单片机的汇编与c语言编程、单片机的开发环境及方法进行了详细的介绍;并通过具体的开发实例,讲解了嵌入式系统中的接口技术、串行通信、数模转换、模数转换、现场总线等知识与开发技巧。本书最大的特色在于每一个实例都力求让读者真正了解从原理到实现的具体过程。因此本书介绍的知识虽然基于atmelat89s51型处理器,但讲解的基本设计原理和技术都是通用的,通过对本书的学习,读者可以完全具备将书中的技术应用于其他处理器的能力。

  89.     rcv_flag++;

  90.      for(i=0; i<8; i++)  //重启生效

  91.     {

  92.         SBUF = AT_RST[i];

  93.         delay_ms();

  94.     }

  95.     delay_s();

  96.     rcv_flag++;

  97.      for(i=0; i<13; i++)  //设置多链接

  98.     {

  99.         SBUF = AT_CIPMUX[i];

  100.         delay_ms();

  101.     }

  102.     rcv_flag++;

  103.      for(i=0; i<21; i++) //创建tcp服务器,端口号8765

  104.     {

  105.         SBUF = AT_CIPSERVER[i];

  106.         delay_ms();

  107.     }

  108.     delay_s();

  109.     rcv_flag++;

  110.      for(i=0; i<15; i++)  //设置超时时间600s

  111.     {

  112.         SBUF = AT_CIPSTO[i];

  113.         delay_ms();

  114.     }

  115.     delay_s();

  116.     rcv_flag++;

  117.      while(1);            

  118. }

  1. void serial_interrup() interrupt 4

  2. {

  3.     if(TI)

  4.         TI = 0;

  5.     if(RI)

  6.     {

  7.         RI = 0;

  8.         tcp_buf[count] = SBUF;//保存一个字节

  9.         if(tcp_buf[0]==0x23)//用操作码以#开头,检测到#就开始保存数据

  10.         {

  11.             count++;

  12.         }

  13.         else

  14.         {

  15.             count=0;

  16.         }

  17.         if(count>3) //用户操作码有4个字符,超出就不是用户操作码

  18.         {

  19.            if(tcp_buf[1] == 'u' && tcp_buf[2] == 'p')//up前进

  20.             {

  21.                 LED4 = 0;

  22.                 ZHENG_ZHUAN

  23.             }

  24.             if(tcp_buf[1] == 'd' && tcp_buf[2] == 'n')     //dn后退

  25.             {

  26.                 LED4 = 1;

  27.                 FAN_ZHUAN

  28.             }

  29.             if(tcp_buf[1] == 'z' && tcp_buf[2] == 'z')     //zz左转

  30.             {

  31.                 LED5 = 1;

  32.                 ZUO_ZHUAN

  33.             }

  34.             if(tcp_buf[1] == 'y' && tcp_buf[2] == 'z')     //yz右转

  35.             {

  36.                 LED5 = 0;

  37.                 YOU_ZHUAN

  38.             }

  39.             if(tcp_buf[1] == 's' && tcp_buf[2] == 'p')     //sp停车

  40.             {

  41.                 LED6 = 0;

  42.                 TING_CHE

  43.             }

  44.             count=0;//超出4个字符,非用户操作码,清零count,重新接收数据

  45.         }

  46.     }

  47. }

delay.c

  1. #include <intrins.h>

  2. void delay_us() //误差 -0.234375us

  3. {

  4.     unsigned char a;

  5.     for(a=3;a>0;a--);

  6. }

  7. void delay_10us() //误差 -0.173611111111us

  8. {

  9.     unsigned char a,b;

  10.     for(b=1;b>0;b--)

  11.         for(a=43;a>0;a--);

  12. }

  13. void delay_ms() //误差 -0.651041666667us

  14. {

  15.     unsigned char a,b;

  16.     for(b=102;b>0;b--)

  17.         for(a=3;a>0;a--);

  18. }

  19. void delay_10ms() //误差 -0.000000000002us

  20. {

  21.     unsigned char a,b;

  22.     for(b=249;b>0;b--)

  23.         for(a=17;a>0;a--);

  24. }

  25. void delay_100ms() //误差 -0.000000000023us

  26. {

  27.     unsigned char a,b;

  28.     for(b=221;b>0;b--)

  29.         for(a=207;a>0;a--);

  30. }

  31. void delay_s() //误差 -0.000000000227us

  32. {

  33.     unsigned char a,b,c;

  34.     for(c=13;c>0;c--)

  35.         for(b=247;b>0;b--)

  36.             for(a=142;a>0;a--);

  37.     _nop_; //if Keil,require use intrins.h

  38. }

  39. void delay_3s() //误差 -0.000000000682us

  40. {

  41.     unsigned char a,b,c;

  42.     for(c=93;c>0;c--)

  43.         for(b=178;b>0;b--)

  44.             for(a=82;a>0;a--);

  45. }

  46. void delay_5s() //误差 -0.000000001137us

  47. {

  48.     unsigned char a,b,c;

  49.     for(c=179;c>0;c--)

  50.         for(b=220;b>0;b--)

  51.             for(a=57;a>0;a--);

  52. }

serial.c


  1. void serial_init()

  2. {

  3.     EA = 0; //关闭所有中断

  4.     SCON = 0x40;//工作方式 1, 8位异步串行收发,波特率由定时器 1 控制

  5.     PCON = 0;

  6.     RCAP2H = 0xff;

  7.     RCAP2L = 0xfd;//方式1和方式3的波特率=fosc/(32-(65535-(RCAP2H,RCAP2L))

  8.     TH2=0xFF;

  9.       TL2=0xFD;  //设置波特率为115200

  10.     T2CON=0x34;  //将定时器2设置为波特率发生器(接收和发送都用Timer2) 

  11.     ET2 = 0;   //关闭定时器1中断

  12.     TI = 0;

  13.     RI = 0;

  14.     REN = 1;   //允许接收

  15.     ES = 1;   //开启串口中断

  16.     EA = 1;   //开启总中断

  17.     TR2 = 1;   //开启定时器 2

  18. }

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

单片机的输出都是晶体管电路。内部给一个高电平,外面就能输出低电平。当你用程序控制输出的时候,实际上是给内存的某一个位置(我们叫做寄存器)赋值了一个1(也就是写高电平)。内存都是电路做的,这个电路一直接到外面的引脚,外面就能输出1。

生成海报
点赞 0

thePro

我还没有学会写个人说明!

相关推荐