我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android硬件通信之 串口通信

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android硬件通信之 串口通信

一,串口介绍

1 串口简介

串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口;

串行接口(SerialInterface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢;

2 串口使用场景

串口是一种用于android开发板对硬件设备通信的一种协议,通过发送某种指令控制硬件设备,通常用于物联网设备的信息传输,比如切割器,打印机,ATM吐卡机、IC/ID卡读卡等。

3 波特率

波特率表示串口传输速率,用来衡量数据传输的快慢,即单位时间内载波参数变化的次数,如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps。波特率与距离成反比,波特率越大传输距离相应的就越短;

4 数据位

这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。如何设置取决于你想传送的信息;

5 停止位

用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢;

6 校验位

在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位;

7 串口地址

不同操作系统的串口地址,Android是基于Linux的所以一般情况下使用Android系统的设备串口地址为/dev/ttyS0;

  • /dev的串口包括:虚拟串口,真实串口,USB转串口
  • 真实串口:/dev/tty0..tty1这个一般为机器自带COM口
  • 虚拟串口:/dev/ttyS1...ttyS2...ttyS3...均为虚拟console,同样可以作为输入输出口
  • USB转串口:/dev/tty/USB0

二 Android中串口的实践

1 由于串口底层需要调用C代码,所以需要用jni来进行C交互,下面是全部的C代码,以及JNI调用

1 SerialPort.h

#include #ifndef _Included_android_serialport_SerialPort#define _Included_android_serialport_SerialPort#ifdef __cplusplusextern "C" {#endifJNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open  (JNIEnv *, jobject, jstring, jint, jint, jint, jint, jint);JNIEXPORT void JNICALL Java_android_serialport_SerialPort_close  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif#ifndef _Included_android_serialport_SerialPort_Builder#define _Included_android_serialport_SerialPort_Builder#ifdef __cplusplusextern "C" {#endif#ifdef __cplusplus}#endif#endif

2 SerialPort.c

#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;    }}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;        {        speed = getBaudrate(baudrate);        if (speed == -1) {                        LOGE("Invalid baudrate");            return NULL;        }    }        {        jboolean 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) {                        LOGE("Cannot open port");                        return NULL;        }    }        {        struct termios cfg;        LOGD("Configuring serial port");        if (tcgetattr(fd, &cfg)) {            LOGE("tcgetattr() failed");            close(fd);                        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);                        return NULL;        }    }        {        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;}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);}

3 gen_SerialPort_h.sh 生成java的文件目录

#!/bin/shjavah -o SerialPort.h -jni -classpath ../java android.serialport.SerialPort

4 SerialPort.java jni对应的java文件

package android.serialport;import android.util.Log;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import java.io.DataOutputStream;import java.io.File;import java.io.FileDescriptor;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public final class SerialPort {    private static final String TAG = "SerialPort";    public static final String DEFAULT_SU_PATH = "/system/bin/su";    private static String sSuPath = DEFAULT_SU_PATH;    private File device;    private int baudrate;    private int dataBits;    private int parity;    private int stopBits;    private int flags;        public static void setSuPath(@Nullable String suPath) {        if (suPath == null) {            return;        }        sSuPath = suPath;    }        @NonNull    public static String getSuPath() {        return sSuPath;    }        private FileDescriptor mFd;    private FileInputStream mFileInputStream;    private FileOutputStream mFileOutputStream;        public SerialPort(@NonNull File device, int baudrate, int dataBits, int parity, int stopBits,                      int flags) throws SecurityException, IOException {        this.device = device;        this.baudrate = baudrate;        this.dataBits = dataBits;        this.parity = parity;        this.stopBits = stopBits;        this.flags = flags;                Log.e(TAG, "SerialPort: canRead" + device.canRead());        if (!device.canRead() || !device.canWrite()) {            try {                                Process su;                su = Runtime.getRuntime().exec(sSuPath);                String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" + "exit\n";                su.getOutputStream().write(cmd.getBytes());                if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {                    throw new SecurityException();                }            } catch (Exception e) {                e.printStackTrace();                throw new SecurityException();            }        }        mFd = open(device.getAbsolutePath(), baudrate, dataBits, parity, stopBits, flags);        if (mFd == null) {            Log.e(TAG, "native open returns null");            throw new IOException();        }        mFileInputStream = new FileInputStream(mFd);        mFileOutputStream = new FileOutputStream(mFd);    }        public SerialPort(@NonNull File device, int baudrate) throws SecurityException, IOException {        this(device, baudrate, 8, 0, 1, 0);    }        public SerialPort(@NonNull File device, int baudrate, int dataBits, int parity, int stopBits)            throws SecurityException, IOException {        this(device, baudrate, dataBits, parity, stopBits, 0);    }    // Getters and setters    @NonNull    public InputStream getInputStream() {        return mFileInputStream;    }    @NonNull    public OutputStream getOutputStream() {        return mFileOutputStream;    }        @NonNull    public File getDevice() {        return device;    }        public int getBaudrate() {        return baudrate;    }        public int getDataBits() {        return dataBits;    }        public int getParity() {        return parity;    }        public int getStopBits() {        return stopBits;    }    public int getFlags() {        return flags;    }    // JNI    private native FileDescriptor open(String absolutePath, int baudrate, int dataBits, int parity,           int stopBits, int flags);    public native void close();        public void tryClose() {        try {            mFileInputStream.close();        } catch (IOException e) {            //e.printStackTrace();        }        try {            mFileOutputStream.close();        } catch (IOException e) {            //e.printStackTrace();        }        try {            close();        } catch (Exception e) {            //e.printStackTrace();        }    }    static {        System.loadLibrary("serial_port");    }    public static Builder newBuilder(File device, int baudrate) {        return new Builder(device, baudrate);    }    public static Builder newBuilder(String devicePath, int baudrate) {        return new Builder(devicePath, baudrate);    }    public final static class Builder {        private File device;        private int baudrate;        private int dataBits = 8;        private int parity = 0;        private int stopBits = 1;        private int flags = 0;        private Builder(File device, int baudrate) {            this.device = device;            this.baudrate = baudrate;        }        private Builder(String devicePath, int baudrate) {            this(new File(devicePath), baudrate);        }                public Builder dataBits(int dataBits) {            this.dataBits = dataBits;            return this;        }                public Builder parity(int parity) {            this.parity = parity;            return this;        }                public Builder stopBits(int stopBits) {            this.stopBits = stopBits;            return this;        }                public Builder flags(int flags) {            this.flags = flags;            return this;        }                public SerialPort build() throws SecurityException, IOException {            return new SerialPort(device, baudrate, dataBits, parity, stopBits, flags);        }    }    public static void checkFilePermission(File file) {        Log.e(TAG, "canRead: " + file.canRead());        Log.e(TAG, "canWrite: " + file.canWrite());        if (!file.canRead() || !file.canWrite()) {            try {                                Process su;                su = Runtime.getRuntime().exec(sSuPath);                String cmd = "chmod 7777 " + file.getAbsolutePath() + "\n" + "exit\n";                su.getOutputStream().write(cmd.getBytes());                Log.e(TAG, "checkFilePermission: " + file.getAbsolutePath());                if ((su.waitFor() != 0) || !file.canRead() || !file.canWrite()) {                    throw new SecurityException();                }            } catch (Exception e) {                e.printStackTrace();                Log.e(TAG, "checkFilePermission: Exception:" + e.getMessage());                throw new SecurityException();            }        }    }    //隐藏系统导航栏    public void hideBottomNavation() {        chmod("mount -o remount -w /system");        chmod("chmod 777 /system");        chmod("echo qemu.hw.mainkeys=1 >> /system/build.prop");    }    public void chmod(String instruct) {        try {            Process process = null;            DataOutputStream os = null;            process = Runtime.getRuntime().exec("su");            os = new DataOutputStream(process.getOutputStream());            os.writeBytes(instruct);            os.flush();            os.close();        } catch (Exception ex) {            ex.printStackTrace();        }    }}

5 CMakeLists.txt,编译c或c++程序的规则文件

Cmake在Jni那篇讲过,这个地方在讲下

CMake是一个可以跨平台的编译工具,可以用简单的语句来描述所有平台的编译过程。他能够输出各种各样的 makefile 或者工程文件。和make与makefile类似,我们在使用CMake时同样也需要一个文件来提供规则,这个文件就是CMakeLists

使用CMake编写跨平台工程的流程如下:

(1)编写源文件

(2)编写CMakeLists.txt

(3)由CMake根据CMakeLists.txt来生成相应的makefile文件

(4)使用make并根据makefile调用gcc来生成相应的可执行文件。

# Sets the minimum version of CMake required to build your native library.# This ensures that a certain set of CMake features is available to# your build.cmake_minimum_required(VERSION 3.4.1)# Specifies a library name, specifies whether the library is STATIC or# SHARED, and provides relative paths to the source code. You can# define multiple libraries by adding multiple add.library() commands,# and CMake builds them for you. When you build your app, Gradle# automatically packages shared libraries with your APK.add_library( # Specifies the name of the library.             serial_port             # Sets the library as a shared library.             SHARED             # Provides a relative path to your source file(s).             class="lazy" data-src/main/cpp/SerialPort.c )             find_library( # Sets the name of the path variable.              log-lib              # Specifies the name of the NDK library that              # you want CMake to locate.              log )# Specifies libraries CMake should link to your target library. You# can link multiple libraries, such as libraries you define in this# build script, prebuilt third-party libraries, or system libraries.target_link_libraries( # Specifies the target library.                       serial_port                       # Links the target library to the log library                       # included in the NDK.                       ${log-lib} )

5 调用串口-连接,并获取输入输出流

Runnable serialConnectRunnable = new Runnable() {            @Override            public void run() {                try {                    if (mSerialPort == null) {                        mSerialPort = new SerialPort(new File(path), baudrate);                        mOutputStream = mSerialPort.getOutputStream();                        mInputStream = mSerialPort.getInputStream();             }                } catch (SecurityException e) {                    ToastUtil.showToast(App.getInstance(), "You do not have read/write permission to the serial port.");                } catch (IOException e) {                    ToastUtil.showToast(App.getInstance(), "The serial port can not be opened for an unknown reason.");                } catch (InvalidParameterException e) {                    ToastUtil.showToast(App.getInstance(), "Please configure your serial port first.");                }                //Serial结束            }        };

 2.6 读取串口消息

 private class ReadThread extends Thread {        @Override        public void run() {            super.run();            while (!isInterrupted()) {                int size;                try {                    byte[] buffer = new byte[512];                    if (mInputStream == null) return;                    size = mInputStream.read(buffer);                    if (size > 0) {                        String mReception=new String(buffer, 0, size);                        String msg = mReception.toString().trim();                        Log.e(TAG, "接收短消息:" + msg);                    }                } catch (IOException e) {                    e.printStackTrace();                    return;                }            }        }    }

7 发送串口指令

 private class WriteRunnable implements Runnable {        @Override        public void run() {            try {                String cmd="KZMT;";                Log.e(TAG, "发送短消息:" + cmd);                mOutputStream.write(cmd.getBytes());                mOutputStream.flush();            } catch (IOException e) {            }        }    }

8 断开关闭串口

public void closeSerialPortStream() {try {if (mOutputStream != null) {mOutputStream.close();mOutputStream = null;}if (mInputStream != null) {mInputStream.close();mInputStream = null;}if (mSerialPort != null) {mSerialPort.close();mSerialPort = null;}  } catch (Exception e) {e.printStackTrace();}}

三 google官方串口工具类

1 除了上面自己编程C底层文件,也可以直接用google官方的串口工具SDK(android-serialport-api),Github串口Demo地址:https://github.com/licheedev/Android-SerialPort-API

2 依赖:

allprojects {    repositories {        ...        jcenter()        mavenCentral() // since 2.1.3    }}dependencies {        implementation 'com.licheedev:android-serialport:2.1.3'}

3 使用

// 默认8N1(8数据位、无校验位、1停止位)// Default 8N1 (8 data bits, no parity bit, 1 stop bit)SerialPort serialPort = new SerialPort(path, baudrate);// 可选配置数据位、校验位、停止位 - 7E2(7数据位、偶校验、2停止位)// or with builder (with optional configurations) - 7E2 (7 data bits, even parity, 2 stop bits)SerialPort serialPort = SerialPort     .newBuilder(path, baudrate)// 校验位;0:无校验位(NONE,默认);1:奇校验位(ODD);2:偶校验位(EVEN)// Check bit; 0: no check bit (NONE, default); 1: odd check bit (ODD); 2: even check bit (EVEN)//    .parity(2) // 数据位,默认8;可选值为5~8// Data bit, default 8; optional value is 5~8//    .dataBits(7) // 停止位,默认1;1:1位停止位;2:2位停止位// Stop bit, default 1; 1:1 stop bit; 2: 2 stop bit//    .stopBits(2)     .build();    // read/write to serial port - needs to be in different thread!InputStream in = serialPort.getInputStream();OutputStream out = serialPort.getOutputStream();// closeserialPort.tryClose();

四 总结

串口通讯使用到进程、Linux指令、JNI等,但本质最终还是获得一个输入输出流去进行读写操作;

串口通讯对于Android开发者来说,仅需关注如何连接、操作(发送指令)、读取数据。

大部分的物联网通信本质上都是获取io流,通过io流进行数据的传输和读取,比如蓝牙,wifi等,只不过蓝牙,wifi是通过Socket协议维持一个长连接进行通信 

来源地址:https://blog.csdn.net/qq_29848853/article/details/130258387

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android硬件通信之 串口通信

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

硬件通信:串口、I2C、SPI、I2S 开发例程

我们做一个简单的串口通信实验,将一串自定义数据通过Hi3861的UART1发送到蓝牙模块(或者其他开发板)。开发流程有以下几步:配置并开启串口、编写发送\\读取任务逻辑、开启任务线程、编译运行测试。

如何实现 Java 串口通信的双向通信?(Java串口通信如何实现双向通信)

在Java编程中,串口通信是一种常见的用于与外部设备进行数据交互的方式。实现双向通信可以让Java程序与串口设备进行有效的数据传输,无论是发送命令还是接收设备的反馈。以下是实现Java串口通信双向通信的详细步骤:一、准备工作
如何实现 Java 串口通信的双向通信?(Java串口通信如何实现双向通信)
Java2024-12-17

Android 串口通信编程及串口协议分析

Android 串口通信编程:嵌入式编程和可穿戴设备及智能设备都会用到串口,这里就带大家分析下, 一,android串口通信串口通信采用一个第三方开源项目,实现串口数据收发。1. 使用了http://code.google.com/p/an
2022-06-06

Java 串口通信(RS232/485)

Java 串口通信(RS232/485) 一.串口通信页面二.串口服务实现1.Java 串口通信配置1.扩展包和依赖库2.Pom配置 2.启动类3.工具包类1.Common2.Crc16Modbus3.SerialUtil
2023-08-17

Python的串口通信(pyserial

串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。串口是计算机上一种非常通用的设备通信协议。pyserial模
2023-01-31

Android USB转串口通信开发实例详解

Android USB转串口通信开发实例详解 好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信
2022-06-06

Java 串口通信的安全性如何?(java串口通信的安全性如何 )

在Java开发中,串口通信是一种常见的与外部设备进行数据交互的方式。然而,随着网络安全威胁的不断增加,串口通信的安全性也成为了开发者关注的重点。本文将深入探讨Java串口通信的安全性问题,并提供一些解决方案和最佳实践。一、串口通信的基本概念
Java 串口通信的安全性如何?(java串口通信的安全性如何  )
Java2024-12-15

QT如何实现串口通信

小编给大家分享一下QT如何实现串口通信,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言:如果用qt写程序作为上位机,然后通过和usb和下位机通信的时候,就需要用
2023-06-15

PHP怎么使用串口通信

本篇内容主要讲解“PHP怎么使用串口通信”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP怎么使用串口通信”吧!php在部分应用偶尔和串口直接通信,需要和rs232、rs485接口上的数据进行
2023-06-20

C#如何实现串口通信

这篇文章主要讲解了“C#如何实现串口通信”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#如何实现串口通信”吧!1.基本概念2.前端winForm布局如下(仅仅为了实现功能,布局略丑)3.代
2023-06-29

C#怎么实现串口通信

本篇内容介绍了“C#怎么实现串口通信”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!框架准备出于简单考虑,首先创建一个Winform项目,本文
2023-07-05

delphi串口通信怎么编写

在Delphi中实现串口通信,可以使用Windows API函数来进行操作。首先,在程序的uses部分,添加Windows单元。usesWindows;声明一些常量和变量,用于存储串口参数。constReadBufferSize = 102
delphi串口通信怎么编写
2023-10-28

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录