android之WIFI小車編程詳述


有了前幾篇wifi模塊eps8266的使用,單片機設置eps8266程序,android TCP客戶端,現在就做一個wifi小車

先上圖

小車是四個輪子的,每個輪子上都有電機驅動,前進后退的時候四個輪子同時前進和后退,轉彎的時候,小車兩邊的輪子按反方向轉。

為了達到更好的操作效果(一直按下前進,小車前進,按下左右轉小車左右轉,松開左右轉,小車繼續前進。松開前進,小車停止。后退同理),在單片機程序里加入了前進或后退的標志位。先說明一下,,,,,,

按下前進向單片機發送‘0’,按下后退向單片機發送‘1’,按下左轉向單片機發送‘2’,按下右轉向單片機發送‘3’,松開前進或后退向單片機發送‘5’,松開左轉或右轉向單片機發送‘6’,這樣子發數據也是為了獲得更好的操作體驗

前進 后退 左轉 右轉按鈕是使用的setOnTouchListener方法,以便在按鈕按下或松開時發送數據,

就看一下前進代碼

我在前面聲明了一下

//前進,關於OnTouchListener的使用,,找度娘,我也是找的度娘,不要偷懶呦

 //前進
    private OnTouchListener forwordButtonTouch = new OnTouchListener() {
        
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://如果按下
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("0".getBytes());//發送0
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            case MotionEvent.ACTION_UP://如果松開
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("5".getBytes());//發送‘5’
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            default:
                break;
            }
            return false;
        }
    };
//源碼
package com.wifi_Contrl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


@SuppressLint("ClickableViewAccessibility") public class MainActivity extends Activity {

    boolean isConnect=true;//連接還是斷開
    Button connectButton;//定義連接按鈕
    Button forwordButton;//定義前進按鈕
    Button backButton;//定義后退按鈕
    Button leftButton;//定義左轉按鈕
    Button righButton;//定義右轉按鈕
    EditText ipEditText;//定義ip輸入框
    EditText portText;//定義端口輸入框
    Socket socket = null;//定義socket
    private InputStream inputStream=null;//定義輸入流
    private OutputStream outputStream=null;//定義輸出流
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        connectButton = (Button) findViewById(R.id.btConnect);
        forwordButton = (Button) findViewById(R.id.btqianjin);
        backButton = (Button) findViewById(R.id.bthoutui);
        leftButton = (Button) findViewById(R.id.btzuozhuan);
        righButton = (Button) findViewById(R.id.btyuozhuan);
        ipEditText = (EditText) findViewById(R.id.etIP);
        portText = (EditText) findViewById(R.id.etPort);
        
