精华内容
下载资源
问答
  • 而这些不管是485也好,232的板子也好,都会用到串口通讯,去往下位机发送指令操控。下面是我个人的一些理解,发送串口指令的方法都是一样的,各位用的时候直接拷贝过去,改一下波特率和串口号就可以测试了。总代码:...

    最近好多做安卓端跟硬件交互的,比如一些智能家居,贩卖机的。

    而这些不管是485也好,232的板子也好,都会用到串口通讯,去往下位机发送指令操控。下面是我个人的一些理解,发送串口指令的方法都是一样的,各位用的时候直接拷贝过去,改一下波特率和串口号就可以测试了。

    总代码:一个activity,两个工具类,一个声明全局变量的类,布局有一个edit发送指令,一个发送按钮,一个接收数据显示的textview

    至于jni的一些文件夹和一些so文件就要自己去弄了,

    activity的xml布局:

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">

    android:id="@+id/et_main_input"

    android:layout_width="match_parent"

    android:layout_height="40dp"

    android:background="@drawable/cycle_corner_border"

    android:textSize="18sp"

    android:layout_marginTop="10dp"

    android:layout_marginLeft="20dp"

    android:layout_marginRight="20dp"

    android:paddingLeft="8dp"

    android:hint="输入的指令"/>

    android:id="@+id/btn_main_send"

    android:layout_width="100dp"

    android:layout_height="wrap_content"

    android:layout_gravity="center_horizontal"

    android:text="发送"/>

    android:id="@+id/tv_main_show"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:textSize="18sp"

    android:layout_marginTop="10dp"

    android:layout_marginLeft="20dp"

    android:layout_marginRight="20dp"

    android:hint="这里显示接收到的串口数据"/>

    MainActivity:

    public class MainActivity extends Activity {

    private EditText editInput;

    private Button btnSend;

    private static TextView textShow;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    init();

    }

    /**

    * 初始化UI控件

    */

    private void init() {

    editInput = findViewById(R.id.et_main_input);

    btnSend = findViewById(R.id.btn_main_send);

    textShow = findViewById(R.id.tv_main_show);

    //打开串口

    SerialPortUtil.openSrialPort();

    btnSend.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    onSend();//点击发送调用onSend

    }

    });

    }

    /**

    * 发送串口数据

    */

    private void onSend() {

    String input = editInput.getText().toString();

    if(TextUtils.isEmpty(input)){

    editInput.setError("要发送的数据不能为空");

    return;

    }

    //发送指令

    SerialPortUtil.sendSerialPort(input);

    }

    /**

    * 刷新UI界面

    * @param data 接收到的串口数据

    */

    public static void refreshTextView(String data){

    Log.i(TAG, "refreshTextView: "+strTo16(data));//打印接收到的数据

    textShow.setText(textShow.getText().toString()+";"+strTo16(data));

    }

    /**

    * 字符串转化成为16进制字符串

    * @param s

    * @return

    */

    public static String strTo16(String s) {

    String str = "";

    for (int i = 0; i < s.length(); i++) {

    int ch = (int) s.charAt(i);

    String s4 = Integer.toHexString(ch);

    str = str + s4;

    }

    return str;

    }

    }

    SerialPortUtil工具类

    public class SerialPortUtil {

    public static SerialPort serialPort = null;

    public static InputStream inputStream = null;

    public static OutputStream outputStream = null;

    public static Thread receiveThread = null;

    public static boolean flag = false;

    public static Handler handler = new Handler() {

    @Override

    public void handleMessage(Message msg) {

    }

    };

    /**

    * 打开串口的方法

    */

    public static void openSrialPort(){

    Log.i("test","打开串口");

    try {

    serialPort = new SerialPort(new File("/dev/"+ IConstant.PORT),IConstant.BAUDRATE,0);

    //获取打开的串口中的输入输出流,以便于串口数据的收发

    inputStream = serialPort.getInputStream();

    outputStream = serialPort.getOutputStream();

    flag = true;

    receiveSerialPort();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    /**

    *关闭串口的方法

    * 关闭串口中的输入输出流

    * 然后将flag的值设为flag,终止接收数据线程

    */

    public static void closeSerialPort(){

    Log.i("test","关闭串口");

    try {

    if(inputStream != null) {

    inputStream.close();

    }

    if(outputStream != null){

    outputStream.close();

    }

    flag = false;

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    /**

    * 发送串口数据的方法

    * @param data 要发送的数据

    */

    public static void sendSerialPort(String data){

    Log.i("test","发送串口数据");

    try {

    byte[] sendData = data.getBytes();

    outputStream.write(sendData);

    outputStream.flush();

    Log.i(TAG, "sendSerialPort: "+sendData);

    Log.i("test","串口数据发送成功");

    } catch (IOException e) {

    e.printStackTrace();

    Log.i("test","串口数据发送失败");

    }

    }

    /**

    * 接收串口数据的方法

    */

    public static void receiveSerialPort(){

    Log.i("test","接收串口数据");

    if(receiveThread != null)

    return;

    /*定义一个handler对象要来接收子线程中接收到的数据

    并调用Activity中的刷新界面的方法更新UI界面

    */

    final Handler handler = new Handler(){

    @Override

    public void handleMessage(Message msg) {

    MainActivity.refreshTextView(msg.getData().getString("data"));

    }

    };

    /*创建子线程接收串口数据

    */

    receiveThread = new Thread(){

    @Override

    public void run() {

    while (flag) {

    try {

    byte[] readData = new byte[1024];

    if (inputStream == null) {

    return;

    }

    int size = inputStream.read(readData);

    if (size>0 && flag) {

    String recinfo = new String(readData,0,size);

    Log.i("test", "接收到串口数据:" + recinfo);

    /*将接收到的数据封装进Message中,然后发送给主线程

    */

    Message message = new Message();

    Bundle bundle = new Bundle();

    bundle.putString("data",recinfo);

    message.setData(bundle);

    handler.sendMessage(message);

    }

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    };

    //启动接收线程

    receiveThread.start();

    }

    }

    SerialPort类

    public class SerialPort {

    private static final String TAG = "SerialPort";

    private FileDescriptor mFd;

    private FileInputStream mFileInputStream;

    private FileOutputStream mFileOutputStream;

    public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {

    //检查访问权限,如果没有读写权限,进行文件操作,修改文件访问权限

    if (!device.canRead() || !device.canWrite()) {

    try {

    //通过挂载到linux的方式,修改文件的操作权限

    Process su = Runtime.getRuntime().exec("/system/xbin/su");

    String cmd = "chmod 777 " + 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, flags);

    if (mFd == null) {

    Log.e(TAG, "native open returns null");

    throw new IOException();

    }

    mFileInputStream = new FileInputStream(mFd);

    mFileOutputStream = new FileOutputStream(mFd);

    }

    // Getters and setters

    public InputStream getInputStream() {

    return mFileInputStream;

    }

    public OutputStream getOutputStream() {

    return mFileOutputStream;

    }

    // JNI(调用java本地接口,实现串口的打开和关闭)

    /**串口有五个重要的参数:串口设备名,波特率,检验位,数据位,停止位

    其中检验位一般默认位NONE,数据位一般默认为8,停止位默认为1*/

    /**

    * @param path 串口设备的据对路径

    * @param baudrate 波特率

    * @param flags 校验位

    */

    private native static FileDescriptor open(String path, int baudrate, int flags);

    public native void close();

    static {//加载jni下的C文件库

    System.loadLibrary("serial_port");

    }

    }

    IConstant

    public interface IConstant {

    String PORT = "填写你那边需要连接的串口号";//串口号

    int BAUDRATE = ;//波特率

    }

    展开全文
  • 1 #include23 //------------------串口通信协议-----------------//4 /*5 客户端数据包格式解释(长度恒为15):6 例如:A01_fmq_01Off___#7 A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)8 01-----...

    1 #include

    2

    3 //------------------串口通信协议-----------------//4 /*

    5 客户端数据包格式解释(长度恒为15):6 例如:A01_fmq_01Off___#7 A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)8 01-----设备代号9 fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部10 #---------数据包的结束标记11

    12 服务器端数据包格式解释(长度恒为15):13 例如:A02_SenT010250#14 A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)15 02-----设备代号16 SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部17 #---------数据包的结束标记18 */

    19 char buf_string[16]; //定义数据包长度为15个字符

    20 #define deviceID_1Bit ‘0‘ //用于串口通信时,定义本地设备ID的第1位

    21 #define deviceID_2Bit ‘2‘ //用于串口通信时,定义本地设备ID的第2位

    22 #define datapackage_headflag ‘A‘ //用于串口通信时,定义数据包头部的验证标记

    23

    24 char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,‘_‘,‘S‘,‘e‘,‘n‘,‘T‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘#‘};25 char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,‘_‘,‘B‘,‘e‘,‘a‘,‘t‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘#‘};26 //----------------------------------------------//27 /*******************************28 串口通信29 MCU:89C52RC 11.0592MHz30

    31 //11.0592MHz 0xd0 1200bps32 //12MHz 0xcc 1200bps33 //11.0592MHz 0xfa 9600bps34 //0xf4 11.0592MHz 0xf3 12MHz 4800bps35 //均在SMOD=1的情况下(波特率倍增模式)36 *******************************/

    37 //串口发送函数

    38 void PutString(unsigned char *TXStr)39 {40 ES=0;41 while(*TXStr!=0)42 {43 SBUF=*TXStr;44 while(TI==0);45 TI=0;46 TXStr++;47 }48 ES=1;49 }50 //串口接收函数

    51 bit ReceiveString()52 {53 char * RecStr=buf_string;54 char num=0;55 unsigned char count=0;56 loop:57 *RecStr=SBUF;58 count=0;59 RI=0;60 if(num<14) //数据包长度为15个字符,尝试连续接收15个字符

    61 {62 num++;63 RecStr++;64 while(!RI)65 {66 count++;67 if(count>130)return 0; //接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现"数据包被分割",默认count=130

    68 }69 gotoloop;70 }71 return 1;72 }73 //定时器1用作波特率发生器

    74 voidInit_USART()75 {76 SCON=0x50; //串口方式1,使能接收

    77 TMOD|=0x20; //定时器1工作方式2(8位自动重装初值)

    78 TMOD&=~0x10;79 TH1=0xfa; //9600bps

    80 TL1=0xfa;81 PCON|=0x80; //SMOD=1

    82 TR1=1;83 TI=0;84 RI=0;85 //PS=1;//提高串口中断优先级

    86 ES=1; //开启串口中断使能

    87 }88 //比较指令头部

    89 bit CompareCMD_head(charCMD_head[])90 {91 unsigned charCharNum;92 for(CharNum=0;CharNum<4;CharNum++) //指令长度为10个字符

    93 {94 if(!(buf_string[CharNum+4]==CMD_head[CharNum]))95 {96 return 0; //指令头部匹配失败

    97 }98 }99 return 1; //指令头部匹配成功

    100 }101 //比较指令尾部(start:从哪里开始比较,quality:比较多少个字符,CMD_tail[]:要比较的字符串)

    102 bit CompareCMD_tail(unsigned char start,unsigned char quality,charCMD_tail[])103 {104 unsigned charCharNum;105 for(CharNum=0;CharNum

    115 {116 //PutString(buf_string);117 if(buf_string[0]==datapackage_headflag&&buf_string[14]==‘#‘) //进行数据包头尾标记验证

    118 {119 switch(buf_string[1]) //识别发送者设备ID的第1位数字

    120 {121 case ‘0‘:122 switch(buf_string[2]) //识别发送者设备ID的第2位数字

    123 {124 case ‘3‘:125 if(CompareCMD_head("Ligt")) //判断指令头部是否为"Ligt"

    126 {127 //下面是指令尾部分析

    128 switch(buf_string[8])129 {130 case ‘0‘:131 switch(buf_string[9])132 {133 case ‘0‘:134

    135 return 0;136 case ‘1‘:137 if(CompareCMD_tail(10,3,"Off")) //A03_Ligt01Off_#

    138 {139 //要执行的代码

    140 return 1;141 }142 if(CompareCMD_tail(10,3,"On_"))143 {144

    145 return 1;146 }147 return 0;148 default:149 return 0;150 }151 case ‘1‘:152

    153 default:154 return 0;155 }156 }157 if(CompareCMD_head("SenT"))158 {159

    160

    161 }162 if(CompareCMD_head("jdq_"))163 {164

    165

    166 }167 if(CompareCMD_head("Try!"))168 {169

    170

    171 }172 return 0;173

    174 default:175 return 0;176 }177 default:178 return 0;179 }180 }181 return 0;182 }183 /************************184 中断函数185 ************************/

    186 //串口中断服务函数-----------

    187 void USART() interrupt 4 //标志位TI和RI需要手动复位,TI和RI置位共用一个中断入口

    188 {189 if(ReceiveString())190 {191 //数据包长度正确则执行以下代码

    192 Deal_UART_RecData();193 }194 else

    195 {196 //数据包长度错误则执行以下代码197 //LED1=~LED1;

    198 }199 RI=0; //接收并处理一次数据后把接收中断标志清除一下,拒绝响应在中断接收忙的时候发来的请求

    200 }201 /***************************202 主函数203 ***************************/

    204 voidmain()205 {206 EA=1;207 Init_USART();208 while(1)209 {210 //PutString(buf_string);//空格20H,回车0DH

    211

    212 }213 }

    展开全文
  • 从树莓派的相关资料我们可以看到,树莓派有两个串口可以使用,一个是硬件串口(/dev/ttyAMA0),另一个是mini串口(/dev/ttyS0)。硬件串口有单独的波特率时钟源,性能好,稳定性强;mini串口功能简单,稳定性较差,...

    从树莓派的相关资料我们可以看到,树莓派有两个串口可以使用,一个是硬件串口(/dev/ttyAMA0),另一个是mini串口(/dev/ttyS0)。硬件串口有单独的波特率时钟源,性能好,稳定性强;mini串口功能简单,稳定性较差,波特率由CPU内核时钟提供,受内核时钟影响。

    树莓派(3/4代)板载蓝牙模块,默认的硬件串口是分配给蓝牙模块使用的,而性能较差的mini串口是分配给GPIO串口 TXD0、RXD0。

    因为树莓派初始时默认把性能较差的mini串口分配给GPIO上的TX、RX。我们要使用性能好的串口就需要把两者交换过来。以下是交换的步骤:

    • 1.运行命令,查看串口分配情况
    ls /dev -al
    

    在这里插入图片描述

    • 2.由于硬件串口分配给板载蓝牙使用,所以要释放掉,并设置硬件串口分配给GPIO串口。
      首先登陆终端后,输入sudo raspi-config命令进入树莓派系统配置界面,选择第五个Interfacing Options:
      在这里插入图片描述
      在这里插入图片描述
    • 3.选择关闭串口登录功能,打开硬件串口调试功能:在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      1. 设置硬件串口为GPIO串口
        接着将串口配置为我们的GPIO串口,对输入命令
    sudo vim /boot/config.txt
    
    • 5.将下面两行代码添加到最后:
    dtoverlay=miniuart-bt
    force_turbo=1
    

    • 6.树莓派重启,再次输出:
    ls /dev -al
    

    可以看到;两个串口互换了位置:
    在这里插入图片描述

    • 7 禁用串口的控制台功能
      前面步骤已经交换了硬件串口与mini串口的映射关系,但是,现在还不能使用树莓派串口模块与电脑进行通信,因为,树莓派gpio口引出串口默认是用来做控制台使用的,即是为了用串口控制树莓派,而不是通信。所以我们要禁用此默认设置。

    首先执行命令如下:

    sudo systemctl stop serial-getty@ttyAMA0.service
    sudo systemctl disable serial-getty@ttyAMA0.service
    

    然后执行命令:

    sudo nano /boot/cmdline.txt
    并删除语句console=serial0,115200(没有的话就不需要此步骤)
    

    删除语句:(没有的话就不需要此步骤)

    console=serial0,115200
    
    • 8 测试与验证串口通讯功能
      这里使用三种方式进行测试验证, c语言下使用wiringPi库, python语言下使用serial包,最后命令行使用minicom工具。

    先安装以上开发工具:

    sudo apt-get install wiringpi
    sudo apt-get install python-serial
    sudo apt-get install minicom
    

    将usb转ttl模块引脚的GND、TX、RX分别与树莓派的GND、RX、TX连接;电脑端启用串口调试助手,波特率设置一致。

    Python语言实现:

    # -*- coding: utf-8 -*
    import serial
    import time
    
    ser = serial.Serial("/dev/ttyAMA0",115200)
    
    if not ser.isOpen():
        print("open failed")
    else:
        print("open success: ")
        print(ser)
    
    try:
        while True:
            count = ser.inWaiting()
            if count > 0:
                recv = ser.read(count)
                print("recv: " + recv)
            	ser.write(recv)
            sleep(0.05) 
    except KeyboardInterrupt:
        if ser != None:
            ser.close()
    
    

    C语言实现:

    #include <stdio.h>
    #include <wiringPi.h>
    #include <wiringSerial.h>
      
    int main()
    {
        int fd;
        if(wiringPiSetup()<0) {
            return 1;
        }
    
        //if((fd=serialOpen("/dev/ttyS0",115200))<0) { // gpio 使用mini串口
        if((fd=serialOpen("/dev/ttyAMA0",115200))<0) { // gpio 使用硬件串口
            return 1;
        }
     
        printf("serial test output ...\n");
        serialPrintf(fd,"1234567890abcdef");
     
        serialClose(fd);
        return 0;
    }
    
    

    树莓派上用Python写的串口发送(16进制)、接收数据(16进制),把16进制的数组转成数组,然后提取出来,在转换成16进制,在转换成10进制。

    import RPi.GPIO as GPIO
    import serial
    import time
    import binascii
    
    GPIO.setmode(GPIO.BCM)
    
    s = serial.Serial("/dev/ttyAMA0",9600)
        
        
        send_data = bytes.fromhex('A3 00 A2 A4 A5')
        s.write(send_data)
        time.sleep(1)
        # rece_data = s.read(10)
        # 接收返回的16进制数组,并把数组转换成字符
        print(send_data)
        rece_data = str(binascii.b2a_hex(s.read(10)))[10:16]
        rece_data_High_16 = rece_data[0:2]   # 数据高16位
        rece_data_High_8  = rece_data[2:4]   # 数据高8位
        rece_data_Low_8   = rece_data[4:6]   # 数据低8位的第1print(rece_data)
        print(str("yuanshi:{}".format(rece_data)))
        print(str("rece_data_High_16 :{}".format(rece_data_High_16)))   # 数据高16位的第1print(str("rece_data_High_8 :{}".format(rece_data_High_8)))     # 数据高8位的第1print(str("rece_data_Low_8 :{}".format(rece_data_Low_8)))       # 数据低8位的第1位
    
        rece_data_High_16_to_int = int(rece_data_High_16)
        rece_data_High_8_to_int  = int(rece_data_High_8)
        rece_data_Low_8_to_int   = int(rece_data_Low_8,16)    # 将16进制转换成10进制
    
        # 重量运算计算公式 rece_data_High_16 * 65536 +  rece_data_High_8 * 256 + rece_data_Low
        g = ((rece_data_High_16_to_int * 65536) + (rece_data_High_8_to_int * 256) + (rece_data_Low_8_to_int))
        print("重量:{}".format(g) + "g")
    
        time.sleep(3)
        
        
        
    
    展开全文
  • 根据了解得到,硬件是通过rs485进行串口通讯的,需要发送16进制命令给仪器,然后通过轮询来得到数据。需要先要下载RXTX的jar包,win64位下载地址:http://pan.baidu.com/s/1o6zLmTc);将解压后的rxtxParallel.dll和...

    最近项目有一个空气检测仪,需要得到空气检测仪的实时数据,保存到数据库当中。根据了解得到,硬件是通过rs485进行串口通讯的,需要发送16进制命令给仪器,然后通过轮询来得到数据。

    需要先要下载RXTX的jar包,win64位下载地址:http://pan.baidu.com/s/1o6zLmTc);将解压后的rxtxParallel.dll和rxtxSerial.dll两个文件放在%JAVA_HOME%/jre/bin目录下,这样该包才能被正常的加载和调用。

    代码如下:

    package com.gpdi.sericlport;

    import gnu.io.*;

    import java.io.FileInputStream;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.OutputStream;

    import java.sql.PreparedStatement;

    import java.sql.Connection;

    import java.sql.SQLException;

    import java.sql.Timestamp;

    import java.text.SimpleDateFormat;

    import java.util.*;

    import java.util.concurrent.BlockingQueue;

    import java.util.concurrent.LinkedBlockingQueue;

    import com.gpdi.utils.*;

    public class ContinueRead extends Thread implements SerialPortEventListener { // SerialPortEventListener

    // 监听器,我的理解是独立开辟一个线程监听串口数据

    // 串口通信管理类

    static CommPortIdentifier portId;

    /* 有效连接上的端口的枚举 */

    static Enumeration> portList;

    InputStream inputStream; // 从串口来的输入流

    static OutputStream outputStream;// 向串口输出的流

    static SerialPort serialPort; // 串口的引用

    // 堵塞队列用来存放读到的数据

    private BlockingQueue msgQueue = new LinkedBlockingQueue();

    @Override

    /**

    * SerialPort EventListene 的方法,持续监听端口上是否有数据流

    */

    public void serialEvent(SerialPortEvent event) {//

    switch (event.getEventType()) {

    case SerialPortEvent.BI:

    case SerialPortEvent.OE:

    case SerialPortEvent.FE:

    case SerialPortEvent.PE:

    case SerialPortEvent.CD:

    case SerialPortEvent.CTS:

    case SerialPortEvent.DSR:

    case SerialPortEvent.RI:

    case SerialPortEvent.OUTPUT_BUFFER_EMPTY:

    break;

    case SerialPortEvent.DATA_AVAILABLE:// 当有可用数据时读取数据

    byte[] readBuffer = null;

    int availableBytes = 0;

    try {

    availableBytes = inputStream.available();

    while (availableBytes > 0) {

    readBuffer = ContinueRead.readFromPort(serialPort);

    String needData = printHexString(readBuffer);

    System.out.println(new Date() + "真实收到的数据为:-----" + needData);

    availableBytes = inputStream.available();

    msgQueue.add(needData);

    }

    } catch (IOException e) {

    }

    default:

    break;

    }

    }

    /**

    * 从串口读取数据

    *

    * @param serialPort 当前已建立连接的SerialPort对象

    * @return 读取到的数据

    */

    public static byte[] readFromPort(SerialPort serialPort) {

    InputStream in = null;

    byte[] bytes = {};

    try {

    in = serialPort.getInputStream();

    // 缓冲区大小为一个字节

    byte[] readBuffer = new byte[1];

    int bytesNum = in.read(readBuffer);

    while (bytesNum > 0) {

    bytes = MyUtils.concat(bytes, readBuffer);

    bytesNum = in.read(readBuffer);

    }

    } catch (IOException e) {

    e.printStackTrace();

    } finally {

    try {

    if (in != null) {

    in.close();

    in = null;

    }

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    return bytes;

    }

    /**

    * 通过程序打开COM4串口,设置监听器以及相关的参数

    *

    * @return 返回1 表示端口打开成功,返回 0表示端口打开失败

    */

    public int startComPort() {

    // 通过串口通信管理类获得当前连接上的串口列表

    portList = CommPortIdentifier.getPortIdentifiers();

    while (portList.hasMoreElements()) {

    // 获取相应串口对象

    portId = (CommPortIdentifier) portList.nextElement();

    System.out.println("设备类型:--->" + portId.getPortType());

    System.out.println("设备名称:---->" + portId.getName());

    // 判断端口类型是否为串口

    if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {

    // 判断如果COM4串口存在,就打开该串口

    if (portId.getName().equals(portId.getName())) {

    try {

    // 打开串口名字为COM_4(名字任意),延迟为1000毫秒

    serialPort = (SerialPort) portId.open(portId.getName(), 1000);

    } catch (PortInUseException e) {

    System.out.println("打开端口失败!");

    e.printStackTrace();

    return 0;

    }

    // 设置当前串口的输入输出流

    try {

    inputStream = serialPort.getInputStream();

    outputStream = serialPort.getOutputStream();

    } catch (IOException e) {

    e.printStackTrace();

    return 0;

    }

    // 给当前串口添加一个监听器

    try {

    serialPort.addEventListener(this);

    } catch (TooManyListenersException e) {

    e.printStackTrace();

    return 0;

    }

    // 设置监听器生效,即:当有数据时通知

    serialPort.notifyOnDataAvailable(true);

    // 设置串口的一些读写参数

    try {

    // 比特率、数据位、停止位、奇偶校验位

    serialPort.setSerialPortParams(9600,

    SerialPort.DATABITS_8, SerialPort.STOPBITS_1,

    SerialPort.PARITY_NONE);

    } catch (UnsupportedCommOperationException e) {

    e.printStackTrace();

    return 0;

    }

    return 1;

    }

    }

    }

    return 0;

    }

    @Override

    public void run() {

    // TODO Auto-generated method stub

    try {

    System.out.println("--------------任务处理线程运行了--------------");

    while (true) {

    // 如果堵塞队列中存在数据就将其输出

    if (msgQueue.size() > 0) {

    String vo = msgQueue.peek();

    String vos[] = vo.split(" ", -1);

    getData(vos);

    sendOrder();

    msgQueue.take();

    }

    }

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    /**

    * @Description: 发送获取数据指令

    * @Param:

    * @return:

    * @Author: LiangZF

    * @Date: 2019/1/3

    */

    public void sendOrder() {

    try {

    Thread.sleep(3000);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    int i = 1;

    if (i == 1) {

    // 启动线程来处理收到的数据

    try {

    byte[] b = new byte[]{0x01, 0x03, 0x00, 0x00, 0x00, 0x0E, (byte) 0xC4, 0x0E};

    System.out.println("发送的数据:" + b);

    System.out.println("发出字节数:" + b.length);

    outputStream.write(b);

    outputStream.flush();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    serialPort.close();

    e.printStackTrace();

    } finally {

    try {

    if (outputStream != null) {

    outputStream.close();

    }

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    }

    /**

    * @Description:通过数组解析检测数据

    * @Param: [vo]

    * @return: void

    * @Author: LiangZF

    * @Date: 2019/1/4

    */

    public void getData(String[] vos) {

    // 数组不为空

    if (vos != null || vos.length != 0) {

    // 风向数据

    long wind_direction = getNum(vos[3], vos[4]);

    System.out.println(wind_direction);

    // 风速数据

    long wind_speech = getNum(vos[5], vos[6]);

    System.out.println(wind_speech);

    // pm2.5

    long polutionPm2 = getNum(vos[7], vos[8]);

    System.out.println(polutionPm2);

    // pm10

    long polutionPm10 = getNum(vos[9], vos[10]);

    System.out.println(polutionPm10);

    // VOC

    long voc = getNum(vos[11], vos[12]);

    System.out.println(voc);

    // 温度

    long polutionPm = getNum(vos[13], vos[14]) / 10;

    System.out.println(polutionPm);

    // 湿度

    long temperature = getNum(vos[15], vos[16]) / 10;

    System.out.println(temperature);

    // 大气压力

    long atmosphericPressure = getNum(vos[17], vos[18]);

    System.out.println(atmosphericPressure);

    // 臭氧

    long ozone = getNum(vos[19], vos[20]) / 1000;

    System.out.println(ozone);

    // CO

    long co = getNum(vos[21], vos[22]) / 100;

    System.out.println(co);

    Map map = new HashMap<>();

    map.put("O3", ozone);

    map.put("PM2.5", polutionPm2);

    map.put("PM10", polutionPm10);

    Map uu = AqiUtil.getAqiByPollutants(map);

    String pollutants = (String) uu.get("key");

    Integer aqi = (Integer) uu.get("value");

    insertDb(wind_direction, wind_speech, polutionPm2, polutionPm10, voc, polutionPm, temperature, atmosphericPressure, ozone, co, pollutants, aqi);

    }

    }

    // 16转10计算

    public long getNum(String num1, String num2) {

    long value = Long.parseLong(num1, 16) * 256 + Long.parseLong(num2, 16);

    return value;

    }

    /**

    * @Description: 保存到数据库表中

    * @Param: [wind_direction, wind_speech, polutionPm2, polutionPm10, voc, polutionPm, temperature, atmosphericPressure, ozone, co, pollution, aqi]

    * @return: void

    * @Author: LiangZF

    * @Date: 2019/1/6

    */

    public void insertDb(long wind_direction, long wind_speech, long polutionPm2, long polutionPm10, long voc, long polutionPm, long temperature, long atmosphericPressure, long ozone, long co, String pollution, Integer aqi) {

    Connection conn = null;

    PreparedStatement ps = null;

    FileInputStream in = null;

    try {

    conn = DBUtil.getConn();

    String sql = "insert into air_status (wind_direction,wind_speed,particulate_matter,particulate_matter_one,voc,weather,humidity,air_pre,ozone,carbon_monoxide,del_flag,create_time,primary_pollutants,aqi)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

    ps = conn.prepareStatement(sql);

    ps.setLong(1, wind_direction);

    ps.setLong(2, wind_speech);

    ps.setLong(3, polutionPm2);

    ps.setLong(4, polutionPm10);

    ps.setLong(5, voc);

    ps.setLong(6, polutionPm);

    ps.setLong(7, temperature);

    ps.setLong(8, atmosphericPressure);

    ps.setLong(9, ozone);

    ps.setLong(10, co);

    ps.setInt(11, 0);

    Timestamp time = new Timestamp(System.currentTimeMillis());//获取系统当前时间

    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    String timeStr = df.format(time);

    time = Timestamp.valueOf(timeStr);

    ps.setTimestamp(12, time);

    ps.setString(13, pollution);

    ps.setInt(14, aqi);

    int count = ps.executeUpdate();

    if (count > 0) {

    System.out.println("插入成功!");

    } else {

    System.out.println("插入失败!");

    }

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    DBUtil.closeConn(conn);

    if (null != ps) {

    try {

    ps.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    }

    }

    }

    public static void main(String[] args) {

    ContinueRead cRead = new ContinueRead();

    System.out.println("asdasd");

    int i = cRead.startComPort();

    if (i == 1) {

    // 启动线程来处理收到的数据

    cRead.start();

    try {

    //根据提供的文档给出的发送命令,发送16进制数据给仪器

    byte[] b = new byte[]{0x01, 0x03, 0x00, 0x00, 0x00, 0x0E, (byte) 0xC4, 0x0E};

    System.out.println("发送的数据:" + b);

    System.out.println("发出字节数:" + b.length);

    outputStream.write(b);

    outputStream.flush();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } finally {

    try {

    if (outputStream != null) {

    outputStream.close();

    }

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    } else {

    return;

    }

    }

    // 字节数组转字符串

    private String printHexString(byte[] b) {

    StringBuffer sbf = new StringBuffer();

    for (int i = 0; i < b.length; i++) {

    String hex = Integer.toHexString(b[i] & 0xFF);

    if (hex.length() == 1) {

    hex = '0' + hex;

    }

    sbf.append(hex.toUpperCase() + " ");

    }

    return sbf.toString().trim();

    }

    }

    MyUtils工具类

    因为得到的byte数组会分成几段,需要进行合并数组操作。

    /**

    * 合并数组

    *

    * @param firstArray 第一个数组

    * @param secondArray 第二个数组

    * @return 合并后的数组

    */

    public static byte[] concat(byte[] firstArray, byte[] secondArray) {

    if (firstArray == null || secondArray == null) {

    if (firstArray != null)

    return firstArray;

    if (secondArray != null)

    return secondArray;

    return null;

    }

    byte[] bytes = new byte[firstArray.length + secondArray.length];

    System.arraycopy(firstArray, 0, bytes, 0, firstArray.length);

    System.arraycopy(secondArray, 0, bytes, firstArray.length, secondArray.length);

    return bytes;

    }

    参考文章:https://blog.csdn.net/update_java/article/details/46898937

    展开全文
  • 1、FX5U的RS2指令使用注意事项: 2、FX5U特殊继电器: (*FX5U特殊寄存器*) SD210 BIN时钟数据(公历(年))时钟数据的年数据以公历4位数的BIN码存储。 SD211 BIN时钟数据(月)时钟数据的月数据以BIN码存储。 SD212...
  • 接线 星瞳教程 发送数据 接收数据 不过我比较奇怪为何它们的uart不需要初始化 openmv传送数据 1、初始化以及uart参数设置 uart pyb.UART(3, 115200) #串口3 波特率115200uart.init(115目录参考接线星瞳教程openmv...
  • 串口发送与接收数据

    2021-04-17 02:20:55
    使用RS-485串口进行通讯。1.定义串口接收数据的缓冲区,最大可以保存64个字节u8 RS485_RX_BUF1[64];2.定义接收发送数据的长度 u8 RS485_RX_CNT;3.发送数据的函数一般有两个printf和 USART_SendData,这里主要说USART...
  • 一、我们可以通过Arduino发送数据给电脑通过串口监视器进行观察 二、可以通过调用函数Serial.available()来判断有没有数据发送过来,从而接收数据。 三、函数Serial.read()可以读取串口过来的数据 ...
  • 这是我以前用WIFI模块时的代码,希望对你有帮助/**串口数据使用**/#define RX1_Lenth32 //串口接收缓冲长度uchar RX1_Buffer[RX1_Lenth]; //接收缓冲uchar TX1_Cnt; //发送计数uchar RX1_Cnt; //接收计数intB_TX1_...
  • 介绍使用Java实现的串口通信程序,支持十六进制数据的发送与接收。源码:SerialPortDemo效果图如下:2.RXTXcomm内含32位64位版本使用方法:拷贝 RXTXcomm.jar 到 JAVA_HOMEjrelibext目录中;拷贝 rxtxSerial.dll ...
  • 三菱FX2N PLC串行通讯指令(FNC 80 RS)串行通讯指令(FNC 80 RS)1、指令格式:[RS D0 K8 D10K8]发送数据帧起始地址和数目 ↓接收数据帧起始地址和数目2、功能和动作:※ RS指令是为使用RS232C、RS-485功能扩展板及特殊...
  • 在之前配置短信语音网关的时候买了一台华为EC122(CDMA)插电信卡使用,配置到gammu之后执行发送命令提示SMSC没有配置。查了一下貌似CDMA没有什么短信...2、当接收到+CMTI指令的之后解析指令的值,例如:+CMTI:”ME...
  • C/C++ code//////////////////////////////////////////////////////////////////////////// 名称: SIO_Init// 说明: 8.0MHZ晶震下初始化串口波特率为1200bps// 8位数据位,1位停止位,无校验// 返回: voidvoid SIO_...
  • 我们在工控软件中,会经常使用到网口和串口,去接受和发送数据。通常我们发送数据的模式有两种,一种16进制,一种是ASCII码。16进制的的经常会用来和仪器PLC等设备通讯。ACSII码是一种文本模式。当我们不点选16进制...
  • 什么是DMA DMA即直接存储器访问,Direct Memory Access.是外设和存储器或存储器之间的告诉数据传输。DMA传输方式不用CPU直接控制传输,而是在RAM和IO设备之间直接进行数据传输的通道,大大提高CPU...//串口发送函数HAL_
  • liaolinhui 于 2014-8-31 00:28 编辑你看看我这个程序,或许是你波特率的原因/************************************************************************************标题: RS232串口通信试验(接收与发送) ...
  • 1、物联网系统架构 如何通过串口工具发送AT命令控制模组帮助 1 准备工作 普通物联网SIM卡 电源开关 USB Type-C电源接口 物联网eSIM芯片 天线 NB-IoT通信模组 NB-IoT通信模组复位按钮 小熊座KE1开发板 检查开发板是否...
  • 串行通信(一)

    2021-01-06 13:59:07
    前言 人类生存于世,少不了沟通。沟通使人类互相认知,传递信息,提升生活品质。...通信方式有两种,分别是并行通信和串行通信。并行通信:并行是指多比特数据同时通过并行线进行传送,这样数据传送
  • Arduino通讯串口

    2020-12-19 11:59:45
    串口是Arduino其它设备进行通信的接口所有的Arduino控制板有至少一个串口(又称作为UART或USART)。它通过0(RX)和1(TX)数字引脚经过串口转换芯片连接计算机USB端口计算机进行通信。因此,如果你使用这些功能的同时...
  • 所以就制作一个不附带多余功能,专注高速连续发送指令串口发送调试器。 直接附上程序图(图方便的话想要源程序工程文件可以点击我的主页资源中找到下载) 到这一步软件就完全做好了,当然我工作时候用的...
  • 简介单片机电脑的串口通信我想谁都会,电脑打开串口监视器,就可以轻易地查看到单片机通过串口发送回来的信息。那么两个单片机之间怎么通信呢?接下来让我们来学习一下吧。下面将使用一个Arduino UNO R3和Nodemcu...
  • 工具/原料电脑、PLC、USB转RS232数据线和RS232转RS485模块(或者USB转RS485)方法/步骤PLC电脑线路连接,根据电脑的串口情况,1.电脑自带RS232串口,那么只需RS232转RS485模块2.电脑没有串口,需要使用USB转RS232...
  • Python串口通信发送浮点型数据发送步骤 发送步骤 导入pyserial库——import serial 用于操作串口(详情见serial简介) 初始化串口——serial.Serial portx = "/dev/ttyUSB0" #端口(此处为Unix下的端口号,...
  • 拒绝接收 22 16 SYN (synchronous idle) 同步空闲 23 17 ETB (end of trans. block) 传输块结束 24 18 CAN (cancel) 取消 25 19 EM (end of medium) 介质中断 26 1A SUB (substitute) 替补 27 1B ...
  • esp32的uart串口发送16进制通信指令调用实例 简介 最近想用esp32通过uart发送的16进制指令来控制一个语言播放模块,记录一下调用uart的过程,请大佬斧正。比较愚笨,过程中踩了很多坑,如下: 将串口号设置为了0,...
  • 串口发送数据一般会分为16进制格式发送和字符串格式下发,两种格式下发需要对数据进行不同的处理才能正确下发 # 通过串口下发16进制 if self.lineEdit.text() != "": list_use = [] num = self.lineEdit.text()....
  • UART最基本的函数接口: 1)Send函数功能:将数据写到发送数据寄存器,当移位...在某些场景下(比如,用AT指令查询蓝牙的名称时),接收数据时,不能确定数据的长度,因此接收长度设置会偏大。此时,接收时会产...
  • 而TCP/IP是通用的标准通信协议,所有基于此协议的两端(服务端和客服端)都是可以进行通信的,所以,无论是否用netty实现客服端、服务端,两端都是可以进行通讯的,这个你再认真了解一下相关概念就明白了。好的,你...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,517
精华内容 13,406
关键字:

串口通信的指令发送与接收