edit | blame | history | raw

一、安装及测试

1. 安装apk软件

通过**adb**安装apk软件:

方法一

Android adb启动任意app的几种方式_adb启动某个app的方法-CSDN博客

彻底解决INSTALL_FAILED_UPDATE_INCOMPATIBLE的安装错误-CSDN博客

adb root
adb install -r apk文件的位置
如:adb install -r E:\lingyun\RK3568\rk3568_app1.0\rk3568.apk

出现:Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package com.example.serial signatures do not match newer version; ignoring!表示系统中已经安装过这个软件,需要把之前的卸载后再重新安装
adb remount
adb pull /data/system/packages.xml
拉取了packages.xml后,打开该文件将涉及com.example.serial的地方都删除
adb push packages.xml /data/system
adb uninstall com.example.serial
adb remount
adb install -r -g E:\lingyun\RK3568\rk3568_app1.0\rk3568.apk

install_apk_method1

方法二

adb root
adb remount
adb push ...\rk3568.apk /system/app
adb shell chmod 666 /system/app/rk3568.apk
adb reboot

重启开启APP
adb shell am start -n com.example.serial/.MainActivity 

com.example.serial是包名

install_apk_method2

关闭APP

adb shell am force-stop com.example.serial

2. 模块测试

菜单:主要测试5个功能,分别是RS485通信,LED灯、CAN通信、蜂鸣器和ADC采样;点击对应的按钮进入相应的测试页面

2-Menu

2.1 测试RS485通信

2.1_RS485_main

RS485通信的页面如上所示,可以根据需要选择不同的波特率、数据位、停止位、校验位和流控制,由于在硬件中已经固定了/dev/ttyS9为RS485通信的串口,因此在串口号的选择中只有/dev/ttyS9。

  1. 打开串口

选择完串口的设置后,打开串口,若是由于权限不足则会弹出”添加权限“的提示。

chmod 666 /dev/ttyS9

2.1_RS485_open_failed

若是串口打开成功,则会以绿色字体显示”/dev/ttyS9 OPEN +串口设置“(其中校验位和流控制为None时,表示为0),如下所示。

2.1_RS485_open_sucess

  1. 发送数据

在发送数据之前,需先将串口状态转换成”发送模式“,然后在发送框中输入数据,点击”发送“即完成发送数据过程。

2.1_RS485_send

  1. 接收数据

在接收数据之前,需先将串口状态转换成”接收模式“,在发送端发送数据,然后在APP中点击”接收“按钮,就能接收到发送端发送的数据。**一次发送一次接收**。RS485是半双工通信,因此,当要发送或是接收数据时,要先改变串口的状态。

2.1_RS485_recv

2.2 测试LED灯

当按下对应的按钮后,相应的灯发生亮灭的变化,其变化同样也会显示在界面中。

例如,红灯亮起时,其上的图标也变成红色,而关闭红灯时,其上的图标变成灰色。同理,黄灯和绿灯也会发生类似的变化。

2.2_turn_off

红灯亮

2.2_red_turn_on

2.3 测试CAN通信

2.3_CAN_main

CAN通信的页面如上所示,可根据需要选择不同的can,设置发送数据帧的ID、DLC、Data。

注:在进行CAN通信前,还需进行以下设置(将can1替换成can0即可操作can0)

ip link set can1 down //关闭 can 网络
ip link set can1 up type can bitrate 800000 //设置 can1 的波特率为 800kbps,can 网络波特率最大值为 1mbps
ip link set can1 up type can //打开 can 网络
  1. 发送数据

在文本框中输入ID、DLC、Data后,点击”发送“按钮后,即可发送数据,在”发送区“会显示已发送的数据。

2.3_CAN_send

  1. 接收数据

点击”接收“按钮后,接收到的数据都会显示在”接收区“,和RS485不同,这里是”一直发送一次接收“。

2.3_CAN_recv

2.4 测试蜂鸣器

这里使用的蜂鸣器是无源蜂鸣器,用于测试pwm功能。通过设置周期和占空比可以让蜂鸣器发声。

若是由于权限问题无法打开PWM,则会弹出”添加export权限“的提示

