需要材料:51单片机一块(我使用的是普中开发板C52)、esp8266 nodmcu、若干杜邦线。
在连线之前,我们需要先明确几个问题:
1、两机之间如何通信? 通常我们使用的是简单的uart串口通信、但是在实际过程中,esp8266会默认在串口打印一些调试信息,特别在手机端和设备端不在一个局域网内的时候,返回tcp数据包的信息。这导致串口通信受到了极大的干扰。
这里我希望读者好厚米能去参考一份文档---《Arduino程序设计基础》(网上电子书网站自己找一下,推荐电子发烧友)
我们采用软串口的方式,即自定义串口的方式,来避免硬件串口打印调试信息的影响。
2、esp8266 --3.3v 51单片机--5v,,两机真的可以通信吗? 答案是肯定的,虽然两机电源电压不一致,对于同一个指令的判定标准可能不同,但是不需要担心这个问题。只需要保证两机共地。然后两机接好自己的电源即可。
3、编程前需要查阅什么资料? 因为我使用的是blinker (详情见点灯科技官网-开发文档和开发社区) 对于初学者更为友好,也要求读者朋友有一点点安卓ui设计的知识。对于51单片机,需要用到串口中断,所以需要了解如何进行串口初始化,对波特率设计,串口中断函数的设计。
下一步,我们开始着手设计两机的代码,并做出解读:
这里对于串口初始化的步骤,我就不介绍了,不知道的读者可以网上找个示例。
这里的波特率为9600
我介绍一下我的串口中断函数:moto=0时,电机关闭;moto=1时。电机转动
void line() interrupt 4
{
RI=0;
recedata=SBUF;
switch (recedata)
{
case 'a':{moto=1;flag=1;break;} //直接打开 模式1
case 'b':{moto=0;flag=1;break;} //直接关闭 模式1
case '1':{flag=0; break;} // 模式0 按键模式 需要按下按键才能启动电机
case '2':{flag=2;break;} //模式2 采用舵机信号二档电机转速
case '3':{flag=3;break;} //模式3 转到三档
}
}
对比一下主函数内对于flag的处理,就能够了解指令大致情况。
void main()
{
flag=1;
moto=0;
Init();
while(1)
{
switch(flag)
{
case 0:{model();break;} //模式1 标准模式
case 1:break;
case 2:{model2();break;} //二档
case 3:{model3();break;} //三档
}
}
}
统一的指令是多机通信的标准、流程执行最好的校验方式。
以下方便起见,我只介绍当收到指令为a 和 b时,esp8266的情况。
配置好esp8266的开发环境(包括下载开发板地址、下载blinker库文件、下载esp8266开发板)
我们需要用到的是Arduino,完整代码如下:
#define BLINKER_WIFI
#include <Blinker.h>
#include <SoftwareSerial.h> //使用软串口必须的两个头文件
char auth[] = "*********"; //APP端的唯一的密钥
char ssid[] = "Dirty";
char pswd[] = "wqh02110954";
// 新建组件对象
BlinkerButton Button1("btn-fan");
BlinkerSlider Slider1("ran-o6s");
#define out D3
#define rx D1
#define dx D3 //定义端口
SoftwareSerial suart = SoftwareSerial (rx,dx) ; //软串口定义,有好几种定义方式。
// 按下按键即会执行该函数
void button1_callback(const String & state) //按键的触发函数
{
BLINKER_LOG("get button state: ", state);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
if(state=="on"){
Button1.print("on");
Button1.color("#FFFFFF");
Button1.text("off");
suart.print('a'); //软串口发送a
}
if(state=="off") {
Button1.print("off");
Button1.color("#000000");
Button1.text("on");
suart.print('b'); //软串口发送b
}
}
void slider_call(int32_t value) 滑块的触发函数
{
BLINKER_LOG("get slider value: ", value); //滑块在设置的时候会有最大值和最小值
Serial.print(value); //value的值就是当前滑块滑到的数值
suart.print(value);
}
// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
Serial.print("组件名称不对"); //自己写一个报错
}
void setup() //setup意为初始化
{
// 初始化串口
Serial.begin(9600);
suart.begin(9600);
BLINKER_DEBUG.stream(Serial); //波特率的标注
// 初始化有LED的IO
pinMode(LED_BUILTIN, OUTPUT); //每一个io口使用的时候需要设置它的模式 这里是输出模式
pinMode(out,OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); //LED_BUTIIN只是电路板上一个自带的灯,不需要自定义
// 初始化blinker
Blinker.begin(auth, ssid, pswd); //根据你给的网络和密钥进行服务器链接
Blinker.attachData(dataRead);
Button1.attach(button1_callback); //滑块和组件的触发函数都需要绑定,这很关键
Slider1.attach(slider_call);
}
void loop() { //loop意为死循环
Blinker.run();
}
了解blinker的读者会知道,手机端会有一个app,提供组件,如图所示:
如手机界面所示,有三个部分:开关按键、滑动条和一个调试框,每一个组件点开都会有自己的键名,如btn-fan ran-o6s(我已经标注了)。 保证键名能够对应的上。观察上方代码,你会发现有如下定义,引号内的就是键名。
BlinkerButton Button1("btn-fan");
BlinkerSlider Slider1("ran-o6s");
对代码的理解需要靠读者自己,或者与朋友交流。请多看代码备注
最后一步就是接线,注意代码中的定义dx 是D3 ,需要将 D3连结51单片机P3.0 GND相连即可。