吉方工控G-3288-02串口通信开发测试 作者:大信 8125036 串口开发测试 G-RK3288工控板有丰富的接口,作为工业数据采集,现场控制是很好的硬件产品。在工业控制方面用的比较多的是通过串口采集数据或者传输数据,控制设备等作用。因此作为工控板支持串口通信是最基础也是最重要的功能。 联盛德的W801开发板是一款基于平头哥80X的核心的MCU,具有200M主频,288K RAM,2MFlash有I2C,SPI,UART,AD等接口,用于做前端传感器的数据采集和控制功能。W801的Uart0串口通过CH340N芯片转为USB接口。
串口通信,这里使用G-RK3288作为中控,联盛德的W801开发板作为下位机,两个设备采用USB的串口相连,即USB转串的方式进行连接,连接如下图所示:
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安装包。如下图所示:
查看系统的串口设备 安装完毕后,然后再把串口工程 Android_serialport_sample 代码复制进去。在调试程序之前,需要了解设备在系统中的文件句柄。这时只要通过ADB 工具等到系统下,查看安USB设备结构如下:
即可以看到 /dev/u*** 下所有的设备目录。在代码工程里需要遍历这些设备即可,找到我们的外设了。 串口通信程序实现 串口通信的工程由C/C++和Android两部分,C++部分主要完成设备的打开,关闭,以及相关对设备句柄的设置等操作。 主要代码如下:
- /*
- * Copyright 2009-2011 Cedric Priscal
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include "SerialPort.h"
- #include "android/log.h"
- static const char *TAG = "serial_port";
- #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
- #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
- #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
- static speed_t getBaudrate(jint baudrate) {
- switch (baudrate) {
- case 0:
- return B0;
- case 50:
- return B50;
- case 75:
- return B75;
- case 110:
- return B110;
- case 134:
- return B134;
- case 150:
- return B150;
- case 200:
- return B200;
- case 300:
- return B300;
- case 600:
- return B600;
- case 1200:
- return B1200;
- case 1800:
- return B1800;
- case 2400:
- return B2400;
- case 4800:
- return B4800;
- case 9600:
- return B9600;
- case 19200:
- return B19200;
- case 38400:
- return B38400;
- case 57600:
- return B57600;
- case 115200:
- return B115200;
- case 230400:
- return B230400;
- case 460800:
- return B460800;
- case 500000:
- return B500000;
- case 576000:
- return B576000;
- case 921600:
- return B921600;
- case 1000000:
- return B1000000;
- case 1152000:
- return B1152000;
- case 1500000:
- return B1500000;
- case 2000000:
- return B2000000;
- case 2500000:
- return B2500000;
- case 3000000:
- return B3000000;
- case 3500000:
- return B3500000;
- case 4000000:
- return B4000000;
- default:
- return -1;
- }
- }
- /*
- * Class: android_serialport_SerialPort
- * Method: open
- * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
- */
- JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open
- (JNIEnv *env, jobject thiz, jstring path, jint baudrate, jint dataBits, jint parity,
- jint stopBits,
- jint flags) {
- int fd;
- speed_t speed;
- jobject mFileDescriptor;
- /* Check arguments */
- {
- speed = getBaudrate(baudrate);
- if (speed == -1) {
- /* TODO: throw an exception */
- LOGE("Invalid baudrate");
- return NULL;
- }
- }
- /* Opening device */
- {
- ***oolean iscopy;
- const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
- LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);
- fd = open(path_utf, O_RDWR | flags);
- LOGD("open() fd = %d", fd);
- (*env)->ReleaseStringUTFChars(env, path, path_utf);
- if (fd == -1) {
- /* Throw an exception */
- LOGE("Cannot open port");
- /* TODO: throw an exception */
- return NULL;
- }
- }
- /* Configure device */
- {
- struct termios cfg;
- LOGD("Configuring serial port");
- if (tcgetattr(fd, &cfg)) {
- LOGE("tcgetattr() failed");
- close(fd);
- /* TODO: throw an exception */
- return NULL;
- }
- cfmakeraw(&cfg);
- cfsetispeed(&cfg, speed);
- cfsetospeed(&cfg, speed);
- cfg.c_cflag &= ~CSIZE;
- switch (dataBits) {
- case 5:
- cfg.c_cflag |= CS5; //使用5位数据位
- break;
- case 6:
- cfg.c_cflag |= CS6; //使用6位数据位
- break;
- case 7:
- cfg.c_cflag |= CS7; //使用7位数据位
- break;
- case 8:
- cfg.c_cflag |= CS8; //使用8位数据位
- break;
- default:
- cfg.c_cflag |= CS8;
- break;
- }
- switch (parity) {
- case 0:
- cfg.c_cflag &= ~PARENB; //无奇偶校验
- break;
- case 1:
- cfg.c_cflag |= (PARODD | PARENB); //奇校验
- break;
- case 2:
- cfg.c_iflag &= ~(IGNPAR | PARMRK); // 偶校验
- cfg.c_iflag |= INPCK;
- cfg.c_cflag |= PARENB;
- cfg.c_cflag &= ~PARODD;
- break;
- default:
- cfg.c_cflag &= ~PARENB;
- break;
- }
- switch (stopBits) {
- case 1:
- cfg.c_cflag &= ~CSTOPB; //1位停止位
- break;
- case 2:
- cfg.c_cflag |= CSTOPB; //2位停止位
- break;
- default:
- cfg.c_cflag &= ~CSTOPB; //1位停止位
- break;
- }
- if (tcsetattr(fd, TCSANOW, &cfg)) {
- LOGE("tcsetattr() failed");
- close(fd);
- /* TODO: throw an exception */
- return NULL;
- }
- }
- /* Create a corresponding file descriptor */
- {
- jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor");
- jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "", "()V");
- jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I");
- mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);
- (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint) fd);
- }
- return mFileDescriptor;
- }
- /*
- * Class: cedric_serial_SerialPort
- * Method: close
- * Signature: ()V
- */
- JNIEXPORT void JNICALL Java_android_serialport_SerialPort_close
- (JNIEnv *env, jobject thiz) {
- jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
- jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");
- jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
- jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");
- jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
- jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
- LOGD("close(fd = %d)", descriptor);
- close(descriptor);
- }
复制代码
Android部分的代码主要完成简单的一个UI的实现,完成收发数据的展示,编码格式的转换以及输入,发送按钮等人机交互部分。 主要代码如下:
测试通信结果 通过Android编译,连接,选择目标板运营,则程序将会自动安装到开发板上,并在板上运行, 首次运营时根据下位机的设置,同步设置串口参数,波特率为:115200,无校验,停止位1。设置好后,选择发现的USB串口设备,点击打开,则可以看到下位机传输过来的内容了,如下图:
开发板刷机方法 在开发调试中,因为在Android系统中打开了开发者调试模式,并且打开了root权限,在调试中会出损害系统文件的情况,导致系统异常甚至不能正常运行,此时则需要刷机,恢复到出厂状态。 相关下载工具已放到百度云盘,分享连接放在这里,需要的朋友自取:
提取码: kynu 刷机方法如下,首先下载瑞芯微开发工具 RkDevtools.exe首次启动如果是英文界面可以在设置里选择中文,则出现中文。
把开发板与PC连接好后,打开瑞芯微工具,启动后界面如下图,首先检查硬件相关信息,可以点击高级功能,分别能够读取到flash id ,ChipUnfo信息等。
进入升级固件选项,点击切换,底部的 “发现一个ADB设备”的提示会变成“发现一个LOADER设备”的提示,再点固件选择相应的出现固件文件,再点击升级即可完成升级了,升级过程在右侧信息输出框里出现相应提示。 升级完将会自动重启,又回到出厂的原始系统了。 |