日韩在线免费播放-日韩在线免费av-日韩在线免费-日韩在线毛片-国产高清不卡视频-国产高清不卡

當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Android串口調(diào)試助手實(shí)現(xiàn)

Android串口調(diào)試助手實(shí)現(xiàn) 時(shí)間:2018-08-16      來(lái)源:未知

串行接口 (Serial Interface) 是指數(shù)據(jù)一位一位地順序傳送,其特點(diǎn)是通信線路簡(jiǎn)單,只要一對(duì)傳輸線就可以實(shí)現(xiàn)雙向通信(可以直接利用電話線作為傳輸線),從而大大降低了成本,特別適用于遠(yuǎn)距離通信,但傳送速度較慢。一條信息的各位數(shù)據(jù)被逐位按順序傳送的通訊方式稱為串行通訊。串行通訊的特點(diǎn)是:數(shù)據(jù)位的傳送,按位順序進(jìn)行,少只需一根傳輸線即可完成;成本低但傳送速度慢。串行通訊的距離可以從幾米到幾千米;根據(jù)信息的傳送方向,串行通訊可以進(jìn)一步分為單工、半雙工和全雙工三種。

日常中的很多設(shè)備都是通過(guò)串口來(lái)傳輸數(shù)據(jù)的。所以,本項(xiàng)目在安卓的平臺(tái)上,建立了一個(gè)通過(guò)串口來(lái)收發(fā)數(shù)據(jù)的平臺(tái)。用戶可以通過(guò)設(shè)定不同的參數(shù)來(lái)連接不同的串口。

第 1 章 使用說(shuō)明

軟件共分為三個(gè)部分:數(shù)據(jù)接收區(qū),數(shù)據(jù)發(fā)送區(qū),參數(shù)設(shè)置區(qū)。

使用之前需要設(shè)置參數(shù):需要打開(kāi)的設(shè)備文件和打開(kāi)的波特率。

點(diǎn)擊Open就可以打開(kāi)串口,如果這時(shí)候串口有數(shù)據(jù)過(guò)來(lái),就可以在左側(cè)顯示出來(lái),同時(shí)可以設(shè)定是否以十六進(jìn)制顯示數(shù)據(jù)。

如果想要向串口發(fā)送數(shù)據(jù),在下方輸入數(shù)據(jù),點(diǎn)擊Send就可以發(fā)送。

第 2 章 環(huán)境搭建

2.1 Android 開(kāi)發(fā)環(huán)境的安裝與配置

Android應(yīng)用軟件開(kāi)發(fā)需要的開(kāi)發(fā)環(huán)境在路徑“光盤\Android應(yīng)用開(kāi)發(fā)環(huán)境\”下:

JDK: JDK\JDK8\jdk-8u5-windows-i586.exe(32bit)或者jdk-8u5-windows-x64.exe(64bit)

(從JDK 8.0開(kāi)始不支持Windows XP操作系統(tǒng),使用Windows XP的用戶可以使用JDK7目錄下的內(nèi)容)

ADT: adt-bundle-windows-x86.7z(32bit)或者adt-bundle-windows-x86_64.7z(64bit)

以下主要介紹在Windows環(huán)境下搭建Android開(kāi)發(fā)環(huán)境的步驟和注意事項(xiàng)。

2.2 安裝JDK和配置Java開(kāi)發(fā)環(huán)境

雙擊JDK\JDK8\jdk-8u5-windows-i586.exe(32bit操作系統(tǒng))或者jdk-8u5-windows-x64.exe(64bit操作系統(tǒng))進(jìn)行安裝(從JDK 8.0開(kāi)始不支持Windows XP操作系統(tǒng),使用Windows XP的用戶可以使用JDK7目錄下的內(nèi)容選擇代替JDK8目錄下的內(nèi)容)。接受許可證,選擇需要安裝的組件和安裝路徑后,單擊“下一步”按鈕,完成安裝過(guò)程。

安裝完成后,利用以下步驟檢查安裝是否成功:打開(kāi)Windows CMD窗口,在CMD窗口中輸入java –version命令,如果屏幕出現(xiàn)下圖所示的代碼信息,說(shuō)明JDK安裝成功。

XP下安裝JDK7如下:

非XP下安裝JDK8如下:

2.3 解壓adt-bundle-windows

JDK安裝成功后,使用軟件解壓ADT目錄下的adt-bundle-windows-x86.7z(32bit)或者adt-bundle-windows-x86_64.7z(64bit)。

注意:解壓路徑不包含中文;

2.4 運(yùn)行Eclipse

