APP通過ESP8266與單片機通信
簡述
本項目中是用ESP8266作爲熱點,工作在MODE2模式,手機作爲station接入ESP8266的網絡進行數據傳輸,同時,ESP8266與52單片機之間通過串口進行數據傳輸。
本項目中只需要APP向WIFI發送數據,所以在APP的程序中沒有接收WIFI數據的程序。在文章最後,則是筆者在寫代碼的過程中遇到的一個問題,51單片機不能接收WIFI數據,但能向WIFI發送AT指令的問題。
手機端實現
建立連接線程
以下爲APP與ESP8266建立連接的線程,建立連接時只要獲取其對象即可。其中的IP和port爲ESP8266的IP地址和端口號,IP一般默認爲192.168.0.1,端口號默認爲8080,端口號可以自己設置。
private class ConnectThred extends Thread{
private String ip;
private int port;
public ConnectThred(String ip,int port){
this.ip = ip;
this.port = port;
}
public void run(){
//接收數據可用子線程也可直接在此線程操作
char[] buffer=new char[256];//定義數組接收輸入流數據
String bufferString="";//定義一個字符接收數組數據
int conut =0;//初始化buffer數組長度爲0
int tag=0;//初時寫入數組的位置
try {
//建立連接
socket = new Socket(ip,port);
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d("Controler","runOnUI");
bt_link.setText("斷開連接");
bt_link.setBackgroundColor(Color.GREEN);
Toast.makeText(Controler.this,"連接成功",Toast.LENGTH_LONG).show();
}
});
//讀取輸入流
bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//獲取輸出流
OutputStream=socket.getOutputStream();
//獲取socket的輸出流,接收數據
InputStream = socket.getInputStream();
while (true) {
//當輸入流寫入buffer數組的長度大於0時即接收到數據時
while ((conut=bufferedReader.read(buffer))>0) {
//將buffer數組的數據全部寫入bufferString字符類型
while ( tag<buffer.length) {
bufferString=bufferString+buffer[tag];
tag++;
}
//將數據給messageHandler刷新UI界面
Message msgMessage =new Message();
msgMessage.obj=bufferString;
msgMessage.what=1;
messageHandler.sendMessage(msgMessage);
//初始化數據,以便處理下一條輸入流信息
tag=0;
bufferString="";
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(Controler.this,"連接錯誤",Toast.LENGTH_LONG).show();
}
});
}
}
}
發送數據線程
以下是APP向ESP8266發送數據的代碼,同樣在一個子線程中執行。需要發送數據時通過對象調用此方法即可。
//向服務器發送數據子程序
public class Send extends Thread{
public void run(){
if(socket != null){
try{
if (msg_send != null && msg_send.length()>0){
OutputStream.write(msg_send.getBytes("utf-8"));
OutputStream.flush();
msg_send="";
}
else{
Looper.prepare();
Toast.makeText(Controler.this,"發送的數據不能爲空",Toast.LENGTH_LONG).show();
Looper.loop();
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
}
通過按鈕建立或斷開連接
定義相關變量
private static final String IP = "192.168.4.1";//服務端IP
private static final int PORT = 8080; //端口號
Socket socket; //創建一個socket
Boolean IsConnected = false; //連接標誌
ConnectThred mConnectThread; //TCP連接線程
//輸入輸出流
OutputStream OutputStream = null;//數據輸出流,發送數據
BufferedReader bufferedReader;//聲明輸入流對象
InputStream InputStream = null;//定義數據輸入流,用於接收數據
通過按鈕實現連接:
bt_link.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { //連接按鈕,點擊與ESP8266芯片連接或斷開
if (socket ==null || !socket.isConnected()){
mConnectThread = new ConnectThred(IP,PORT);
mConnectThread.start();
}
if (socket!=null && socket.isConnected()){
try {
socket.close();
socket = null;
bt_link.setText("點擊連接");
bt_link.setBackgroundColor(Color.GRAY);
Toast.makeText(Controler.this,"連接已斷開",Toast.LENGTH_LONG).show();
}catch (IOException e){
e.printStackTrace();
}
}
}
});
通過按鈕發送數據:
通過new一個發送數據線程的對象,調用start方法啓動發送數據線程即可發送數據。
select_mode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mode_count++;
if (mode_count > 4)
mode_count=0;
mode = mode_arr[mode_count];
msg_send = "mod"+Integer.toString(mode_count)+"/n";
new Send().start();
tempmode.setText(mode); //設置模式
}
});
下位機端接收WIFI數據
下位機端使用51單片機實現,下位機端與ESP8266之間通過串口進行通信,傳輸數據。所以下位機接收WIFI數據時使用的是串口接收程序。
void UartConfiguration()
{
TMOD=0x20; // 設置計數器1工作模式2
TH1=0xfd; //計數器1初值
TL1=0xfd; //計數器1初值 兩個初值決定波特率,此處設置波特率9600
PCON=0x00; //波特率倍增0x00不加倍,0x80加倍
SCON=0x50; //
EA=1; //
ES=1; //
TR1=1; //
TI=1;
}
將接收到的數據存入一個數組中然後進行處理
void ESP_UART() interrupt 4
{
static uchar i=0;
// led1=~led1;
if(RI==1)
{
RI=0; //½ÓÊÕ±êÖ¾
Recive_table[i]=SBUF;
sendByte(Recive_table[i]);
i++;
if((Recive_table[i-1]=='\n'))
{
Recive_table[i]='\0';
i=0;
}
}
else
TI=0;
}
處理接收到的數據
void getData()
{
if(Recive_table[0]=="+")
sendString(Recive_table);
if((Recive_table[0]=='+')&&(Recive_table[1]=='I')&&(Recive_table[2]=='P'))
{
if((Recive_table[3]=='D')&&(Recive_table[6]==','))
{
if(Recive_table[9]=='0')//&& Recive_table[10]=='0' //
{
Shutdown();
}
else if(Recive_table[9]=='1')//&& Recive_table[10]=='1' //
{
MakeNum(Recive_table[10],Recive_table[11]);
Startup();
}
else if(Recive_table[9]=='d')//&& Recive_table[10]=='1' //
{
MakeNum(Recive_table[10],Recive_table[11]);
}
else if(Recive_table[9]=='e')//&& Recive_table[10]=='1' //
{
MakeNum(Recive_table[10],Recive_table[11]);
}
else if(Recive_table[9]=='o'&& Recive_table[10]=='d') //
{
m_index=Recive_table[11]-'0';
SetMode(m_index);
}
else if(Recive_table[9]=='f')//&& Recive_table[10]=='1' //
{
SetSweep(Recive_table[10]-'0');
}
else if(Recive_table[9]=='p')//&& Recive_table[10]=='1' //
{
SetSpeed(Recive_table[10]-'0');
}
else if(Recive_table[9]=='i')//&& Recive_table[10]=='1' //
{
SetDirect(Recive_table[10]-'0');
}
memset(Recive_table,0,50);
}
}
}
注意
當ESP8266與51單片機通信時,51單片機不能使用CH340芯片進行串口數據的傳輸,不然會出現ESP8266發送的數據51單片機接收不到的情況。