赞
踩
准备材料:stm89c516、esp8266-01、至少5根杜邦线。。、电路板。
大概思路:
1、控制esp和服务器连接。
2、pc向向服务器发送指令。
3、服务器接收到指令后,再向esp发送。
4、esp接收到指令后,再向单片机发送。
5、单片机接收到指令后,执行 指令。
先讲第一步:控制esp和服务器连接
首先用到是esp8266-01,如图:
然后是下面TTL-USB串口线,如图:
还需要一个串口调试助手,为了接发数据。我使用的调试助手如,下图:
下面是硬件连接,硬件连接并不复杂,如图:
之后打开串口进行连接,如图:
备注:由于我之前把模块的波特率修改成9600了,其实esp8266波特率默认是115200。因此如果你没有修改波特率,则需要选择115200,不然没有结果。
准备工作做好之后,开始进行指令发送:
指令全部成功发送后,esp的基本工作就完成了
接下俩讲第二步,运行以下代码:
`#include
#include<winsock.h>
#pragma comment(lib,“ws2_32.lib”)
using namespace std;
void initialization();
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr(“115.29.109.104”);
server_addr.sin_port = htons(6520);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << “服务器连接失败!” << endl;
WSACleanup();
}
else {
cout << “服务器连接成功!” << endl;
}
//发送,接收数据 while (1) { cout << "you:"; cin >> send_buf; send_buf[strlen(send_buf) - 1] = '\n'; send_buf[strlen(send_buf) - 2] = '\r'; send_len = send(s_server, send_buf, strlen(send_buf), 0); if (send_len < 0) { cout << "发送失败!" << endl; break; } /*recv_len = recv(s_server, recv_buf, 100, 0); if (recv_len < 0) { cout << "接受失败!" << endl; break; } else { cout << "other:" << recv_buf << endl; }*/ } //关闭套接字 closesocket(s_server); //释放DLL资源 WSACleanup(); return 0;
}
void initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << “初始化套接字库失败!” << endl;
}
else {
cout << “初始化套接字库成功!” << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << “套接字库版本号不符!” << endl;
WSACleanup();
}
else {
cout << “套接字库版本正确!” << endl;
}
//填充服务端地址信息
}
`
成功运行,如图:
第三步已经在第一步里面完成了。
接下来讲第四步,如何让esp向单片机发送指令:
这里只要依照这电路图找出 RXD/TXD I/O 口就行,我这款单片机的 RXD、TXD 为 P30 和 P31 口,只要将 ESP8266 接通 3.3 V 电源,将 wifi 模块的 RX 和 TX 与单片机对应的口交叉相连就可以了,实际连线如下
-ESP8266-01- | -单片机- |
---|---|
-VCC- | -VCC(3.3)- |
-GND- | -GND- |
-RXD- | -TXD- |
-TXD- | -RXD- |
第四步完成!
开始,第五步!!(最后一步了!!!)
将以下代码烧入单片机中
#include <stdio.h>
#include <reg51.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED1 = P2^0;
sbit LED2 = P2^1;
sbit LED3 = P2^2;
sbit LED4 = P2^3;
sbit LED5 = P2^4;
sbit LED6 = P2^5;
sbit LED7 = P2^6;
sbit LED8 = P2^7;
// 串口中断接收相关
uint scount = 0, maxLen = 25, tscount = 0;
uchar srdatas[25];
// 计时器 0, 多大代表有多少个 50ms(0 ~ 65535)
uint time0Count = 0;
// 串口接收数据已处理标志
bit sflag = 0;
// 校验连接发送标志(1-表示需要发送)
bit tsflag = 0;
void Delay2(unsigned long cnt);
void Tranfer(uchar s);
void SysInit();
void SetWifi();
void dealReceiveData();
void dealReceiveLine(uchar line, uint length);
void dealWifiConnectInfo();
// 10 进制 => 2 进制
//uchar* decimal2binary(uint val);
// 字符串转数字
// uint parseInt(uchar* str, uint len);
void Delay2(unsigned long cnt) {
long i;
for(i=0;i<cnt*10;i++);
}
/*
uchar* decimal2binary(uint val) {
uchar chs[8];
uint i = 0, tmp = val;
for(i = 0; i < 8; i++) {
if(tmp == 0) {
chs[i] = 0;
continue;
}
chs[i] = (tmp % 2) + 48;
tmp = tmp / 2;
}
for(i = 0; i < 4; i++) {
tmp = chs[i];
chs[i] = chs[8-i-1];
chs[8-i-1] = tmp;
}
return chs;
}
*/
/*
uint parseInt(uchar* str, uint len) {
uint i = 0, resVal = 0;
for(i = 0; i < len; i++) {
resVal = resVal + ((str[i] - 0x30) * pow(10, len - i - 1));
}
return resVal;
}
*/
// 接收到字符串出现 /r/n, 视为新行标志
void dealReceiveData() {
uint t = 0;
if(sflag == 1 || scount <= 0) { return; } // 延时之后依然没有数据, 既断定为串口有数据接收到 tscount = scount; // 使用 Delay2 有问题 // Delay2(100); t = time0Count; // 演示 50 ms while(abs(time0Count - t) <= 0); if(scount != tscount) { return; } // 数据处理期间暂停串口中断使能 ES = 0; // 数组未溢出 if(scount < maxLen) { // 接收到第二个数据之后, 判断是否出现了结束符 if(scount > 2) { // 出现了换行符, 处理接收到的行的数据 if(srdatas[scount - 2] == '\r' && srdatas[scount - 1] == '\n') { dealReceiveLine(srdatas, scount - 2); scount = 0; } } } // 执行之后即为串口接收到的数据已经处理 sflag = 1; ES = 1;
}
void dealWifiConnectInfo() {
// 开始发送尝试重连
if(tsflag == 1) {
ET0 = 0;
printf(“AT+CIPCLOSE=2\r\n”);
Delay2(5);
printf(“AT+CIPSTART=2,“TCP”,“115.29.109.104”,6520\r\n”);
Delay2(10);
tsflag = 0;
ET0 = 1;
}
}
void dealReceiveLine(uchar* line, uint length) {
// bit hasCommand = 0;
uint i = 0, t = 0;
uchar command;
uchar newLine[25];
// 去除换行符 if(length > 3) { for(i = 0; i < length; i++) { if(line[i] != '\r' && line[i] != '\n') { newLine[t] = line[i]; t++; } if(t >= 25) { length = t; break; } } } if(length > 3) { // 处理开关控制指令 if( newLine[0] == '+' && newLine[1] == 'I' && newLine[2] == 'P' && newLine[3] == 'D' ) { i = 0; while(i < length && newLine[i] != ':') { i++; } // 存在有效位置 if(i < length) { t = 0; for(i = i + 1; i < length; i++) { t++; if(newLine[i] == '/') { continue; } command = newLine[i] - 0x30; switch(t) { case 1: LED1 = !command; break; case 2: LED2 = !command; break; case 3: LED3 = !command; break; case 4: LED4 = !command; break; case 5: LED5 = !command; break; case 6: LED6 = !command; break; case 7: LED7 = !command; break; case 8: LED8 = !command; break; } if(t >= 8) { break; } } } } /* LED6 = ~LED6; // 处理定时轮询的远程连接状态响应数据 if(tsflag == 1) { LED7 = ~LED7; if( newLine[0] == 'A' && newLine[1] == 'L' && newLine[2] == 'R' && newLine[3] == 'E' && newLine[4] == 'A' && newLine[5] == 'D' && newLine[6] == 'Y' ) { LED8 = 0; } else { LED8 = 1; } tsflag = 0; } */ }
}
void SysInit() {
// 初始化定时器1, 配置波特率发生器
TH1 = 0xFD; //晶振11.0592mhz 波特率设为9600
TL1 = TH1;
TMOD |= 0x20; //定时器1方式2
SCON = 0x50; //串口接收使能
ES = 1; //串口中断使能
TR1 = 1; //定时器1使能
TI = 1; //发送中断标记位,必须设置
// 初始化定时器0, 做系统定时任务(11.0592MHz, 定时 50ms)
/* */
TH0 = 0x4C;
TL0 = 0x00;
TMOD |= 0x01; // 工作在方式2
TR0 = 1; // 定时器0使能
ET0 = 1;
//REN = 0; // 禁止串口接收数据
printf("begin init wifi...\r\n");
SetWifi();
printf("wifi inited...\r\n");
//REN = 1;
EA=1;
}
void SetWifi() {
Delay2(1000);
printf(“AT+CIPMUX=1\r\n”);
Delay2(1000);
printf(“AT+CIPSERVER=1\r\n”);
Delay2(1000);
printf(“AT+CIPCLOSE=2\r\n”);
Delay2(2000);
printf(“AT+CIPSTART=2,“TCP”,“115.29.109.104”,6520\r\n”);
Delay2(2000);
}
/**/
void Timer0() interrupt 1 {
uint t = 0;
ET0 = 0;
// 继续下一轮定时
TH0 = 0x4C;
TL0 = 0x00;
time0Count = (time0Count + 1) % 1200;
// 大概 30s 判断一下连接是否断开, 断开之后需要重连
if(time0Count % 600 == 0) {
tsflag = 1;
}
ET0 = 1;
}
void Usart() interrupt 4 {
if(RI == 1)
{
RI = 0;
srdatas[scount] = SBUF;
scount += 1;
if(scount >= maxLen) {
scount = 0;
}
sflag = 0;
}
}
void main() {
SysInit();
while(1) {
dealReceiveData();
dealWifiConnectInfo();
}
}
备注:void dealReceiveLine(…) { … }
处理逻辑如下
去除接收到的行的前后换行符。
判断处理后的结果是否以 +IPD 开头。
找到 : 后的 8 个字符,依次控制 LED1 ~ LED8 的开关状态,1 为开启,0 为关闭。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。