瑞芯微Rockchip开发者社区
直播中

ALSET

4年用户 286经验值
擅长:可编程逻辑,电源/新能源,嵌入式技术,处理器/DSP
私信 关注
[经验]

【吉方工控G-3288-02开发板试用体验】吉方工控G-3288-02串口通信开发与开发板刷机

吉方工控G-3288-02串口通信开发测试
作者:大信 8125036
串口开发测试
      G-RK3288工控板有丰富的接口,作为工业数据采集,现场控制是很好的硬件产品。在工业控制方面用的比较多的是通过串口采集数据或者传输数据,控制设备等作用。因此作为工控板支持串口通信是最基础也是最重要的功能。
       联盛德的W801开发板是一款基于平头哥80X的核心的MCU,具有200M主频,288K RAM,2MFlash有I2C,SPI,UART,AD等接口,用于做前端传感器的数据采集和控制功能。W801的Uart0串口通过CH340N芯片转为USB接口。
11.jpg
       串口通信,这里使用G-RK3288作为中控,联盛德的W801开发板作为下位机,两个设备采用USB的串口相连,即USB转串的方式进行连接,连接如下图所示:
1.jpg
                              


Andrioid NDK开发环境准备
       对这个测试,需要在G-RK3288上开发一个串口的应用程序,用来与W801设备进行连接并进行通讯,这里需要G-RK3288支持CH340X的USB驱动,通过查询资料得知在Rk3288的android系统里已经对CH34X系列芯片有支持,在应用程序中需要打开这个USB设备并进行相应的操作即可。但这部分的接口是系统的原生接口,即不属于Android的SDK部分,那么就需要在Android应用里面通过 c/c++代码调用底层系统的接口来进行通讯。因此在Android开发环境中安装 NDK来支持C/C++对系统底层的调用。在AndroidStudio开发软件的菜单 Tools->SDK Manager里点开当前的SDK包,勾选上NDK选项,确定后即补充安装NDK安装包。如下图所示:
2.jpg
查看系统的串口设备
      安装完毕后,然后再把串口工程 Android_serialport_sample
代码复制进去。在调试程序之前,需要了解设备在系统中的文件句柄。这时只要通过ADB 工具等到系统下,查看安USB设备结构如下:
3.jpg
      即可以看到 /dev/u*** 下所有的设备目录。在代码工程里需要遍历这些设备即可,找到我们的外设了。
串口通信程序实现
      串口通信的工程由C/C++和Android两部分,C++部分主要完成设备的打开,关闭,以及相关对设备句柄的设置等操作。