解壓完畢后,直接執(zhí)行其中的eclipse\eclipse.exe文件,Eclipse可以自動(dòng)找到用戶前期安裝的JDK路徑。

2.5 配置Eclipse

運(yùn)行解壓目錄下的eclipse\eclipse.exe,為自己選擇一個(gè)工作目錄Workspace,不要有中文路徑,不選擇默認(rèn)也可以。

需要為Eclipse關(guān)聯(lián)SDK的安裝路徑,即解壓路徑下的sdk目錄。在Eclipse中,點(diǎn)擊Window->Preferences,會(huì)看到其中添加了Android的配置,按圖所示的操作,然后點(diǎn)擊Apply,后點(diǎn)擊OK即可。

完成以上步驟后,設(shè)置Eclipse環(huán)境

勾選Android相關(guān)的工具,點(diǎn)擊OK(如果已經(jīng)勾選,則不理會(huì))。

第 3 章 NDK環(huán)境配置

3.1 安裝NDK工具包

安裝包已經(jīng)放到“華清遠(yuǎn)見(jiàn)開(kāi)發(fā)環(huán)境”光盤當(dāng)中,名字為“android-ndk-r10d-windows-x86”,這個(gè)是針對(duì)32位系統(tǒng)使用的工具包,如果有64位的需求可以到我們提供的網(wǎng)盤上進(jìn)行下載。

將安裝包拷貝到E:盤,雙擊程序即可在當(dāng)前路徑進(jìn)行安裝。

3.2 配置Eclipse

打開(kāi)Eclipse,點(diǎn)Window->Preferences->Android->NDK,設(shè)置NDK路徑,例如E:\ android-ndk-r10d

新建一個(gè)Android工程,在工程上右鍵點(diǎn)擊Android Tools->Add Native Support...,然后給我們的.so文件取個(gè)名字,例如:my-ndk

這時(shí)候工程就會(huì)多一個(gè)jni的文件夾,jni下有Android.mk和my-ndk.cpp文件。Android.mk是NDK工程的Makefile,my-ndk.cpp就是NDK的源文件。

完成了,然后運(yùn)行。運(yùn)行之前先編譯NDK,然后在編譯JAVA代碼。編譯也許會(huì)遇到Unable to launch cygpath. Is Cygwin on the path等問(wèn)題?如何解決?如下:

工程右鍵,點(diǎn)Properties->C/C++ Build的Building Settings中去掉Use default build command,然后輸入${NDKROOT}/ndk-build.cmd

在C/C++ Build中點(diǎn)擊Environment,點(diǎn)Add...添加環(huán)境變量NDKROOT,值為NDK的根目錄

接著,按照如下圖所示的位置,根據(jù)使用的SDK的版本的不同選擇不同的頭文件包,例如如果使用的是android4.0.3 的話,就選擇:E:\ android-ndk-r10d\platforms\android-15\arch-arm\usr\include

之后,再次編譯運(yùn)行工程,即可成功。

第 1 章 源碼編譯

1.1 導(dǎo)入源碼

打開(kāi)Eclipse環(huán)境,選擇File->Import。

然后,導(dǎo)入光盤資料中的“BlueHelper”工程,勾選下圖中的選項(xiàng)。

點(diǎn)擊finish完成工程的導(dǎo)入

1.1 運(yùn)行程序

注意:如果在調(diào)試開(kāi)發(fā)板的時(shí)候,出現(xiàn)ADB連接不上的問(wèn)題(已知華清遠(yuǎn)見(jiàn)FSPAD723開(kāi)源平板),可以試著替換Android SDK的ADB工具(把光盤\Android應(yīng)用開(kāi)發(fā)環(huán)境\ADB\ADB1.0.26\下的4個(gè)文件拷貝到用戶ADT解壓目錄下的sdk\platform-tools中)

開(kāi)發(fā)期間,在實(shí)際的設(shè)備上運(yùn)行Android程序與在模擬器上運(yùn)行該程序的效果幾乎相同,需要做的就是用USB電纜連接手機(jī)與計(jì)算機(jī),并安裝一個(gè)對(duì)應(yīng)的設(shè)備驅(qū)動(dòng)程序。如果模擬器窗口已打開(kāi),請(qǐng)將其關(guān)閉。只要將開(kāi)發(fā)平臺(tái)通過(guò)USB下載線與計(jì)算機(jī)相連,應(yīng)用程序就會(huì)在開(kāi)發(fā)平臺(tái)上加載并運(yùn)行。

