一生有你llx 阅读(224) 评论(0)
/*************************************************************************************************
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();
  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. }