近日,因项目需要做了个电脑与ESP8266模块通讯的实验,实现:电脑通过局域网控制ESP8266模块IO口驱动Led灯亮、灭,并向电脑返回执行结果。供各位小伙伴参考,不足之处,敬请谅解!
软件工具:
- VS2022;
- Arduino IDE 2.2.1
操作系统:Windows 10
模 块:Esp82266 STA+UDP模式
Esp8266实拍图:
VS2022开发Form界面
Form源码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Udp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_Load(object sender, EventArgs e)
{
label6.Text = "未连接";
button2.Enabled = false;
}
Socket sockRev;
Socket sockSend;
EndPoint revc;
IPEndPoint send;
Thread tdRev;
private void button1_Click(object sender, EventArgs e)
{
if(textBox3.Text==""| textBox4.Text == ""| textBox5.Text == "")
{
MessageBox.Show("接收IP、端口,发送端口均不能为空!");
}
IPEndPoint add = new IPEndPoint(IPAddress.Any, Convert.ToInt16(textBox5.Text));
sockRev = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sockRev.Bind(add);
revc = (EndPoint)add;
sockSend = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
send = new IPEndPoint(IPAddress.Parse(textBox3.Text), Convert.ToInt16(textBox4.Text));
//建立开启接收进程
tdRev = new Thread(DataRev);
tdRev.IsBackground = true;
tdRev.Start();
label6.Text = "连接成功";
button1.Enabled = false;
button2.Enabled = true;
}
//数据接收函数
public void DataRev()
{
int len;
while (true)
{
//从目标地址接收数据
len = sockRev.ReceiveFrom(dataRecv, ref revc);
if (len > 0)
{
//将数据进行ASCII\UTF8解码,获得字符串
//string str = Encoding.ASCII.GetString(dataRecv, 0, len);
string str = Encoding.UTF8.GetString(dataRecv, 0, len);
textBox2.Multiline = true;// 设置为多行文本输入模式
textBox2.WordWrap = true; // 开启自动换行功能
// textBox2.ScrollBars = ScrollBars.Vertical;//设置TextBox的ScrollBars属性为Vertical,表示只显示垂直滚动条
textBox2.AppendText(DateTime.Now.ToString()+" ");
textBox2.AppendText(str); //向文本框添加接收到字符串,显示接收到的字符
textBox2.AppendText(System.Environment.NewLine); //换行
}
}
}
//定义发送缓冲区
byte[] dataSend = new byte[1024];
//定义接收缓冲区
byte[] dataRecv = new byte[1024];
private void button2_Click(object sender, EventArgs e)
{
if (textBox1.Text=="")
{
MessageBox.Show("发送框数据不能为空!");
}
//将数据转换为ASCII\UTF8编码,得到byte类型的数组
//dataSend = Encoding.ASCII.GetBytes(textBox1.Text);
dataSend = Encoding.UTF8.GetBytes(textBox1.Text);
//将数据发送
sockSend.SendTo(dataSend, dataSend.Length, SocketFlags.None, send);
}
private void label7_Click(object sender, EventArgs e)
{
}
}
}
Arduino IDE 2.2.1开发界面截图
Arduino IDE 2.2.1源码
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char *STAssid ="chenggui227"; //需要连接路由器的名称
const char *STApassword="chenggui227"; //路由器的密码
/****************UDP设置项 *****************/
unsigned int read_Port = 8268; //接收监听端口
unsigned int send_Port = 8267; //发送端口
char readdata[512]; //数据缓存
WiFiUDP Udp; //定义udp对象
int deng = 15; //IO14(D5),用来做控制灯亮灭的
int deng_g = 12; //IO14(D5),用来指示连接路由器状态
void setup() {
Serial.begin(115200);
Serial.println("");
pinMode(deng, OUTPUT); //设置指定io为输出模式
digitalWrite(deng, 0); //初始化为低电平,关闭灯状态
pinMode(deng_g, OUTPUT); //设置指定io为输出模式
digitalWrite(deng_g, 0); //初始化为低电平,关闭灯状态
WiFi.mode(WIFI_STA); //设置为STA模式
WiFi.begin(STAssid, STApassword); //配置连接信息,开始连接
//运行自定义函数,在未连接到路由器的过程中,打印输出......,直到连接成功
gotoWifi();
Serial.println("连接路由器成功");
digitalWrite(deng_g, 1);
Udp.begin(read_Port); //UDP设置监听指定端口
}
void loop() {
/****************检测WiFi连接状态****************/
//如果没有连接到路由器,在setup里面已经连接过,这里表示断线,执行断线重连
//否则,正常的UDP通信
if (WiFi.status() != WL_CONNECTED) {
WiFi.disconnect();
WiFi.begin(STAssid, STApassword);
gotoWifi();
}
else{
Udp_Handler(Read_Udp());
}
}
//连接路由器
void gotoWifi(){
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("正在连接路由器......");
}
Serial.println("");
Serial.println("Connected");
Serial.print("IP Address:");
Serial.println(WiFi.localIP()); //串口输出模块IP地址
Serial.println(read_Port); //串口输出模块监听端口号
}
/*自定义函数
*将接收的数据,以String类型返回,方便分析处理
*/
String Read_Udp(){
String data="";
int packetSize = Udp.parsePacket();
if (packetSize) {
memset(readdata,0x00,sizeof(readdata));
Udp.read(readdata, 511);
Udp.flush();
for(int i=0;i<packetSize;i++){
data +=readdata[i];
}
Serial.println(data);
}
return data;
}
/************自定义函数,对接收数据分析处理************/
void Udp_Handler(String data){
if(data!=""){
if(data=="开灯"){
digitalWrite(deng, 1);//灯亮
myPrint("打开",0); //指定发送模式:0;广播发送模式:1
}
else if(data=="关灯"){
digitalWrite(deng, 0);//灯灭
myPrint("关闭",0); //指定发送模式:0;广播发送模式:1
}
else if(data=="请求"){
myPrint("收到",0); //指定发送模式:0;广播发送模式:1
}
}
}
/*自定义函数
*封装数据发送功能,方便调用
*第一个参数,使用String类型作为发送内容
*第二个参数,a为真,指定发送,对发送方返回数据,a为假,广播发送,群发信息
*/
void myPrint(String data,bool a){
if(a==true){
// Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Serial.println("广播发送");
}else{
Udp.beginPacket("192.168.3.91", send_Port);//指定返回数据接收IP地址、端口号
Serial.println("指定发送");
}
Udp.print(data);//把数据写入发送缓冲区
Udp.endPacket();//发送数据
}