在Eclipse中選擇“Run” →“Run”(或Debug)命令(或者在工程上點(diǎn)擊右鍵),這時(shí)會(huì)彈出一個(gè)窗口,讓你選擇用模擬器還是手機(jī)來(lái)顯示,如果選擇手機(jī),即可在手機(jī)上運(yùn)行該程序。

第 2 章 詳細(xì)設(shè)計(jì)

2.1 UartTool串口工具

因?yàn)楸卷?xiàng)目要連接上層java和底層c語(yǔ)言,所以需要先聲明本地方法。

NormalText Code

private static native int NativeFileOpen(String filename, int size);// 成功返回0,失敗-1

private static native int NativeFileClose();// 返回是否關(guān)閉成功

private static native int NativeFileRead(byte[] buf, int size);// 返回讀取數(shù)據(jù)的個(gè)數(shù)

private static native int NativeFileWrite(byte[] buf, int size);// 返回寫入的數(shù)據(jù)長(zhǎng)度

串口初始化函數(shù),需要傳遞想要打開(kāi)的串口的文件名和波特率。

NormalText Code

public Boolean uartInit(String filename, int size) {

if ((fd = NativeFileOpen(filename, size)) != -1) {

uartInit = true;

return true;

} else {

log.E("%%%%% _uart_init() == -1 !!!! %%%%%");

return false;

}

}

接下來(lái)要封裝讀函數(shù)和寫函數(shù),利用的是底層的read和write。

NormalText Code

public String uartRead(int num) {

byte[] data = new byte[num];

int re = 0;

if ((re = NativeFileRead(data, data.length)) > 0) {

return new String(data, 0, re);

} else {

log.E("%%%%% _uart_read() != num !!!! %%%%%");

return null;

}

}

NormalText Code

public Boolean uartWrite(byte[] data) {

if (NativeFileWrite(data, data.length) > 0) {

return true;

} else {

log.E("%%%%% _uart_write(data) == -1 !!!! %%%%%");

return false;

}

}

2.2 Uarthelper調(diào)試助手

本項(xiàng)目中,線程和UI線程通信是通過(guò)Handler 機(jī)制實(shí)現(xiàn)的。作用是將數(shù)據(jù)傳輸?shù)経I線程進(jìn)行顯示。

NormalText Code

private Handler handler = new Handler() {

@SuppressLint("SimpleDateFormat")

public void handleMessage(Message msg) {

switch (msg.what) {

case 0:

if (!check.isChecked()) {

treceive.append(recdate + " ");

} else {

treceive.append("0x" + printHex(recdate.getBytes()) + " ");

}

scroll.scrollTo(0,

treceive.getMeasuredHeight() - scroll.getHeight());

recdate = "";

break;

default:

break;

}

}

};

設(shè)定按鈕的監(jiān)聽(tīng)時(shí)間,當(dāng)點(diǎn)擊Open按鈕的時(shí)候,按照設(shè)定的參數(shù)去打開(kāi)對(duì)應(yīng)的串口,成功后啟動(dòng)讀和寫的線程,同時(shí)設(shè)定按鈕文字為Close,屏幕進(jìn)行提示打開(kāi)成功。

NormalText Code

save.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

if (open == false) {

if (!fd.getText().toString().equalsIgnoreCase("")) {

if (uart.uartInit("/dev/" + fd.getText().toString(),

rate_t) == true) {

Toast.makeText(Uarthelper.this, "打開(kāi)成功".toString(),

Toast.LENGTH_LONG).show();

log.E("打開(kāi)文件 " + "/dev/" + fd.getText().toString());

open = true;

threadon = true;

readThread = new ReadThread();

readThread.start();

save.setText("Close".toString());

} else {

Toast.makeText(Uarthelper.this,

"文件打開(kāi)失敗".toString(), Toast.LENGTH_SHORT)

.show();

}

} else {

Toast.makeText(Uarthelper.this, "請(qǐng)?zhí)顚懲暾?quot;.toString(),

Toast.LENGTH_SHORT).show();

}

} else {

Toast.makeText(Uarthelper.this, "正在關(guān)閉串口。。。".toString(),

Toast.LENGTH_LONG).show();

threadon = false;

uart.uartWrite("s".getBytes());

UartQThread uartQThread = new UartQThread();

uartQThread.start();

open = false;

save.setText("Open".toString());

}

}

});

讀取數(shù)據(jù)的線程,調(diào)用底層的uartRead函數(shù),接收到數(shù)據(jù)后,將數(shù)據(jù)存入全局變量,然后通知主線程來(lái)顯示。

NormalText Code

class ReadThread extends Thread {

String tmp = null;

@Override

public void run() {

log.E("讀取數(shù)據(jù)線程啟動(dòng)!");

while (threadon) {

tmp = uart.uartRead(10);

if (threadon) {

if (tmp == null) {

// log.E("接收數(shù)據(jù)出錯(cuò)!");

} else {

log.E("接收數(shù)據(jù) " + tmp);

recdate += tmp;

NoteThread noteThread = new NoteThread();

noteThread.start();

}

}

}

log.E("讀取數(shù)據(jù)線程結(jié)束!");

}

}

如果想要發(fā)送數(shù)據(jù),需要調(diào)用底層的uartWrite函數(shù)。

NormalText Code

send.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

if (uart.uartInit == true) {

String date = tsent.getText().toString();

if (uart.uartWrite(date.getBytes()) == true) {

// tsent.setText("");

log.E("發(fā)送數(shù)據(jù) " + date);

} else {

Toast.makeText(Uarthelper.this, "發(fā)送失敗".toString(),

Toast.LENGTH_SHORT).show();

}

} else {

Toast.makeText(Uarthelper.this, "請(qǐng)先設(shè)置串口".toString(),

Toast.LENGTH_SHORT).show();

}

}

});

2.3 NDK程序詳解

2.3.1 jni.c

這個(gè)文件的作用主要是連結(jié)上層和底層之間的函數(shù)。

首先需要定義一個(gè)結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體表明了上層函數(shù)名稱和底層函數(shù)名稱的對(duì)應(yīng)關(guān)系。并且函數(shù)名稱的書寫是有要求的,Java_cn_com_farsight_tool_UartTool_NativeFileRead類似這樣的,格式為java+程序包名+函數(shù)名稱。

NormalText Code

static JNINativeMethod gMethods[] = { { "NativeFileOpen",

"(Ljava/lang/String;I)I",

(void *) Java_cn_com_farsight_tool_UartTool_NativeFileOpen }, {

"NativeFileRead", "([BI)I",

(void *) Java_cn_com_farsight_tool_UartTool_NativeFileRead }, {

"NativeFileWrite", "([BI)I",

(void *) Java_cn_com_farsight_tool_UartTool_NativeFileWrite }, {

"NativeFileClose", "()I",

(void *) Java_cn_com_farsight_tool_UartTool_NativeFileClose }, };

int register_cn_com_farsight_tool_UartTool(JNIEnv *env) {

return jniRegisterNativeMethods(env, kClassPathName, gMethods,

sizeof(gMethods) / sizeof(gMethods[0]));

然后在這些函數(shù)中調(diào)用底層的函數(shù)來(lái)實(shí)現(xiàn)對(duì)應(yīng)的功能。

NormalText Code

jint Java_cn_com_farsight_tool_UartTool_NativeFileRead(JNIEnv* env,

jobject thiz, jbyteArray buf, jint size) {

unsigned char *buf_char = (char*) ((*env)->GetByteArrayElements(env, buf,

NULL));

int result = uart_read(buf_char, size);

(*env)->ReleaseByteArrayElements(env, buf, buf_char, 0);

return result;

}

2.3.2 onLoad.cpp

這個(gè)文件的主要作用是完成加載底層的庫(kù)文件的時(shí)候的工作。OnLoad函數(shù)在加載庫(kù)文件的時(shí)候會(huì)第一個(gè)執(zhí)行。

NormalText Code

jint JNI_OnLoad(JavaVM* vm, void* reserved) {

JNIEnv* env = NULL;

jint result = JNI_ERR;

sVm = vm;

if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

LOGE("GetEnv failed!");

return result;

}

if (register_cn_com_farsight_tool_UartTool(env) != JNI_OK) {

LOGE("can't load register_cn_com_farsight_tool_UartTool()");

goto end;

}

LOGE("loaded succeed");

result = JNI_VERSION_1_4;

end: return result;

}

jniRegisterNativeMethods函數(shù)的作用是將剛才的關(guān)系結(jié)構(gòu)體注冊(cè)進(jìn)系統(tǒng)當(dāng)中,同時(shí),尋找上層需要調(diào)用這些底層函數(shù)的類。

NormalText Code

int jniRegisterNativeMethods(JNIEnv* env, const char* className,

const JNINativeMethod* gMethods, int numMethods) {

jclass clazz;

LOGE("Registering %s natives\n", className);

clazz = env->FindClass(className);

if (clazz == NULL) {

LOGE("Native registration unable to find class '%s'\n", className);

return -1;

}

if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {

LOGE("RegisterNatives failed for '%s'\n", className);

return -1;

}

return 0;

}

2.3.3 uart.c

這個(gè)文件就是底層函數(shù)的具體實(shí)現(xiàn)了。uart_get函數(shù)的功能就是打開(kāi)串口,根據(jù)上層傳遞過(guò)來(lái)的參數(shù)和波特率來(lái)打開(kāi)設(shè)備文件。

NormalText Code

int uart_get(char *filename, int rate) { //成功返回0,失敗-1

struct termios opt;

// uart

if ((fd = open(filename, O_RDWR | O_NOCTTY, 0777)) == -1) {

LOGE("UART open error!!! :%s ", strerror(errno));

return -1;

}

//初始化串口

tcgetattr(fd, &opt);

LOGE("rate is %d", rate);

switch (rate) {

case 4800:

cfsetispeed(&opt, B4800);

cfsetospeed(&opt, B4800);

break;

case 9600:

cfsetispeed(&opt, B9600);

cfsetospeed(&opt, B9600);

break;

case 19200:

cfsetispeed(&opt, B19200);

cfsetospeed(&opt, B19200);

break;

case 38400:

cfsetispeed(&opt, B38400);

cfsetospeed(&opt, B38400);

break;

case 115200:

LOGE("rate is %d", rate);

cfsetispeed(&opt, B115200);

cfsetospeed(&opt, B115200);

break;

default:

cfsetispeed(&opt, B115200);

cfsetospeed(&opt, B115200);

break;

}

opt.c_cflag |= (CLOCAL | CREAD);

opt.c_cflag &= ~CSIZE;

opt.c_cflag &= ~CRTSCTS;

opt.c_cflag |= CS8;

opt.c_iflag |= IGNPAR;

opt.c_cflag &= ~CSTOPB;

opt.c_oflag = 0;

opt.c_lflag = 0;

tcsetattr(fd, TCSANOW, &opt);

LOGE("UART open %s succeed!!!", filename);

return 0;

}

當(dāng)要讀取數(shù)據(jù)的時(shí)候,先將上層傳遞下來(lái)的緩沖清空,使用read函數(shù)進(jìn)行數(shù)據(jù)的讀取,然后返回。

NormalText Code

int uart_read(unsigned char *buf, int size) { //返回讀取數(shù)據(jù)的個(gè)數(shù)

int len = 0;

memset(buf, 0, size);

int result = read(fd, buf, size);

if (result <= 0) {

LOGE("uart_read(%d) is error %s", size, strerror(errno));

return -1;

}

// while (result < size) {

// len = read(fd, buf + result, size - result);

// result += len;

// }

LOGE("uart_read is %s", buf);

return result;

}

直接調(diào)用write來(lái)向設(shè)備寫入數(shù)據(jù)。

NormalText Code

int uart_write(const unsigned char *buf, int size) { //返回寫入的數(shù)據(jù)長(zhǎng)度

int result = write(fd, buf, size);

if (result > 0) {

LOGE("uart write is %s", buf);

}

return result;

}

后程序結(jié)束的時(shí)候,關(guān)閉設(shè)備文件。

NormalText Code

int uart_close() {

close(fd);

LOGE("UART close succeed!!!");

return 0;

}

上一篇:linux make命令安裝詳解

下一篇:fork函數(shù)的小誤區(qū)

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺(tái)專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見(jiàn)科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號(hào)-5京公海網(wǎng)安備11010802025203號(hào)

回到頂部

主站蜘蛛池模板: 莫恭明| 拾贝的小女孩阅读理解答案| 莫比乌斯电影完整版免费观看| 小强升职记| 相识电影| 四川地图旅游地图高清版大图| 永远是少年电影免费观看| 少女第一季| 隐藏的秘密电影免费观看全集| 豪血寺一族2出招表| 会说话的金杰| 数学二年级上册答案| cctv6 节目表| 第一财经现场直播| 让我们的家更美好教学设计 | 神犬小七2| 大空头 电影| 生日特效动图| 定坤| 17岁韩国电影完整版观看免费| 帕瓦德奥特曼| 牛奶奶油是什么奶油| 小松未可子| 培根《谈读书》原文及翻译| 美女写真视频网站| 三年电影免费完整| 祈今朝电视剧| 想要女朋友菲律宾| 我的成功密码| 杨文元| 暴雪电影| 在线抖音| 安泽豪个人资料| 韩孝周超异能族| 拼音表大全图| 江苏卫视今天节目表| 朱莉安妮| 抖音充值链接| cctv体育频道5| 老炮儿演员表| 血色浪漫电视剧演员表|