chmod 777 /sys/class/pwm/pwmchip2/*

2.4_add_export_permission

继续运行出现”添加pwm0权限”的提示

chmod 777 /sys/class/pwm/pwmchip2/pwm0/*

2.4_add_pwm0_permission

如下所示,设置周期为1000000,周期50000,点击”播放“,成功运行出现弹窗提醒

2.4_PWM_play

暂停播放

2.4_PWM_stop

2.5 测试ADC采样

ADC的串口设置和RS485类似,只不过ADC通信中所使用的是十六进制数据。

串口设置:波特率(115200),数据位(8),停止位(1),校验位(None),流控制(None)

2.5_open_ADC

打开串口后,在操作设置中选择电流或电压,选择要读取数据的通道。

例如,读取第0通路的电流

2.5_get_current_channel0

读取第0通道的电压

2.5_get_voltage_channel0

其他通路的操作和上面类似

二、各模块接口函数说明

每个模块的功能由四个文件共同组成:

  1. xxxActivity.java

UI界面的功能实现。位于:\app\src\main\java\com\example\serial\xxxActivity.java

  1. xxxControl.java

API函数声明。位于:\app\src\main\java\com\example\serial\xxxControl.java

  1. xxx_control.cpp

API函数实现。位于:\app\src\main\cpp\xxx_control.cpp

  1. activity_xxx.xml

UI界面设计。位于:\app\src\main\res\layout\activity_xxx.xml

1. RS485

1.1 RS485Activity.java

\app\src\main\java\com\example\serial\RS485Activity.java

实现RS485通信界面中各个按钮的跳转,数据的获取。

1.2 RS485Control.java

\app\src\main\java\com\example\serial\RS485Control.java

  1. 打开串口并设置串口的波特率、数据位、校验位、停止位、流控制。

java public static native int openSerialPort(String path, long baudRate, int dataBits, int parity, int stopBits, int flowControl, int maxLen);

path: 串口地址(/dev/ttyS9),baudRate:串口的波特率,dataBits:数据位,parity:校验位,stopBits:停止位,flowControl:流控制(通常设置为0,表示None)。**成功返回0,失败返回负数, 打开串口的权限不足返回1**。

  1. 关闭串口

java public static native int closeSerialPort();

成功返回0,失败返回-1。

  1. 发送数据

java public static native int sendToPort(String msg, int len);

msg:发送的数据,String类型;len:发送数据的长度。成功返回>0,失败返回<0。

  1. 接收数据

java public static native String recvFromPort(int len, int timeout);

len:表示接收数据的长度;timeout:超时时间,单位为ms。**成功返回接收到的数据,失败返回NULL**。

  1. 修改串口状态

java public static native int changeState(int state);

RS485是半双工通信,发送和接收取决于gpiochip4 26引脚的高低电平,设置为低电平发送,高电平接收。成功返回0,失败返回-1.

1.3 rs485_control.cpp

\app\src\main\cpp\rs485_control.cpp。此文件包含RS485Control.java中函数的实现。

  1. 串口结构体:

```C
typedef struct comport_s
{
char devname[12];
unsigned int databit, parity, stopbit, flowctrl;
long baudrate;

   int             fd;
   int             frag_size;

}comport_t;
```

  1. 获取波特率

C static speed_t getBaudRate(int baudRate);

将int类型的波特率转换成speed_t类型。

包含:0、50、75、110、134、150、200、300、600、1200、1800、2400、4800、9600、19200、38400、57600、115200、230400、460800、500000、576000、921600、1000000、1152000、1500000、2000000、2500000、3000000、3500000、4000000;若是baudRate不在这个范围内,则返回-1。

(有关RS485的UI设计位于\app\src\main\res\layout\activity_rs485.xml)

2. LED

2.1 LedActivity.java

实现按钮的功能

2.2 LedControl.java

 public static native int ledCtrl(int which, int status);

which:表示要操作的灯的位置,取值为0,1,2;status:表示灯的状态,0表示开灯,1表示关灯。(低电平点亮,高电平关闭)。成功返回0,失败返回一个小于0的负数。

2.3 led_control.cpp

enum
{
    LED_R=0,
    LED_Y,
    LED_G,
    LED_MAX,
};

typedef struct led_gpio_s
{
    int                           idx;
    int                           gpio;
    const char                   *desc;
    struct gpiod_line            *line;
}led_gpio_t;

定义结构体,gpio表示引脚编号,如红灯对应的是gpiochip0 18,那么gpio=18;desc:表示对该引脚的描述,可以表示为”red“;

led_gpio_t leds[LED_MAX] =
        {
                {LED_R, 18, "red", NULL},
                {LED_Y, 22, "yellow", NULL},
                {LED_G, 20, "green", NULL},
        };

预先定义数组用来存放每个灯所对应的信息。

3. CAN

3.1 CanActivity.java

UI界面的功能实现

3.2 CanControl.java

  1. 发送数据

java public static native int sendMessage(String id, String dlc, String data, String ifname);

待发送的CAN帧由id,dlc,data三部分组成,ifname表示can设备的名称(can0或can1)。成功返回0,失败返回小于0的负数。

  1. 接收数据

java public static native String receiveMessage(String ifname);

​ ifname表示can设备的名称(can0 或can1).成功返回接收到的数据,失败返回NULL。返回的数据格式为”ID=xx DLC=xx Data=xx xx xx xx“。

3.3 can_control.cpp

CanControl.java中的函数实现

4. PWM-蜂鸣器

4.1 BuzzerActivity.java

UI界面的功能实现

4.2 BuzzerControl.java

  1. 打开PWM

java public native static int pwmOpen(String id);

打开需要操作的pwm设备,例如需要操作的pwm为: /sys/class/pwm/pwmchip2,因此id=”2“,需要操作的是/sys/class/pwm/pwmchip2/pwm0,会先判断pwm0是否存在,不存在就会导入。成功返回0,失败返回小于0的负数,打开设备的权限不足返回1.

  1. 配置PWM

java public native static int pwmConfig(String attr, String val);

​ 以/sys/class/pwm/pwmchip2为例,通过配置/sys/class/pwm/pwmchip2/pwm0的period和duty_cycle可以让该PWM输出不同的方波。attr表示需要配置的文件名(period或duty_cycle),val表示写入该文件的值。打开设备的权限不足返回1,配置的值无效返回2.

4.3 buzzer_control.cpp

BuzzerControl.java的函数实现

5. ADC采样

5.1 AdcActivity.java

UI界面的功能实现

5.2 AdcControl.java

  1. 打开串口

Java public static native int openComport(String path, long baudRate, int dataBits, int parity, int stopBits, int flowControl);

path: 串口(/dev/ttyS6); baudRate: 波特率(115200);dataBits:数据位(8);parity:奇偶校验(0表示None,1表示奇校验,2表示偶校验);stopBits:停止位(1);flowControl:流控制(0表示无,1表示硬件流,2表示软件流)。成功返回0,失败返回小于0的负数,当返回1时表示打开串口的权限不够。

  1. 关闭串口

Java public static native int closeComport();

成功返回0,失败返回小于0的负数。

  1. 发送数据

java public static native int sendToPort(String operate, String channel);

向串口发送数据,operate:操作电流或电压;channel:欲操作的通道。

下图是ADC串口协议,通过添加类型和通道号即可形成完整的读指令报文。

5.3_ADC_protocol

  1. 接收数据

Java public static native String recvFromPort(int len, int timeout);

从串口读取数据并返回。len:表示读取数据的最大长度;timeout:超时时间(单位:ms)。成功返回读取到的数据,失败返回NULL。

根据接收到的数据即可计算其所对应的电流或电压。

设接收的数据为:AA 55 01 00 95 01 BB 71 //01 95 -> 405 单位0.01mA,即4.05mA,其中AA 55为报文头,01表示电流,00表示通道0,95 01表示通道0的电流值,BB 71表示CRC校验码。由于是低字节先发送,因此在计算电流值时,实际的顺序是 01 95 => 电流 = 0*16^3 + 1*16^2 + 9*16^1 + 5*16^0 = 405, 单位是0.01mA,最后得到电流值为4.05mA。

5.3 adc_control.cpp

typedef struct comport_s
{
    char            devname[12];
    unsigned int    databit, parity, stopbit, flowctrl;
    long            baudrate;

    int             fd;
    int             frag_size;
}comport_t;

串口配置结构体。

static speed_t getBaudRate(int baudRate)

将int类型的波特率转换成可以识别的波特率.

unsigned short crc_modbus(unsigned char *ptr, int len)

根据十六进制值计算CRC16校验码。ptr:需要计算的十六进制字符数组;len:表示需要计算的字符长度。以读指令为例,设unsigned char read[6] = {0xAA, 0x55, 0x01, 0x00},那么它的CRC校验码为uint16_t crc = crc_modbus(read, 4), 完整的读指令为read[4] = crc & 0xFF; read[5] = (crc >> 8) & 0xFF.

void calculate(char *result, unsigned char *data, int len)

计算ADC返回结果的数值,result用于存放返回的结果,格式为"电流/电压-通道X=....";data表示ADC串口返回的十六进制结果;len表示data的数据长度。

openComport, closeComport, sendToPort, recvFromPort的函数实现。

三、项目配置

3-gradle

3-sdk

3-minSDK

ndk:25.1.8937393

CMake:3.22.1, 3.18.1

外部配置:libgpiod库。