主要代码如下:
  1. /*
  2. * Copyright 2009-2011 Cedric Priscal
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */

  16. #include
  17. #include
  18. #include
  19. #include
  20. #include
  21. #include
  22. #include

  23. #include "SerialPort.h"

  24. #include "android/log.h"

  25. static const char *TAG = "serial_port";
  26. #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
  27. #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
  28. #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)

  29. static speed_t getBaudrate(jint baudrate) {
  30.     switch (baudrate) {
  31.         case 0:
  32.             return B0;
  33.         case 50:
  34.             return B50;
  35.         case 75:
  36.             return B75;
  37.         case 110:
  38.             return B110;
  39.         case 134:
  40.             return B134;
  41.         case 150:
  42.             return B150;
  43.         case 200:
  44.             return B200;
  45.         case 300:
  46.             return B300;
  47.         case 600:
  48.             return B600;
  49.         case 1200:
  50.             return B1200;
  51.         case 1800:
  52.             return B1800;
  53.         case 2400:
  54.             return B2400;
  55.         case 4800:
  56.             return B4800;
  57.         case 9600:
  58.             return B9600;
  59.         case 19200:
  60.             return B19200;
  61.         case 38400:
  62.             return B38400;
  63.         case 57600:
  64.             return B57600;
  65.         case 115200:
  66.             return B115200;
  67.         case 230400:
  68.             return B230400;
  69.         case 460800:
  70.             return B460800;
  71.         case 500000:
  72.             return B500000;
  73.         case 576000:
  74.             return B576000;
  75.         case 921600:
  76.             return B921600;
  77.         case 1000000:
  78.             return B1000000;
  79.         case 1152000:
  80.             return B1152000;
  81.         case 1500000:
  82.             return B1500000;
  83.         case 2000000:
  84.             return B2000000;
  85.         case 2500000:
  86.             return B2500000;
  87.         case 3000000:
  88.             return B3000000;
  89.         case 3500000:
  90.             return B3500000;
  91.         case 4000000:
  92.             return B4000000;
  93.         default:
  94.             return -1;
  95.     }
  96. }

  97. /*
  98. * Class:     android_serialport_SerialPort
  99. * Method:    open
  100. * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
  101. */
  102. JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open
  103.         (JNIEnv *env, jobject thiz, jstring path, jint baudrate, jint dataBits, jint parity,
  104.          jint stopBits,
  105.          jint flags) {

  106.     int fd;
  107.     speed_t speed;
  108.     jobject mFileDescriptor;

  109.     /* Check arguments */
  110.     {
  111.         speed = getBaudrate(baudrate);
  112.         if (speed == -1) {
  113.             /* TODO: throw an exception */
  114.             LOGE("Invalid baudrate");
  115.             return NULL;
  116.         }
  117.     }

  118.     /* Opening device */
  119.     {
  120.         ***oolean iscopy;
  121.         const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
  122.         LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);
  123.         fd = open(path_utf, O_RDWR | flags);
  124.         LOGD("open() fd = %d", fd);
  125.         (*env)->ReleaseStringUTFChars(env, path, path_utf);
  126.         if (fd == -1) {
  127.             /* Throw an exception */
  128.             LOGE("Cannot open port");
  129.             /* TODO: throw an exception */
  130.             return NULL;
  131.         }
  132.     }

  133.     /* Configure device */
  134.     {
  135.         struct termios cfg;
  136.         LOGD("Configuring serial port");
  137.         if (tcgetattr(fd, &cfg)) {
  138.             LOGE("tcgetattr() failed");
  139.             close(fd);
  140.             /* TODO: throw an exception */
  141.             return NULL;
  142.         }

  143.         cfmakeraw(&cfg);
  144.         cfsetispeed(&cfg, speed);
  145.         cfsetospeed(&cfg, speed);


  146.         cfg.c_cflag &= ~CSIZE;
  147.         switch (dataBits) {
  148.             case 5:
  149.                 cfg.c_cflag |= CS5;    //使用5位数据位
  150.                 break;
  151.             case 6:
  152.                 cfg.c_cflag |= CS6;    //使用6位数据位
  153.                 break;
  154.             case 7:
  155.                 cfg.c_cflag |= CS7;    //使用7位数据位
  156.                 break;
  157.             case 8:
  158.                 cfg.c_cflag |= CS8;    //使用8位数据位
  159.                 break;
  160.             default:
  161.                 cfg.c_cflag |= CS8;
  162.                 break;
  163.         }

  164.         switch (parity) {
  165.             case 0:
  166.                 cfg.c_cflag &= ~PARENB;    //无奇偶校验
  167.                 break;
  168.             case 1:
  169.                 cfg.c_cflag |= (PARODD | PARENB);   //奇校验
  170.                 break;
  171.             case 2:
  172.                 cfg.c_iflag &= ~(IGNPAR | PARMRK); // 偶校验
  173.                 cfg.c_iflag |= INPCK;
  174.                 cfg.c_cflag |= PARENB;
  175.                 cfg.c_cflag &= ~PARODD;
  176.                 break;
  177.             default:
  178.                 cfg.c_cflag &= ~PARENB;
  179.                 break;
  180.         }

  181.         switch (stopBits) {
  182.             case 1:
  183.                 cfg.c_cflag &= ~CSTOPB;    //1位停止位
  184.                 break;
  185.             case 2:
  186.                 cfg.c_cflag |= CSTOPB;    //2位停止位
  187.                 break;
  188.             default:
  189.                 cfg.c_cflag &= ~CSTOPB;    //1位停止位
  190.                 break;
  191.         }

  192.         if (tcsetattr(fd, TCSANOW, &cfg)) {
  193.             LOGE("tcsetattr() failed");
  194.             close(fd);
  195.             /* TODO: throw an exception */
  196.             return NULL;
  197.         }
  198.     }

  199.     /* Create a corresponding file descriptor */
  200.     {
  201.         jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor");
  202.         jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "", "()V");
  203.         jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I");
  204.         mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);
  205.         (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint) fd);
  206.     }

  207.     return mFileDescriptor;
  208. }

  209. /*
  210. * Class:     cedric_serial_SerialPort
  211. * Method:    close
  212. * Signature: ()V
  213. */
  214. JNIEXPORT void JNICALL Java_android_serialport_SerialPort_close
  215.         (JNIEnv *env, jobject thiz) {
  216.     jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
  217.     jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");

  218.     jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
  219.     jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");

  220.     jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
  221.     jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);

  222.     LOGD("close(fd = %d)", descriptor);
  223.     close(descriptor);
  224. }


      Android部分的代码主要完成简单的一个UI的实现,完成收发数据的展示,编码格式的转换以及输入,发送按钮等人机交互部分。
主要代码如下:
  1. /*
  2. * Copyright 2009 Cedric Priscal
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */

  16. package android.serialport.sample;

  17. import android.app.Activity;
  18. import android.app.AlertDialog;
  19. import android.content.DialogInterface;
  20. import android.content.DialogInterface.OnClickListener;
  21. import android.os.Bundle;
  22. import android.serialport.SerialPort;
  23. import java.io.IOException;
  24. import java.io.InputStream;
  25. import java.io.OutputStream;
  26. import java.security.InvalidParameterException;

  27. public abstract class SerialPortActivity extends Activity {

  28.     protected Application mApplication;
  29.     protected SerialPort mSerialPort;
  30.     protected OutputStream mOutputStream;
  31.     private InputStream mInputStream;
  32.     private ReadThread mReadThread;

  33.     private class ReadThread extends Thread {

  34.         @Override
  35.         public void run() {
  36.             super.run();
  37.             while (!isInterrupted()) {
  38.                 int size;
  39.                 try {
  40.                     byte[] buffer = new byte[64];
  41.                     if (mInputStream == null) return;
  42.                     size = mInputStream.read(buffer);
  43.                     if (size > 0) {
  44.                         onDataReceived(buffer, size);
  45.                     }
  46.                 } catch (IOException e) {
  47.                     e.printStackTrace();
  48.                     return;
  49.                 }
  50.             }
  51.         }
  52.     }

  53.     private void DisplayError(int resourceId) {
  54.         AlertDialog.Builder b = new AlertDialog.Builder(this);
  55.         b.setTitle("Error");
  56.         b.setMessage(resourceId);
  57.         b.setPositiveButton("OK", new OnClickListener() {
  58.             public void onClick(DialogInterface dialog, int which) {
  59.                 SerialPortActivity.this.finish();
  60.             }
  61.         });
  62.         b.show();
  63.     }

  64.     @Override
  65.     protected void onCreate(Bundle savedInstanceState) {
  66.         super.onCreate(savedInstanceState);
  67.         mApplication = (Application) getApplication();
  68.         try {
  69.             mSerialPort = mApplication.getSerialPort();
  70.             mOutputStream = mSerialPort.getOutputStream();
  71.             mInputStream = mSerialPort.getInputStream();

  72.                         /* Create a receiving thread */
  73.             mReadThread = new ReadThread();
  74.             mReadThread.start();
  75.         } catch (SecurityException e) {
  76.             DisplayError(R.string.error_security);
  77.         } catch (IOException e) {
  78.             DisplayError(R.string.error_unknown);
  79.         } catch (InvalidParameterException e) {
  80.             DisplayError(R.string.error_configuration);
  81.         }
  82.     }

  83.     protected abstract void onDataReceived(final byte[] buffer, final int size);

  84.     @Override
  85.     protected void onDestroy() {
  86.         if (mReadThread != null) mReadThread.interrupt();
  87.         mApplication.closeSerialPort();
  88.         mSerialPort = null;
  89.         super.onDestroy();
  90.     }
  91. }

测试通信结果
      通过Android编译,连接,选择目标板运营,则程序将会自动安装到开发板上,并在板上运行,
      首次运营时根据下位机的设置,同步设置串口参数,波特率为:115200,无校验,停止位1。设置好后,选择发现的USB串口设备,点击打开,则可以看到下位机传输过来的内容了,如下图:
  
5.jpg 6.jpg 4.jpg
开发板刷机方法
      在开发调试中,因为在Android系统中打开了开发者调试模式,并且打开了root权限,在调试中会出损害系统文件的情况,导致系统异常甚至不能正常运行,此时则需要刷机,恢复到出厂状态。
      相关下载工具已放到百度云盘,分享连接放在这里,需要的朋友自取:

提取码: kynu
       刷机方法如下,首先下载瑞芯微开发工具 RkDevtools.exe首次启动如果是英文界面可以在设置里选择中文,则出现中文。 7.jpg
       把开发板与PC连接好后,打开瑞芯微工具,启动后界面如下图,首先检查硬件相关信息,可以点击高级功能,分别能够读取到flash id ,ChipUnfo信息等。
8.jpg
       进入升级固件选项,点击切换,底部的 “发现一个ADB设备”的提示会变成“发现一个LOADER设备”的提示,再点固件选择相应的出现固件文件,再点击升级即可完成升级了,升级过程在右侧信息输出框里出现相应提示。
        升级完将会自动重启,又回到出厂的原始系统了。
   9.jpg 10.jpg
   

更多回帖

发帖
×
20
完善资料,
赚取积分