        connectButton.setOnClickListener(connectButtonListener);
        forwordButton.setOnTouchListener(forwordButtonTouch);
        backButton.setOnTouchListener(backButtonTouch);
        leftButton.setOnTouchListener(leftButtonTouch);
        righButton.setOnTouchListener(righButtonTouch);
       
    }
    //連接
    private OnClickListener connectButtonListener = new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            if (isConnect == true) //標志位 = true表示連接
            {
                isConnect = false;//置為false
                connectButton.setText("斷開");//按鈕上顯示--斷開
                //打開連接線程
                Connect_Thread connect_Thread = new Connect_Thread();
                connect_Thread.start();
            }
            else //標志位 = false表示退出連接
            {
                isConnect = true;//置為true
                connectButton.setText("連接");//按鈕上顯示連接
                Toast.makeText(MainActivity.this,"已退出連接!", Toast.LENGTH_SHORT).show();
                try 
                {
                    socket.close();//關閉連接
                    socket=null;
                } 
                catch (IOException e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };
    //前進
    private OnTouchListener forwordButtonTouch = new OnTouchListener() {
        
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("0".getBytes());
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            case MotionEvent.ACTION_UP:
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("5".getBytes());
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            default:
                break;
            }
            return false;
        }
    };
    //后退
    private OnTouchListener backButtonTouch = new OnTouchListener() {
            
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    try 
                    {
                        //獲取輸出流
                        outputStream = socket.getOutputStream();
                        //發送數據
                        //outputStream.write(msgEditText.getText().toString().getBytes());
                        outputStream.write("1".getBytes());
                    } 
                    catch (Exception e) 
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    try 
                    {
                        //獲取輸出流
                        outputStream = socket.getOutputStream();
                        //發送數據
                        //outputStream.write(msgEditText.getText().toString().getBytes());
                        outputStream.write("5".getBytes());
                    } 
                    catch (Exception e) 
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                default:
                    break;
                }
                return false;
            }
    };
    //左轉
    private OnTouchListener leftButtonTouch = new OnTouchListener() {
        
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("2".getBytes());
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            case MotionEvent.ACTION_UP:
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("6".getBytes());
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            default:
                break;
            }
            return false;
        }
    };
    //右轉
    private OnTouchListener righButtonTouch = new OnTouchListener() {
        
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("3".getBytes());
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            case MotionEvent.ACTION_UP:
                try 
                {
                    //獲取輸出流
                    outputStream = socket.getOutputStream();
                    //發送數據
                    //outputStream.write(msgEditText.getText().toString().getBytes());
                    outputStream.write("6".getBytes());
                } 
                catch (Exception e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            default:
                break;
            }
            return false;
        }
    };
    //連接線程
    class Connect_Thread extends Thread//繼承Thread
    {
        public void run()//重寫run方法
        {
            try 
            {
                if (socket == null) 
                {
                    //用InetAddress方法獲取ip地址
                    InetAddress ipAddress = InetAddress.getByName(ipEditText.getText().toString());
                    int port =Integer.valueOf(portText.getText().toString());//獲取端口號 
                    socket = new Socket(ipAddress, port);//創建連接地址和端口    
                    if (socket !=null) {
                        runOnUiThread(new Runnable()
                        {
                            public void run() 
                            {    
                                // TODO Auto-generated method stub
                                Toast.makeText(MainActivity.this,"已成功連接!", Toast.LENGTH_SHORT).show();
                            }                        
                        });
                    }
                }    
            } 
            catch (Exception e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

 

//布局源碼,大神勿噴,小弟才入門android,所以關於布局還,,,,,
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_purple"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.wifi_Contrl.MainActivity" >

    <!-- IP地址 : -->
    <TextView
        android:id="@+id/tvIP"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="IP地址 :"
        android:textSize="23dp" 
        android:layout_x="0dp"
        android:layout_y="0dp"
        />
        
    <!-- 左轉 -->
    <Button
        android:id="@+id/btzuozhuan"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:layout_x="400dp"
        android:layout_y="118dp"
        android:text="左轉" />

    <!-- 右轉 -->
    <Button
        android:id="@+id/btyuozhuan"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:layout_x="520dp"
        android:layout_y="118dp"
        android:text="右轉" />

    <!-- 后退 -->

    <Button
        android:id="@+id/bthoutui"
        android:layout_width="wrap_content"
        android:layout_height="90dp"
        android:layout_x="105dp"
        android:layout_y="200dp"
        android:text="后退" />

    <!-- 前進 -->
    <Button
        android:id="@+id/btqianjin"
        android:layout_width="wrap_content"
        android:layout_height="90dp"
        android:layout_marginBottom="21dp"
        android:layout_x="105dp"
        android:layout_y="65dp"
        android:text="前進" />
    
    <!-- 連接 -->
    <Button
        android:id="@+id/btConnect"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_marginBottom="21dp"
        android:layout_x="500dp"
        android:text="連接" />

    <!-- 端口號 : -->
    <TextView
        android:id="@+id/tvPort"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="280dp"
        android:layout_y="0dp"
        android:text="端口號 :"
        android:textSize="23dp" />

    <!-- 輸入端口地址的文本控件 -->
    <EditText
        android:id="@+id/etPort"
        android:layout_width="70dp"
        android:layout_height="30dp"
        android:layout_x="380dp"
        android:layout_y="0dp"
        android:background="@android:color/white"
        android:ems="10"
        android:text="8080" />

    <!-- 輸入ip地址的文本控件 -->

    <EditText
        android:id="@+id/etIP"
        android:layout_width="150dp"
        android:layout_height="30dp"
        android:layout_x="100dp"
        android:layout_y="0dp"
        android:background="@android:color/white"
        android:ems="10"
        android:text="192.168.4.1" >

        <requestFocus />
    </EditText>

</AbsoluteLayout>

 

再看單片機,因為學實時操作系統UCOSII的時候,寫程序就養成了這樣寫程序習慣,如果對於這樣

#ifndef _USART_C_//如果沒有定義_USART_C_
#define _USART_ex_ extern
#else
#define _USART_ex_
#endif

_USART_ex_ unsigned char Usart_Receive[20];
_USART_ex_ unsigned char Usart_Cnt;
_USART_ex_ bit Usart_AT_flage;
_USART_ex_ bit Command_Flag;
_USART_ex_ unsigned char UsartData;
_USART_ex_ void InitUART(void);//串口初始化
_USART_ex_ void SendOneByte(unsigned char c);//發送字節型數據
_USART_ex_ void UartSends(unsigned char *str);//串行口連續發送char型數組,遇到終止號/0將停止

其實這樣寫,有助於各個c文件之間調用變量。說一下

#ifndef _USART_C_//如果沒有定義_USART_C_
#define _USART_ex_ extern//就定義_USART_ex_ 為extern
#else//否則
#define _USART_ex_就定義_USART_ex_為空
#endif

如果是自身文件編譯由於我在USART.C文件的開頭加上了#define _USART_C_所以,就定義_USART_C_為空

即   unsigned char Usart_Receive[20];

如果別的文件編譯那么因為別的文件沒有定義#define _USART_C_ 所以就定義_USART_ex_ 為extern

extern  unsigned char Usart_Receive[20];

對於extern  這應該不陌生吧,好了接着往下看,

不好意思再啰嗦下,我把所有的.h文件全放在了一個.h文件中,這樣在每個c文件的開頭只需加上#include "include.h"就方便多了

#define _MAIN_C_
#include "include.h"

sbit a1 = P1^0;//前左輪前進
sbit a2 = P1^1;//前左輪后退
sbit a3 = P1^2;//前右輪前進
sbit a4 = P1^3;//前右輪后進
sbit a5 = P1^4;//后左輪前進
sbit a6 = P1^5;//后左輪后退
sbit a7 = P1^6;//后右輪前進
sbit a8 = P1^7;//后右輪后進

bit forword_flag=0;
bit back_flag=0;

unsigned char CWMODE[]="AT+CWMODE=2\r\n"; //設置模塊的工作的模式為AP模式
unsigned char RST[]="AT+RST\r\n"; //重啟模塊使AT+CWMODE=2模式生效
unsigned char CIPMUX[]="AT+CIPMUX=1\r\n"; //啟動多連接
unsigned char CIPSERVER[]="AT+CIPSERVER=1,8080\r\n";//開啟服務器模式,端口號8080


void delay1s(void) //誤差 -0.00000000024us
{
 unsigned char a,b,c;
 for(c=95;c>0;c--)
for(b=26;b>0;b--)
for(a=185;a>0;a--);
}

//多連接AP模式
void ManyConnect_AP()
{
    P0=0x00;
    while(1)
    {
    UartSends(CWMODE);//返回ok
    delay1s();
    if(Usart_AT_flage ==1)
    {
    if(strstr(Usart_Receive, "OK") )
    {
    Usart_AT_flage = 0;
    P0 = 0x01;
    break;
    } 
    }
 }
    UartSends(RST);//返回一大溜,不用判斷返回
delay1s();
    delay1s();
    while(1)
    {
    UartSends(CIPMUX);//返回ok
    delay1s();
    if(Usart_AT_flage ==1)
    {
    if(strstr(Usart_Receive, "OK") )
    {
    Usart_AT_flage = 0;
    P0 = 0x03;
    break;
    } 
    }
 }
    while(1)
    {
    UartSends(CIPSERVER);//返回ok,多了也返回ok
    delay1s();
    if(Usart_AT_flage ==1)
    {
    if(strstr(Usart_Receive, "OK") )
    {
    Usart_AT_flage = 0;
    P0 = 0x07;
    break;
    } 
    }
 }
}

void main()
{
    InitUART();
    while(1)
    {
    ManyConnect_AP();//多連接AP模式
while(1)
    {
    //由於消息的開頭是+IP 故做此判斷
if((Usart_Receive[0]=='+')&&(Usart_Receive[1]=='I')&&(Usart_Receive[2]=='P'))
    {
    if((Usart_Receive[3]=='D')&&(Usart_Receive[6]==','))
    {
    if(Usart_Receive[9]=='0')//前進
{
forword_flag = 1;//前進標志位置一
back_flag = 0; //后退標志位置零
a1 = 1;//前左輪前進
a2 = 0;//前左輪后退
a3 = 1;//前右輪前進
a4 = 0;//前右輪后進
a5 = 1;//后左輪前進
a6 = 0;//后左輪后退
a7 = 1;//后右輪前進
a8 = 0;//后右輪后進
/*sbit a1 = P1^0;//前左輪前進
sbit a2 = P1^0;//前左輪后退
sbit a3 = P1^1;//前右輪前進
sbit a4 = P1^2;//前右輪后進
sbit a5 = P1^3;//后左輪前進
sbit a6 = P1^0;//后左輪后退
sbit a7 = P1^0;//后右輪前進
sbit a8 = P1^1;//后右輪后進*/

    }
if(Usart_Receive[9]=='1')//后退
{
forword_flag = 0;//前進標志位置一
back_flag = 1; //后退標志位置零
a1 = 0;//前左輪前進
a2 = 1;//前左輪后退
a3 = 0;//前右輪前進
a4 = 1;//前右輪后進
a5 = 0;//后左輪前進
a6 = 1;//后左輪后退
a7 = 0;//后右輪前進
a8 = 1;//后右輪后進
}
if(Usart_Receive[9]=='6')//左右轉停止
{
if(forword_flag == 1 && back_flag == 0)//上一次按下的是前進,沒松開
{
    //前進
a1 = 1;//前左輪前進
a2 = 0;//前左輪后退
a3 = 1;//前右輪前進
a4 = 0;//前右輪后進
a5 = 1;//后左輪前進
a6 = 0;//后左輪后退
a7 = 1;//后右輪前進
a8 = 0;//后右輪后進
}
if(forword_flag == 0 && back_flag == 1)//上一次按下的是后退,沒松開
{
    //后退
a1 = 0;//前左輪前進
a2 = 1;//前左輪后退
a3 = 0;//前右輪前進
a4 = 1;//前右輪后進
a5 = 0;//后左輪前進
a6 = 1;//后左輪后退
a7 = 0;//后右輪前進
a8 = 1;//后右輪后進
}
if(forword_flag == 0 && back_flag == 0)//上一次松開了前進或后退
{
    //停止
a1 = 0;//前左輪前進
a2 = 0;//前左輪后退
a3 = 0;//前右輪前進
a4 = 0;//前右輪后進
a5 = 0;//后左輪前進
a6 = 0;//后左輪后退
a7 = 0;//后右輪前進
a8 = 0;//后右輪后進
}
    }
if(Usart_Receive[9]=='2')//左轉
{
a1 = 0;//前左輪前進
a2 = 1;//前左輪后退
a3 = 1;//前右輪前進
a4 = 0;//前右輪后進
a5 = 0;//后左輪前進
a6 = 1;//后左輪后退
a7 = 1;//后右輪前進
a8 = 0;//后右輪后退
}
if(Usart_Receive[9]=='3')//右轉
{
a1 = 1;//前左輪前進
a2 = 0;//前左輪后退
a3 = 0;//前右輪前進
a4 = 1;//前右輪后進
a5 = 1;//后左輪前進
a6 = 0;//后左輪后退
a7 = 0;//后右輪前進
a8 = 1;//后右輪后退
}
if(Usart_Receive[9]=='5')//停止
{
forword_flag = 0;//前進標志位置零
back_flag = 0; //后退標志位置零
a1 = 0;//前左輪前進
a2 = 0;//前左輪后退
a3 = 0;//前右輪前進
a4 = 0;//前右輪后進
a5 = 0;//后左輪前進
a6 = 0;//后左輪后退
a7 = 0;//后右輪前進
a8 = 0;//后右輪后進
}
    }
    }
    }
    }
}

 

 

#define _USART_C_
#include "include.h"
unsigned char Usart_Receive[20]={0};
unsigned char Usart_Cnt=0;
bit Usart_AT_flage;
bit flage;
bit Command_Flag;
void InitUART(void)
{
    TMOD = 0x20;
    SCON = 0x50;
    TH1 = 0xFD;
    TL1 = TH1;
    PCON = 0x00;
    EA = 1;
    ES = 1;
    TR1 = 1;
}

void SendOneByte(unsigned char c)
{
        SBUF = c;
        while(!TI);
        TI = 0;    
}

//串行口連續發送char型數組,遇到終止號/0(空格)將停止
void UartSends(unsigned char *str)
{
    while(*str!='\0')
    {
        SBUF=*str;
        while(!TI);//等待發送完成信號(TI=1)出現
        TI=0;
        str++;
    }
}

void UARTInterrupt(void) interrupt 4
{
    RI=0;
    Usart_Receive[Usart_Cnt]=SBUF;//接收串口數據
    Usart_Cnt++;//
    //返回數據以回車結尾,有回車,而且數據個數大於2,說明接收到了數據
    if(Usart_Receive[Usart_Cnt-2]=='\r' && Usart_Receive[Usart_Cnt-1]=='\n' && Usart_Cnt >= 2)
    {
        Usart_Cnt = 0;//接收數據計數清零
        Usart_AT_flage = 1;//數據接收成功標志位
  }
    else if(Usart_Cnt > 20)//
    {
        Usart_Cnt = 0;
    }    
}

 

 

#ifndef __USART_H_
#define __USART_H_


#ifndef _USART_C_
#define _USART_ex_ extern
#else
#define _USART_ex_
#endif

_USART_ex_ unsigned char Usart_Receive[20];
_USART_ex_ unsigned char Usart_Cnt;
_USART_ex_ bit Usart_AT_flage;
_USART_ex_ bit Command_Flag;
_USART_ex_ unsigned char UsartData;
_USART_ex_ void InitUART(void);//串口初始化
_USART_ex_ void SendOneByte(unsigned char c);//發送字節型數據
_USART_ex_ void UartSends(unsigned char *str);//串行口連續發送char型數組,遇到終止號/0將停止
#endif

 

#include <REGX52.H>
#include "USART.h"
#include <string.h>

 

下載好程序,接好線,等一會用手機連接就好了,連接成功會顯示連接成功

eps8266說是3.3v供電因為我手頭沒有降壓模塊也沒有二極管所以就直接接的5v供電,不過沒有燒,正常工作,就是摸上去有點熱。其實程序還有點不夠可靠,以后再改進

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM