久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3398|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

控制中心 - 筆記 -> S5PV210中ZigBee的Jni回調(diào)要點(diǎn)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:71922 發(fā)表于 2015-1-10 20:10 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式

由于ZigBee是用USB轉(zhuǎn)串口通訊,所以需要在內(nèi)核加上PL2303驅(qū)動(dòng)。進(jìn)入內(nèi)核源碼:make menuconfig ->
                     Device Drivers ->
                           <*> USB support ->
                                   <*> USB Serial Converter support ->
                                            <*>USB Prolific 2303 Single Port Serial Driver



啟用之后重新編譯,并燒錄到FS210中。

ZigBee 模塊是通過(guò)串口通信,需要發(fā)送什么數(shù)據(jù),只需要往串口寫(xiě)入數(shù)據(jù),里面的ZigBee即可發(fā)送數(shù)據(jù)。

Fs210 應(yīng)用程序測(cè)試:app.c
-------------------------------------------------------------------------------------------------------
#include <termios.h>    //串口相關(guān)頭文件
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


流程:
    1、打開(kāi)串口

    2、初始化串口

    3、讀寫(xiě)串口數(shù)據(jù)

    4、關(guān)閉串口



/* 初始化串口 */
void  serial_init(int fd)
{
        struct termios options;
        tcgetattr(fd, &options);
        options.c_cflag |= ( CLOCAL | CREAD );/*input mode flag:ignore modem
        options.c_cflag &= ~CSIZE;
        options.c_cflag &= ~CRTSCTS;
        options.c_cflag |= CS8;
        options.c_cflag &= ~CSTOPB; //停止位
        options.c_iflag |= IGNPAR;        // 忽略校驗(yàn)錯(cuò)誤
        options.c_oflag = 0;// 無(wú)輸出模式
        options.c_lflag = 0; //本地模式禁用
        options.c_cc[VTIME] = 0;                // 50 代表5秒 5秒內(nèi)沒(méi)有收到數(shù)據(jù)就返回
        options.c_cc[VMIN] = 2;                        // 代表收到2個(gè)字節(jié)就返回
        cfsetispeed(&options, B115200);
        cfsetospeed(&options, B115200);
        tcsetattr(fd,TCSANOW,&options);
}
/* 主函數(shù) */
int main(int argc, char **args)
{
        int fd = 0;
        char a[3] = "v";
        int size = 0;
        /* 1、打開(kāi)串口 */

        fd = open("/dev/ttyUSB0", O_RDWR);    // 因?yàn)樵撃K是USB轉(zhuǎn)串口
        if(fd<0) return 0;
        puts("串口初始化....");


        /* 2、初始化串口 */

        serial_init(fd);


        /* 3、讀寫(xiě)數(shù)據(jù) */
        // 往串口寫(xiě)數(shù)據(jù)
        write(fd, a, strlen(a));
        puts("開(kāi)始接受數(shù)據(jù)");
        while(1)
        {       
                memset(a, 0, sizeof(a));
                // 從串口讀數(shù)據(jù)

                size = read(fd, a, sizeof(a));
                printf("a = %s\n", a);               
        }


        /* 4、關(guān)閉串口 */       
        close(fd);
        return 0;
}

-------------------------------------------------------------------------------------------------------

編譯腳本:Android.mk

-------------------------------------------------------------------------------------------------------

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)


LOCAL_SRC_FILES := app.c
LOCAL_MODULE := app_c


LOCAL_SHARED_LIBRARIES := \
        libcutils


LOCAL_MODULE_TAGS := optional


include $(BUILD_EXECUTABLE)

-------------------------------------------------------------------------------------------------------


Fs210作為控制中心,需要時(shí)時(shí)刻刻與M0通訊,并把數(shù)據(jù)顯示在apk應(yīng)用上,需要采用JNI與上層APK交互。
需要采用回調(diào)機(jī)制,Jin回調(diào)Java的方法。可以采用NDK或獨(dú)立的Jni庫(kù)形式。
這里,我考慮到日后更新方便,就采用分離的Jni庫(kù)形式。

控制中心與節(jié)點(diǎn)通信的數(shù)據(jù)結(jié)構(gòu):---> 后來(lái)想想,下面這些用聯(lián)合體會(huì)更加合適一些
-------------------------------------------------------------------------------------------------------

// 節(jié)點(diǎn)標(biāo)識(shí)  
#define M0_NUM_1        1                // M0_1 標(biāo)識(shí)
#define M0_NUM_2        2                // M0_2 標(biāo)識(shí)
#define M0_NUM_3        3                // M0_3 標(biāo)識(shí)
#define M0_NUM_4        4                // M0_4 標(biāo)識(shí)
#define M0_NUM_5        5                // M0_5 標(biāo)識(shí)
#define M0_NUM_6        6                // M0_6 標(biāo)識(shí)


// 命令類(lèi)型
#define Get_Data                        21                  // 獲取數(shù)據(jù)
#define Set_Temp_Warning_val                22                // 設(shè)置溫度報(bào)警閥值
#define Set_Hum_Warning_val                23                // 設(shè)置濕度報(bào)警閥值
#define Set_Auto_Send                        25                // 設(shè)置主動(dòng)上報(bào)數(shù)據(jù)
#define Set_NoAuto_Send                        26                // 禁止主動(dòng)上報(bào)數(shù)據(jù)
                                                  
// 設(shè)備狀態(tài)
#define FAN_ON                                24                // 風(fēng)扇開(kāi)啟狀態(tài)
#define FAN_OFF                                25                // 風(fēng)扇關(guān)閉狀態(tài)
#define BEEP_ON                                26                // 蜂鳴器開(kāi)啟狀態(tài)
#define BEEP_OFF                        27                // 蜂鳴器關(guān)閉狀態(tài)


#define ZigBee_Cmd_HEAD        '$'
       
// 命令/數(shù)據(jù) 結(jié)構(gòu)體
struct ZigBee_Cmd
{
        char Head;                        // 包頭 由于從串口接數(shù)據(jù)有可能第一個(gè)字節(jié)不是頭,所以需要判斷
       
        int ID;                                // 節(jié)點(diǎn)標(biāo)識(shí)
        char CmdType;                          // 命令類(lèi)型
        char TempH;                        // 溫度整數(shù)部分               
        char TempL;                        // 溫度小數(shù)部分               
        char HumH;                        // 濕度整數(shù)部分               
        char HumL;                        // 濕度小數(shù)部分
        char AdvH;                        // 電壓整數(shù)
        char AdvL;                        // 電壓小數(shù)
        signed char x;                         // 三軸傳感器 x
        signed char y;                        // 三軸傳感器 y
        signed char z;                        // 三軸傳感器 z
        int Light;                         // 亮度
        char FAN;                         // 風(fēng)扇狀態(tài)       
        char BEEP;                        // 蜂鳴器狀態(tài)
        char Used;                        // CPU使用率
                       
        unsigned  int chksum;                // 校驗(yàn)碼
};

-------------------------------------------------------------------------------------------------------

Jni代碼
-------------------------------------------------------------------------------------------------------

在M0中提供兩種數(shù)據(jù)發(fā)送方式:
被動(dòng)獲取數(shù)據(jù):
    APK通過(guò)Jni打開(kāi)串口發(fā)送 Get_Data 指令獲取數(shù)據(jù),M0收到指令就發(fā)送一次數(shù)據(jù)。
主動(dòng)獲取數(shù)據(jù):
    APK通過(guò)Jni打開(kāi)串口發(fā)送 Set_Auto_Send 指令,M0收到指令就連續(xù)發(fā)送數(shù)據(jù)。


Jni的難點(diǎn)在于回調(diào)Java的方法和串口操作,如數(shù)據(jù)接收。

回調(diào)Java方法:
            需要?jiǎng)?chuàng)建新的線程,去回調(diào)Java的方法,所以需要利用全局變量將Jni的 JNIEnv *,, jobject* 保存,
        然后在線程里面使用。
實(shí)現(xiàn)步驟:
APK 要點(diǎn):
-------------------------------------------------------------------------------------------------------
步驟1:創(chuàng)建一個(gè)回調(diào)方法:
        private void ZigBee_Call(int ID, char TempH, char TempL, char HumH, char HumL, char AdvH,
            char AdvL, int x, int y, int z, int Light, char FAN, char BEEP, char CPUUSed)
        {
                // 通過(guò)發(fā)送Handler消息刷新APK的GUI

                return;
        }



步驟2:聲明本地方法
        public native int ZigBee_Open();
        public native int ZigBee_Cmd(char cmd, int arg1, int arg2);
        public native int ZigBee_Close();
        public native int ZigBee_StartRevc();
        public native int ZigBee_StopRevc();

        // 添加這句是為了通過(guò)javap 命令獲取其類(lèi)型簽名 獲取完后可以刪除掉

    public native void ZigBee_Call(int ID, char TempH, char TempL, char HumH, char HumL, char AdvH, char AdvL,
                        int x, int y, int z, int Light, char FAN, char BEEP, char CPUUSed);

步驟2:利用  javap -s bin\classes\com\lmx\zigbee\MainActivity 可以獲取到類(lèi)型簽名 用于給Jni構(gòu)建映射表
-------------------------------------------------------------------------------------------------------


Jni 回調(diào)要點(diǎn):
-------------------------------------------------------------------------------------------------------

要點(diǎn)1:創(chuàng)建兩個(gè)全局變量。給線程備用。
        JavaVM *gJavaVM = NULL;

        jobject gJavaObj= NULL;



要點(diǎn)2:提供一個(gè)函數(shù),或在何時(shí)的地方保存全局變量
        //注意,直接通過(guò)定義全局的JNIEnv和jobject變量,在此保存env和thiz的值是不可以在線程中使用的
        //線程不允許共用env環(huán)境變量,但是JavaVM指針是整個(gè)jvm共用的,所以可通過(guò)下面的方法保存JavaVM指針,在線程中使用
        env->GetJavaVM(&gJavaVM);
        //同理,jobject變量也不允許在線程中共用,因此需要?jiǎng)?chuàng)建全局的jobject對(duì)象在線程中訪問(wèn)該對(duì)象
        gJavaObj = env->NewGlobalRef(thiz);


要點(diǎn)3:在線程里面通過(guò)保存的全局變量去獲取Java環(huán)境變量、獲取Java層對(duì)應(yīng)類(lèi)、獲取回調(diào)函數(shù)。
        //從全局的JavaVM中獲取到環(huán)境變量
        gJavaVM->AttachCurrentThread(&env, NULL);
        //獲取Java層對(duì)應(yīng)的類(lèi)
        jclass javaClass = env->GetObjectClass(gJavaObj);;
        //獲取Java層被回調(diào)的函數(shù)
        jmethodID javaCallback = env->GetMethodID(javaClass,"ZigBee_Call","(ICCCCCCIIIICCC)V");
        //回調(diào)Java層的函數(shù)
        env->CallVoidMethod(gJavaObj, javaCallback, ZData.ID, ZData.TempH, ZData.TempL,ZData.HumH,
        ZData.HumL, ZData.AdvH, ZData.AdvL, ZData.x, ZData.y, ZData.z, ZData.Light, ZData.FAN,
        ZData.BEEP,ZData.Used);
-------------------------------------------------------------------------------------------------------


串口操作要點(diǎn):
-------------------------------------------------------------------------------------------------------

要點(diǎn)1:串口初始化,需要關(guān)注  .c_cc[VTIME]、.c_cc[VMIN]
void  serial_init(int fd)
{
        struct termios options;
        tcgetattr(fd, &options);
             options.c_cflag |= ( CLOCAL | CREAD );                                                                                  options.c_cflag &= ~CSIZE;
        options.c_cflag &= ~CRTSCTS;
        options.c_cflag |= CS8;                // 8位數(shù)據(jù)

        options.c_cflag &= ~CSTOPB;             //停止位

        options.c_iflag |= IGNPAR;                // 忽略校驗(yàn)錯(cuò)誤
        options.c_oflag = 0;                   // 無(wú)輸出模式
        options.c_lflag = 0;                   //本地模式禁用
        options.c_cc[VTIME] = 10;          // 表示 read() 超時(shí)值 50 表示 5秒后仍沒(méi)有數(shù)據(jù)則返回
        options.c_cc[VMIN] = 1;           // 表示讀到多少個(gè)字節(jié)就返回 5 表示讀完5個(gè)字節(jié)就返回
        cfsetispeed(&options, B115200);        // 設(shè)置波特率

        cfsetospeed(&options, B115200);
        tcsetattr(fd,TCSANOW,&options);
}

要點(diǎn)2:讀取數(shù)據(jù)的時(shí)候要注意,因?yàn)楣?jié)點(diǎn)發(fā)送數(shù)據(jù)的時(shí)候,控制中心的ZigBee已經(jīng)收到數(shù)據(jù),而我們還未             做好準(zhǔn)備,當(dāng)ZigBee往串口寫(xiě)數(shù)據(jù)寫(xiě)到一半的時(shí)候,我們才做好準(zhǔn)備收,這時(shí)候只能收到后半部分的數(shù)據(jù),
             如果節(jié)點(diǎn)是一直發(fā)送數(shù)據(jù),那么我們?cè)谑諗?shù)據(jù)的時(shí)候就很可能變成 第一個(gè)數(shù)據(jù)包的后半部分與第二個(gè)數(shù)據(jù)的
             前半部分組合成一個(gè)數(shù)據(jù)包,那么解析的數(shù)據(jù)自然就不是正確的。
        //線程循環(huán)
        while(gIsThreadExit)
        {
                LOGD("ZigBee_Call...");
                memset(&ZData, 0, sizeof(struct ZigBee_Cmd));
                memset(&buf, 0, sizeof(buf));
                size = 0;
                while(size != sizeof(struct ZigBee_Cmd))  // 直至接受完一個(gè)數(shù)據(jù)包
                {
                        ret = read(fd, &rd, 1);
                        if((size == 0) && (rd != ZigBee_Cmd_HEAD)
                                continue;
                        if( ret == -1 || ret == 0)      // 若出錯(cuò)則跳出循環(huán)
                                breka;
                        buf[size++] = rd;               // 若考慮優(yōu)化性能,這里可以直接用結(jié)構(gòu)體存,
                                                        // 存之前只需要用char*p = (char*)ZData  存的時(shí)候 *p++ = rd;
                }
                // 將數(shù)據(jù)拷貝到結(jié)構(gòu)體

                memcpy(&ZData, buf, sizeof(struct ZigBee_Cmd));
                校驗(yàn)數(shù)據(jù)....
                .........

                LOGD("Revc Data OK``");       
                回調(diào)Java層的函數(shù),將數(shù)據(jù)回傳...   
                .........

        }


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 日韩精品在线网站 | 亚洲精品中文字幕av | 在线成人福利 | 日本一区二区三区在线观看 | 日韩成年人视频在线 | 亚洲精品一区二区三区中文字幕 | 日本h片在线观看 | 在线免费观看黄色网址 | 日日操夜夜操天天操 | 亚洲视频在线观看 | 五月花丁香婷婷 | 久久久久久久久国产 | 亚洲一区二区电影网 | 一区二区三区四区五区在线视频 | 狠狠综合久久av一区二区小说 | 91超碰在线 | 午夜免费看| 国产成人短视频在线观看 | 日日干干| 成人福利视频 | 久久综合影院 | 99re国产视频 | 成人在线看片 | 婷婷在线视频 | 午夜在线| 亚洲精品久久久久久久久久久久久 | 久久不卡| 日韩成人免费视频 | 久久爱综合 | 国产欧美一区二区三区在线播放 | 成人a在线观看 | 国产精品久久久久久久久 | 男人天堂网址 | 欧美精品一二三区 | 免费在线成人 | 97av在线| 国产日韩精品一区 | 自拍偷拍中文字幕 | 在线一级片 | 美日韩免费 | 日韩一区二区三区在线视频 |