当前位置: 首页 > news >正文

Android 中的串口开发

一:背景

本文着重讲安卓下的串口。

由于开源的Android在各种智能设备上的使用越来越多,如车载系统等。在我们的认识中,Android OS的物理接口一般只有usb host接口和耳机接口,但其实安卓支持各种各样的工业接口,如HDMI、usb、网口、串口等等。

下图就是一块Android工业板,标圈的DB9(也叫RS232串口)就是串口中的一种形态。

 

二、什么是串口?

串行端口 ,即:SerialPort,简称串口,主要用于数据被逐位按顺序传送的通讯方式称为串口通讯(简单来讲就是按顺序一位一位地传输数据)。

三、串口的一般形态

串口一般有RS232和RS485之分,485串口可以使用RS-232转RS-485串口的转换器转换。

RS232:

232协议的串口是全双工 的,它允许数据同时接收和发送,但RS232的理论传输距离只有10米。

RS-485:

485是半双工的,半双工意味着同一时间只能收/发,就像是独木桥,同时只能有一个方向的人流通过,如果对向有来人则会造成数据丢失,RS485的理论距离是1200峭,通常如果要远距离使用的话会使用485串口,短距离则可以使用232。

四、串口的使用

无论是Android、windows还是Linux,串口的使用都要以下几步:

  1. 打开串口

  2. 串口配置(一般为:波特率、数据位、停止位和奇偶校验

  3. 串口操作(读/写,无非就是输入输出流的操作罢了

  4. 关闭串口

五、代码实践

package com.xz.andfasterserialport;import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import tp.xmaihh.serialport.SerialHelper;
import tp.xmaihh.serialport.bean.ComBean;
import tp.xmaihh.serialport.stick.AbsStickPackageHelper;
import tp.xmaihh.serialport.utils.ByteUtil;public class MainActivity extends AppCompatActivity implements View.OnClickListener{private Button leftReduce;private Button leftAdd;private Button buyWine;private TextView wine_number;private String yellowWineType = "01";@BindView(R.id.rg_type)RadioGroup mRgType;private SerialHelper serialHelper;private boolean isHexType = false;private String text = "";private Handler mHandler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {ComBean comBean = (ComBean) msg.obj;String time = comBean.sRecTime;String rxText;rxText = new String(comBean.bRec);if (isHexType) {//转成十六进制数据rxText = ByteUtil.ByteArrToHex(comBean.bRec);}text += "Rx-> " + time + ": " + rxText + "\r" + "\n";//mEtReadContent.setText(text);return false;}});private RadioButton radioButton1;private RadioButton radioButton2;private RadioButton radioButton3;private RadioButton radioButton4;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);initSerialConfig();//下面的两行设置全屏,隐藏系统状态栏getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);leftReduce = findViewById(R.id.left_reduce);leftAdd = findViewById(R.id.left_add);buyWine = findViewById(R.id.buy_wine);wine_number = findViewById(R.id.wine_number);radioButton1 = findViewById(R.id.rb_mk);radioButton2 = findViewById(R.id.rb_ls);radioButton3 = findViewById(R.id.rb_lx);radioButton4 = findViewById(R.id.rb_fzz);leftReduce.setOnClickListener(this);leftAdd.setOnClickListener(this);buyWine.setOnClickListener(this);radioButton1.setOnClickListener(this);radioButton2.setOnClickListener(this);radioButton3.setOnClickListener(this);radioButton4.setOnClickListener(this);}private void initSerialConfig() {//初始化SerialHelper对象,设定串口名称和波特率serialHelper = new SerialHelper(Const.SPORT_NAME, Const.BAUD_RATE) {@Overrideprotected void onDataReceived(ComBean paramComBean) {Message message = mHandler.obtainMessage();message.obj = paramComBean;mHandler.sendMessage(message);}};/** 默认的BaseStickPackageHelper将接收的数据扩展成64位,一般用不到这么多位* 我这里重新设定一个自适应数据位数的*/serialHelper.setStickPackageHelper(new AbsStickPackageHelper() {@Overridepublic byte[] execute(InputStream is) {try {int available = is.available();if (available > 0) {byte[] buffer = new byte[available];int size = is.read(buffer);if (size > 0) {return buffer;}} else {SystemClock.sleep(50);}} catch (IOException e) {e.printStackTrace();}return null;}});}//设置数据格式为十六进制还是其他,我们希望isHexType = true@Overrideprotected void onDestroy() {super.onDestroy();serialHelper.close();serialHelper = null;}//打开串口方法public void openSerialPort() {if (serialHelper.isOpen()) {Toast.makeText(this, Const.SPORT_NAME + "串口已经打开", Toast.LENGTH_SHORT).show();return;}try {serialHelper.open();} catch (Exception e) {e.printStackTrace();}Toast.makeText(this, Const.SPORT_NAME + "串口打开成功", Toast.LENGTH_SHORT).show();}//关闭串口方法public void closeSerialPort() {if (serialHelper.isOpen()) {serialHelper.close();Toast.makeText(this, Const.SPORT_NAME + "串口已经关闭", Toast.LENGTH_SHORT).show();}}@Overridepublic void onClick(View v) {int id = v.getId();switch (id) {case R.id.left_reduce:String stringValue1 = wine_number.getText().toString();//Log.d("XTQXTQXTQ",stringValue1);int value1 = Integer.parseInt(stringValue1);//Log.d("XTQXTQXTQ",value1+"");if ((value1 > 50)) {int newValue1 = value1 - 10;wine_number.setText(newValue1 + "");}break;case R.id.left_add:String stringValue2 = wine_number.getText().toString();//Log.d("XTQXTQXTQ",stringValue2);int value2 = Integer.parseInt(stringValue2);//Log.d("XTQXTQXTQ",value2+"");if ((value2 < 150)) {int newValue2 = value2 + 10;wine_number.setText(newValue2 + "");}break;case R.id.buy_wine:Toast.makeText(this,"开始发送串口数据",Toast.LENGTH_LONG).show();openSerialPort();if (!serialHelper.isOpen()) {Toast.makeText(this, Const.SPORT_NAME + "串口没打开 发送失败", Toast.LENGTH_SHORT).show();return;}int sendContentInt = Integer.parseInt(wine_number.getText().toString());//Log.d("100转十六进制" ,String.format("%02x", 100));String sendContent = "FB01"+yellowWineType+"00"+String.format("%x", sendContentInt)+"00"+"00"+"FE";Log.d("100转十六进制内容" ,sendContent);isHexType = true;//String sendContent = "FB010200960000FE";if (isHexType) {serialHelper.sendHex(sendContent);} else {serialHelper.sendTxt(sendContent);}case R.id.rb_mk:yellowWineType = "01";break;case R.id.rb_ls:yellowWineType = "02";break;case R.id.rb_lx:yellowWineType = "03";break;case R.id.rb_fzz:yellowWineType = "04";break;default:break;}}//十六进制校验位checkSum
}
package com.xz.andfasterserialport;public class Const {//串口 波特率public static final String SPORT_NAME = "/dev/ttyS1";public static final int BAUD_RATE = 9600;public static final String TXT_TYPE_SEND = "hello";public static final String HEX_TYPE_SEND = "123ABC";
}

主要思路:

添加依赖

首先,你需要在你的Android项目中添加依赖。确保项目build.gradle(Module级别)文件中有以下配置:

allprojects {repositories {maven { url 'https://jitpack.io' } // 或者使用作者推荐的仓库地址}
}dependencies {implementation 'com.github.xiaozhuang799:AndFasterSerialPort:latest.version'
}

初始化并使用串口

接下来,在你的Activity或Service中,初始化SerialHelper对象,并配置必要的串口参数:

import com.example.andfasterserialport.SerialHelper;// 假设已经定义了串口名和波特率
final String SERIAL_PORT_NAME = "/dev/ttyS0"; // 根据实际情况更改
final int BAUD_RATE = 9600; // 设置波特率SerialHelper serialHelper = new SerialHelper(SERIAL_PORT_NAME, BAUD_RATE) {@Overrideprotected void onDataReceived(ComBean paramComBean) {// 处理接收到的数据byte[] data = paramComBean.getData();// 你的逻辑代码}
};// 打开串口
serialHelper.open();// 发送数据示例
byte[] sendBuffer = "Hello, Serial Port!".getBytes();
serialHelper.send(sendBuffer);// 不要忘记在适当的时候关闭串口
serialHelper.close();

 确保在使用串口前,已添加必要的权限到AndroidManifest.xml:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 对于Android 6.0及以上,还需要在运行时请求这些权限 -->

参考项目地址:
GitCode - 全球开发者的开源社区,开源代码托管平台

相关文章:

Android 中的串口开发

一&#xff1a;背景 本文着重讲安卓下的串口。 由于开源的Android在各种智能设备上的使用越来越多&#xff0c;如车载系统等。在我们的认识中&#xff0c;Android OS的物理接口一般只有usb host接口和耳机接口&#xff0c;但其实安卓支持各种各样的工业接口&#xff0c;如HDM…...

TensorRt OP

在TensorRT中&#xff0c;OP&#xff08;Operations&#xff0c;操作&#xff09;是指网络中的基本计算单元&#xff0c;类似于数学中的运算符。每个OP执行一个特定的计算任务&#xff0c;例如卷积、矩阵乘法、激活函数等。TensorRT通过识别和优化这些OP来提高深度学习模型的推…...

构建负责任的人工智能:数据伦理与隐私保护

构建负责任的人工智能&#xff1a;数据伦理与隐私保护 目录 &#x1f31f; 数据伦理的重要性&#x1f4ca; 公平性评估&#xff1a;实现无偏差的模型&#x1f512; 数据去标识化&#xff1a;保护用户隐私的必要手段&#x1f50d; 透明性与问责&#xff1a;建立可信的数据处理…...

微信小程序live-pusher和video同时使用,video播放声音时时大时小

一、遇到的问题 微信小程序live-pusher和video同时使用,video播放声音时有时无时大时小 二、排查流程 业务是模拟面试,每道题一个推流live-pusher和一个面试题video,一次面试有多道面试题,页面就一个live-pusher和一个video,切换面试题时给live-pusher和video重新赋值u…...

MySQL 分库分表实战

在当今互联网时代&#xff0c;数据量的增长呈爆炸式趋势&#xff0c;传统的单库单表架构已经难以满足大规模数据存储和高并发访问的需求。MySQL 分库分表技术应运而生&#xff0c;它可以有效地提高数据库的性能、扩展性和可用性。本文将详细介绍 MySQL 分库分表的实战经验。 一…...

MySQL—CRUD—进阶—(二) (ಥ_ಥ)

文本目录&#xff1a; ❄️一、新增&#xff1a; ❄️二、查询&#xff1a; 1、聚合查询&#xff1a; 1&#xff09;、聚合函数&#xff1a; 2&#xff09;、GROUP BY子句&#xff1a; 3&#xff09;、HAVING 子句&#xff1a; 2、联合查询&#xff1a; 1&#xff09;、内连接…...

时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解

时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解 目录 时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 (创新独家)TTNRBO-VMD改进牛顿-拉夫逊优化算优化变分模态分解TTNRBO–VMD 优化VMD分解层数K和…...

2024“源鲁杯“高校网络安全技能大赛-Misc-WP

Round 1 hide_png 题目给了一张图片&#xff0c;flag就在图片上&#xff0c;不过不太明显&#xff0c;写个python脚本处理一下 from PIL import Image ​ # 打开图像并转换为RGB模式 img Image.open("./attachments.png").convert("RGB") ​ # 获取图像…...

CSS行块标签的显示方式

块级元素 标签&#xff1a;h1-h6&#xff0c;p,div,ul,ol,li,dd,dt 特点&#xff1a; &#xff08;1&#xff09;如果块级元素不设置默认宽度&#xff0c;那么该元素的宽度等于其父元素的宽度。 &#xff08;2&#xff09;所有的块级元素独占一行显示. &#xff08;3&#xff…...

Go 语言中的 for range 循环教程

在 Go 语言中&#xff0c;for range 循环是一个方便的语法结构&#xff0c;用于遍历数组、切片、映射和字符串。本教程将通过示例代码来帮助理解如何在 Go 中使用 for range 循环。 package mainimport "fmt"func main() {// 遍历切片并计算和nums : []int{2, 3, 4}…...

青训营 X 豆包MarsCode 技术训练营--小M的比赛胜场计算

问题描述 小M参加了一场n个人的比赛&#xff0c;比赛规则是所有选手两两对决。每个人有一个能力值&#xff0c;对应着他们的序号。参赛者同时被分为黄色或蓝色两种颜色。比赛胜负的规则如下&#xff1a; 当比赛双方颜色不同时&#xff0c;能力值大的选手获胜&#xff1b; 当比…...

海王3纯源码

海王3是一款热门的捕鱼类游戏&#xff0c;其纯源码为开发者提供了一个完整的游戏开发基础。该源码包括客户端和服务端的完整架构&#xff0c;支持多人在线竞技模式和丰富的游戏玩法。服务端采用C语言编写&#xff0c;并使用MySQL数据库来存储玩家数据&#xff0c;确保数据处理的…...

【ShuQiHere】Linux 系统中的硬盘管理详解:命令与技巧

【ShuQiHere】 &#x1f4bd; 在 Linux 系统中&#xff0c;硬盘管理不仅仅是存储数据的操作&#xff0c;更涉及系统性能、数据安全和稳定性的优化。无论你是系统管理员、开发者还是 Linux 爱好者&#xff0c;掌握硬盘管理的基础操作都非常有用。本文将从硬盘健康检查、分区管理…...

数据结构之堆和二叉树的简介

1.树 1.1 树的概念与结构 如图所示&#xff0c;树是⼀种非线性的数据结构&#xff0c;它是由 n &#xff08;n>0&#xff09; 个有限结点组成⼀个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 …...

微信小程序上传图片添加水印

微信小程序使用wx.chooseMedia拍摄或从手机相册中选择图片并添加水印&#xff0c; 代码如下&#xff1a; // WXML代码&#xff1a;<canvas canvas-id"watermarkCanvas" style"width: {{canvasWidth}}px; height: {{canvasHeight}}px;"></canvas&…...

xshell5找不到匹配的host key算法

xshell5找不到匹配的host key算法&#xff0c;是因为电脑客户端不支持服务器的算法&#xff0c;因此需要再服务器增加算法。 下面以Ubuntu系统为例&#xff0c;修改下面的文件 sudo vim /etc/ssh/sshd_config 增加下面算法 KexAlgorithms diffie-hellman-group-exchange-…...

Linux中安装Tomcat

文章目录 一、Tomcat介绍1.1、Tomcat是什么1.2、Tomcat的工作原理1.3、Tomcat适用的场景1.4、Tomcat与Nginx、Apache比较1.4.1、优势1.4.2、劣势1.4.3、定位功能 1.5、Tomcat 的主要组件1.6、Tomcat 的主要配置文件 二、Tomcat安装2.1、查看可用的JDK2.2、安装OpenJDK 112.3、配…...

RV1126音视频学习(二)-----VI模块

文章目录 前言2.RV1126的视频输入vi模块2.1什么是VI模块2.3RV1126VI模块主要APIRK_MPI_SYS_Init()RK_MPI_VI_SetChnAttrRK_MPI_VI_EnableChnRK_S32 RK_MPI_VI_DisableChnRK_MPI_VI_StartStreamRK_MPI_SYS_GetMediaBufferRK_MPI_MB_GetPtrRK_MPI_MB_GetSizeRK_MPI_MB_ReleaseBuf…...

「C/C++」C++17 之 std::string_view 轻量级字符串视图

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...

Linux内核-内核模块内核参数

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们的Linux进阶部分&#xff0c;到目前为止&#xff0c;已经讲过&#xff1a;硬件&#xff0c;日常运维&#xff0c;基础软…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...