精华内容
下载资源
问答
  • CH340串口驱动程序.zip

    2020-06-09 09:01:33
    CH340串口驱动,用于识别使用CH340芯片的串口工具,支持TTL转USB,支持32位/64位电脑;
  • ch340串口驱动

    2018-07-02 22:45:44
    CH340串口驱动(win7/win8/win8.1/win10) USB-232的串口驱动
  • CH340串口下载电路,电气原理图,PNG图片格式,适合毕业设计,机电课程设计。
  • CH340 串口驱动 wind7 64位 这个驱动解决了 code:52 的问题。
  • c++ ch340 arduino 串口,使用这个工程可以简单的使用串口进行数据的发送 参考:https://blog.csdn.net/a897180673/article/details/79706031
  • mac CH340 usb转串口驱动

    2018-06-14 10:38:02
    苹果macos下的esp8266开发所需的ch340usb转串口驱动下载
  • 集成CH340串口 平衡车主控
  • 本压缩包包含专业的中文串口调试助手sscom33.exe和ch340驱动
  • 主要芯片有CH340G USB-TTL模块,AMS1117_3.3V和AMS1117_5V两块线性稳压芯片,其电路完整且应用范围广, 主要应用范围为:单片机的DIY作为电脑和单片机通信以及为单片机供电等,两者两者合二为一方便其制作中的布线和...
  • Arduino板载USB转串口CH340驱动安装包,是为CH340系列推出的一款免费的驱动程序,多数的芯片都是CH340芯片,所以此款驱动适用于大部分的USB转串口,兼容win7、win8、win10等操作系统,有需要的朋友可以下载,不光是...
  • 该USB转TTL串口主要用于STC单片机下载或升级以及刷机烧录等,主要采用CH340T芯片进行数据接口通信,同时外接USB接口。支持XP/Win7/Win8/安卓系统等。同时CH340是STC原厂指定的下载芯片。 CH340与PL2302性能对比: ...
  • 打开SETUP.EXE,提示INF文件为CH341SER.INF,我们不需要理会(341,340共用的),所以直接点安装即可!!
  • CH340串口驱动

    2017-03-31 22:45:32
    USB转串口CH340驱动
  • CH340串口通信

    千次阅读 2020-06-11 20:11:13
    VMware Ubuntu 安装 CH340驱动 终端输入命令查看单片机设备端口号:dmesg 查看串口波特率:(例如设备端口为ttyUSB0) stty -F /dev/ttyUSB0 -a 设置串口波特率: stty -F /dev/ttyUSB0 ispeed 115200 ospeed 115200 ...

    A:vmware 虚拟机 Ubuntu
    B:单片机
    通信方式:串口通信
    电脑通过usb连接单片机,跑串口通信
    VMware Ubuntu 安装 CH340驱动
    终端输入命令查看单片机设备端口号:dmesg
    查看串口波特率:(例如设备端口为ttyUSB0)
    stty -F /dev/ttyUSB0 -a
    设置串口波特率:
    stty -F /dev/ttyUSB0 ispeed 115200 ospeed 115200 cs8
    备注:代码中设置了串口波特率后也需要通过端口命令更改端口号

    展开全文
  • WIN7+64+USB转串口CH340驱动是一款适用于win7 64位系统的串口驱动。
  • 前言第一次学习STM32的时候,不知道有调试器这个东西,所以一直是通过串口来给STM32下载程序,下载速度也还算可以,一般是几秒钟完成。后来用了调试器,可以直接在Keil环境下进行下载,而且还可以进行在线调试,所以...

    5123f821ccd9b7058928450ddaf768de.png

    前言

    第一次学习STM32的时候,不知道有调试器这个东西,所以一直是通过串口来给STM32下载程序,下载速度也还算可以,一般是几秒钟完成。后来用了调试器,可以直接在Keil环境下进行下载,而且还可以进行在线调试,所以后来就很少使用串口来下载程序了。前几天在uFUN试用群里看到有几个朋友在使用串口下载程序时,遇到了各种各样的问题,所以在这里简单介绍一下如何通过串口来给STM32下载程序。

    STM32的启动模式介绍

    从STM32参考手册上,可以查阅到,STM32的启动模式,共有下列三种,可以通过BOOT0和BOOT1电平的不同组合,来选择不同的启动模式。

    40c53ed0fdea03179d1932512a20ed76.png

    关于这几种模式的介绍,下面是我个人的理解:

    主闪存启动模式:即运行模式,单片机上电即运行程序。

    系统存储器启动模式:即串口下载模式。上电之前要先设置BOOT0=1,BOOT1=0,然后才能通过串口下载程序。或者在已经上电的情况下,设置BOOT0=1,BOOT1=0,然后按一下复位键,这样也能通过串口下载程序。

    SRAM启动模式:即调试模式。假如我只修改了代码中一个小小的地方,如果直接擦除整个Flash,比较费时,而且Flash的擦写次数也是有限制的。所以可以考虑从RAM中启动代码,用于快速的程序调试,等程序调试完成后,再将程序下载到Flash中。

    有的朋友可能遇到过这种情况:程序第一次下载的时候可以运行,但是掉电重启之后,程序就不能运行了。这种情况就有可能是把BOOT设置成了串口下载模式,所以掉电之后,并不会自动运行。如果想要即使掉电重启也能直接运行程序,可以把BOOT设置为主闪存启动模式,即BOOT0=0。

    安装USB串口驱动

    9fc8235f3da0c4ed48961f390c66289d.png

    在进行串口下载程序之前,如果串口芯片的驱动程序没有安装,那么电脑不能识别串口,如上图所示,设备管理器里有一个未识别的设备。在安装串口驱动之前,要先确定开发板所使用的串口芯片,我们的uFUN开发板使用的是CH340串口芯片。这里我提供了几个常用串口芯片的驱动程序下载地址,大家如果使用其他的串口芯片,要安装对应的驱动程序:

    • CH340:CH340/CH341USB转串口WINDOWS驱动程序
    • PL2302:PL2303 Windows Driver Download
    • CP2102:CP210x USB转UART桥接VCP驱动程序
    • FT232:FT232R USB UART Driver Download

    如果驱动安装成功,在设备管理器里可以看到该设备对应的串口号:

    b1fe51927c381bdf288ec96ef755b2c2.png

    设置启动模式为系统存储启动模式

    上电前,设置BOOT0=1,BOOT1=0。或者是在上电后,设置BOOT0=1,BOOT1=0之后,然后按一下复位按键。这两种方式都可以让设置为系统存储启动模式,从而通过串口下载程序。

    参考uFUN的原理图:

    c9d19baf88223966a4a38a426bf944ab.png

    可以看出,BOOT的选择是通过拨码开关实现的。S1对应BOOT1,S2对应BOOT0,开关处于ON状态,BOOT直接接地,为低电平0;开关处于OFF状态,BOOT上拉为高电平1,即:

    09793c905772964785016ba8bf40ce68.png

    这一点和【uFun 开发板快速入门指南 V10】介绍的有所出入,在这里手动@管理员核对一下。

    6ca34edf8ccd1373c6953fcf0a291f41.png

    对于uFUN开发板,要切换到串口下载模式,只需要设置S1=ON,即BOOT1=0,S2=OFF,即BOOT0=1,就可以进行下一步的程序下载。如下图所示:

    016b7fd81583784ffc558d80c0a6eb34.png

    使用FlyMCU下载程序

    STM32串口下载软件主要两个,一个是国人开发的FlyMCU,另一个是ST官方的Flash Loader Demonstrator,这两个软件的下载方法我都会介绍,不过我个人认为FlyMCU更简单易用一些。

    9bb28d07508e5bbce19af8511c94d25f.png

    FlyMCU是由单片机在线编程网开发的一款串口下载软件,我使用的是V0.188版本,主界面如上图所示,如果大家想获取最新版的软件可以到官方网站下载。我去官网上看了一下,又发布了免费的Free ISP软件,可以支持STM32和LPC2xxx程序的下载。如果有朋友从事LPC2xxx MCU的开发,而又没有调试器,可以尝试一下这个软件。 好了,话不多说,下面来看一下如何使用FlyMCU通过串口来给uFUN开发板下载程序。

    • 1.软件的下载

    可以到官方网站下载最新版,或者是下载我使用的这个版本,FlyMCU V0.188。

    • 2.选择COM号

    确保启动模式已经设置为串口下载模式,BOOT1=0,BOOT0=1,即S1=ON,S2=OFF,然后把开发板连接电脑上电,打开软件,选择PORT菜单下对应的COM口。

    19ffe5f6c26cdc81cdeb14c442933a7c.png
    • 3.加载hex文件

    加载生成的hex文件,并勾选右边的编程前重装文件,这样,就不用每次下载程序,重新加载hex文件了。

    fb6ecf336512eac1f504eee6764d75d8.png
    • 4.下载程序

    勾选校验编程后执行这两个选项,取消勾选编程到FLASH时写选项字节,然后点击开始编程按钮,如果正常下载的话,右边会输出下载的信息,如果成功下载并运行,最后会输出:

    共写入8KB,进度100%,耗时4750毫秒
    成功从08000000开始运行

    表示程序成功下载。

    4fb038d85dce5abe5271cb7f47139ee6.png

    编程后执行:这个选项是指,程序下载完成后自动运行,而不用切换到BOOT到主闪存启动模式,但是,掉电重启,程序不会直接运行。如果要上电即运行此程序,还需要把BOOT设置回主闪存启动模式BOOT0=0,即S2=ON。

    编程到FLASH时写选项字节:这个选项不要勾选,如果勾选了,可能会导致下载失败,或者是运行失败,甚至会导致芯片的锁死。所以,这个选项一定不要勾选。

    使用Flash Loader Demonstrator下载

    Flash Loader Demonstrator是ST官方的串口下载软件,可以用于STM32系列单片机的程序下载,官网地址:STM32 Flash loader demonstrator

    • 1.软件的下载

    通过上面的官网链接,可以下载到最新2.8.0版本的Flash Loader Demonstrator,但是如果要想下载,需要先登陆ST官网的账号,如果不想注册账号的话,可以通过下面的链接下载,这个是我之前找的,版本是2.6.0的,但不影响程序的下载:Flash_Loader_Demonstrator_v2.6.0_Setup

    • 2.连接芯片

    和FlyMCU不同的是,要想下载程序,必须要经过连接芯片,等一系列步骤才能完成下载,这一点,也是我觉得这个软件不好用的原因。

    打开软件,选择板子串口对应的COM号,波特率可以调成最高,这样下载速度会快一点,但是有的串口芯片,不能支持很高的波特率。

    26147131ffbbe52661245f2058486af0.png

    如果和板子连接成功的话,会检测到目标STM32芯片的Flash的大小,我们的uFUN开发板是使用STM32F10RC,256KB Flash。

    d342c51a068d3602c07084113c22cfe3.png

    这一步,可以查看当前Flash各页的读写情况,绿色的锁表示可读/可写,如果芯片被加了读保护,或者写保护,部分页会显示为红色的锁。

    ebb65f3b3c2454fa8fd16320bc93a453.png
    • 3.程序的下载

    先加载hex文件,下面的擦除选项可以选择:擦除必要的页、不擦除或者是全片擦除,这里保持默认配置就行,直接点击Next进行程序的下载。

    a70295ea92126555d482378b23e6af3c.png

    如果下载成功,会显示

    abcbc5cfa1910345cd68f2ea0bd00180.png

    这里如果点击Back是不能进行第二次程序下载的,必须重新打开,连接,才能下载。

    8ea6654c75db6794cf1705500aceb44c.png

    另外,除了STM32系列单片机程序的下载,它还支持ST公司的STM8的程序下载。

    总结

    STM32只能通过串口1进行程序下载,即PA9、PA10,其他串口都不具备这个功能,所以,如果自己设计板子,要注意这一点。一些联网的设备进行固件更新也是这个原理,即把WIFI模块,连接到串口1,实现程序的在线升级。当然,具体的实现还是很复杂的,而且还涉及到Bootloader程序的开发,这就是另外一个方面了。虽然STM32的F4系列也可以使用串口下载程序,但擦除时间很长,有十几秒种。推荐大家尽量还是使用调试器来进行程序的下载和调试,方便又好用,单片机开发必备!

    参考资料

    • STM32 BOOT模式配置以及作用
    • STM32启动模式详解

    历史精选文章:

    • STM32串口打印输出乱码的解决办法
    • 【UFUN开发板评测】小巧而不失精致,简单而不失内涵——uFun开发板开箱爆照
    • 一键自动格式化你的代码
    • Qt小项目之串口助手控制LED
    • Jlink使用技巧之烧写SPI Flash存储芯片
    • Jlink使用技巧之虚拟串口功能
    • Jlink使用技巧之读取STM32内部的程序
    • Jlink使用技巧之J-Scope虚拟示波器功能

    欢迎大家关注我的个人博客

    或微信扫码关注我的公众号

    3bfcdd4b932503fca0c2d59296c5b6ad.png
    展开全文
  • CH340串口读取

    万次阅读 2018-12-26 17:38:04
    CH34x 系列芯片是 USB 总线的转接芯片,主要包含 CH340CH341、CH345,通过 USB 总线提供异 步串口、打印口、并口、MIDI 以及常用的 2 线和 4 线等接口CH34x 串口提供的 Android 接口需要基于 Android 3.1 ...

    最近在开发android工控机同硬件设备通信的时候,用到了ch340U转串,所以把关于这个串口的一些知识分享给大家。

    简介:

    CH34x 系列芯片是 USB 总线的转接芯片,主要包含 CH340、CH341、CH345,通过 USB 总线提供异 步串口、打印口、并口、MIDI 以及常用的 2 线和 4 线等接口。

    CH34x 串口提供的 Android 接口需要基于 Android 3.1 及以上版本系统,使用 CH34x 串口 Android 驱动条件:

    1、需要基于 Android 3.1 及以上版本系统

    2、Android 设备具有 USB Host 或 OTG 接口

    接口说明:

    EnumerateDevice:枚举 CH34x 设备

    函数原型 :public UsbDevice EnumerateDevice()

    返回枚举到的 CH34x 的设备,若无设备则返回 null
    OpenDevice:打开 CH34x 设备

    函数原型 :public void OpenDevice(UsbDevice mDevice)

    mDevice :需要打开的 CH34x 设备
    ResumeUsbList:枚举并打开 CH34x 设备,这个函数包含了 EnumerateDevice,OpenDevice 操作

    函数原型 :public int ResumeUsbList()

    返回 0 则成功,否则失败
    UartInit:设置初始化 CH34x 芯片

    函数原型 :public boolean UartInit()

    若初始化失败,则返回 false,成功返回 true

    SetConfig:设置 UART 接口的波特率、数据位、停止位、奇偶校验位以及流控

    函数原型 :public boolean SetConfig(int baudRate, byte dataBit, byte stopBit, byte parity, byte flowControl)

    baudRate :波特率:300,600,1200、2400、4800、9600、19200、38400、57600、115200、 230400、460800、921600,默认:9600

    dataBits :5 个数据位、6 个数据位、7 个数据位、8 个数据位,默认:8 个数据位

    stopBits :0:1 个停止位,1:2 个停止位,默认:1 个停止位

    parity :0:none,1:add,2:even,3:mark 和 4:space,默认:none

    flowControl :0:none,1:cts/rts,默认:none

    若设置失败,则返回 false,成功返回 true
    WriteData:发送数据

    函数原型 :public int WriteData(byte[] buf, int length)

    buf :发送缓冲区 length :发送的字节数

    返回值为写成功的字节数
    ReadData:读取数据

    函数原型 :public int ReadData(char[] data, int length)

    data :接收缓冲区,数据类型为

    char length :读取的字节数 返回实际读取的字节数
    函数原型 :public int ReadData(byte[] data, int length)

    data :接收缓冲区

    length :读取的字节数 返回实际读取的字节数
    CloseDevice:关闭串口。

    函数原型 :public void CloseDevice()
    isConnected:判断设备是否已经连接到 Android 系统

    函数原型 :public boolean isConnected() 返回为 false 时表示设备未连接到系统,true 表示设备已连接
    除了上述提供的接口 API,用户还可以根据自己的设备来设置读写超时时间:

    函数原型:public boolean SetTimeOut(int WriteTimeOut, int ReadTimeOut)

    WriteTimeOut:设置写超时时间,默认为 10000ms

    ReadTimeOut :设置读超时时间,默认为 10000ms


    使用:

    添加usb权限

       <!-- USB权限 -->
        <uses-feature android:name="android.hardware.usb.host"/>

    现将jar包拷贝到lib文件夹下https://pan.baidu.com/s/1SG-9MWgZ9OfLLxTTXv8RPg

    然后就可以调用所提供的的方法了,为了方便理解我另外写了点简单的代码,多的不说直接上代码,注释很详细:

    //打开串口
        public void open() {
            try {
                device = new CH34xUARTDriver((UsbManager) context.getSystemService(Context.USB_SERVICE), context, ACTION_USB_PERMISSION);
                if (!device.UsbFeatureSupported())// 判断系统是否支持USB HOST
                { return; }
                //判断是否授权  如果没有等待几秒让用户授权
                if (device.ResumeUsbPermission() == -2) {
                    timer.schedule( authorizeTimeTask, 1000, 1000);
                } else {
                    //如果已授权 直接开启连接
                    if (setCon()) {
                        ConThread = new Thread(Conrunnable);
                        ConThread.start();
                    }
                }
            } catch (Exception e) {
                sentConMsg("初始化USB串口异常");
            }
    
        }
        //连接串口
        private boolean setCon() {
            if (device == null) {
                return false;
            }
            try {
                //检查是否授权
                if (device.ResumeUsbPermission() == -2) {
                    sentConMsg("授权失败");
                }
                //得到设备名称
                UsbName = device.EnumerateDevice().getDeviceName();
                //打开设备
                retval = device.ResumeUsbList();
              
                if (retval == -1) {
                    sentConMsg("打开串口失败1");
                    device.CloseDevice();
                    isStart = false;
                } else if (retval == 0) {
                    if (!device.UartInit()) {
                        sentConMsg("打开串口失败2");
                        isStart = false;
                        return false;
                    }
                    //配置串口波特率
                    is = device.SetConfig(baudRate, dataBit, stopBit, parity, flowControl);
                    if (is) {
                        sentConMsg("打开串口成功");
                        isStart = true;
                        return true;
                    } else {
                        sentConMsg("打开串口失败3");
                    }
                }
            } catch (Exception e) {
                sentConMsg("打开串口异常4");
            }
            return false;
        }

    本想不停地请求打开设备直到用户授权,但是不行,因为不停地请求会报异常,所以我是设置了个计时器(待优化),在规定的时间内授权后,再次请求打开串口就行了。

    //几秒后 用户已授权 然后开始连接串口
        final Handler timeConnectHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1:
                        if (recLen < 0) {
                            timer.cancel();
                            if (setCon()) {
                                ConThread = new Thread(Conrunnable);
                                ConThread.start();
                            }
                        }
                }
            }
        };
        TimerTask  authorizeTimeTask = new TimerTask() {
            @Override
            public void run() {
                recLen--;
                Message message = Message.obtain();
                message.what = 1;
                timeConnectHandler.sendMessage(message);
            }
        };
    

    因为我们需要在不同的界面知道现在串口的连接情况所以写了一个接口,专门用来传输连接状态:

        /**
         * 连接状态事件
         */
        private List<ConnectStateListener> lstConnect;
    
        public void addConnectState(ConnectStateListener connectStateListener) {
            if (lstConnect == null) {
                lstConnect = new ArrayList<>();
            }
            lstConnect.add(connectStateListener);
        }
    
        public void removeConnectState(ConnectStateListener connectStateListener) {
            if (lstConnect == null) {
                lstConnect = new ArrayList<>();
            }
            lstConnect.remove(connectStateListener);
        }
    
    
        private Handler ConnetHandler = new Handler() {
            public void handleMessage(Message msg) {
                if (lstConnect == null)
                    return;
                for (ConnectStateListener item : lstConnect) {
                    item.ConnectState((String) msg.obj);
                }
            }
        };
    
        //发送状态
        private void sentConMsg(String msg) {
            Message message = Message.obtain();
            message.obj = msg;
            ConnetHandler.sendMessage(message);
        }

    做到现在应该是可以读取到数据了的,开启线程读取数据:

    
        private Runnable Conrunnable = new Runnable() {
            @Override
            public void run() {
                try {
                    byte[] buffer;
                    while (isRead) {
                        try {
                            if (!isStart) {
                                break;
                            }
                            buffer = new byte[520];
                            int length = device.ReadData(buffer, 520);
                            if (length > 0) {
                             sentConMsg("串口连接成功");
                                byte[] temp = new byte[length];
                                System.arraycopy(buffer, 0, temp, 0, length);
                                sentData(temp );
                            }
                            if (length == 0) {
                                if (_Timer == null) {
                                    _Timer = new Timer();
                                    _Timer.schedule(new DataTimer(), 0, 1000);
                                }
                                continue;
                            } else {
                                _Datatime = 0;
                            }
                        } catch (Exception e) {
                            sentConMsg("读取数据异常1");
                            continue;
                        }
                    }
                    close();
                    return;
                } catch (Exception e) {
                    sentConMsg("连接异常");
                }
            }
        };
    

    当数据在几秒内持续为空是,视为连接已断开。读取的数据与界面的交互同样使用接口:

     /**
         * 数据传输事件
         */
        private List<GetDataListener> lsDatas;
    
        public void addGetData(GetDataListener dataListener) {
            if (lsDatas == null) {
                lsDatas = new ArrayList<>();
            }
            lsDatas.add(dataListener);
        }
    
        public void removeGetData(GetDataListener dataListener) {
            if (lsDatas == null) {
                lsDatas = new ArrayList<>();
            }
            lsDatas.remove(dataListener);
        }
    
        private Handler DataHandler = new Handler() {
            public void handleMessage(Message msg) {
                if (lsDatas == null)
                    return;
                for (GetDataListener item : lsDatas) {
                    item.getData((byte[]) msg.obj);
                }
            }
        };
    
        //发送数据
        private void sentData(byte[] bytes) {
            Message message = Message.obtain();
            message.obj = bytes;
            DataHandler.sendMessage(message);
        }

    关闭串口,就是回收一下资源,停止读取数据就行

     public void close() {
            if (_Timer != null) {
                _Timer.cancel();
                _Timer = null;
                _Datatime = 0;
            }
            UsbName = "";
            isRead = false;
            if (ConThread != null) {
                ConThread.interrupt();
                ConThread = null;
            }
            _Timer = null;
            _Datatime = 0;
            isStart = false;
        }

    发送数据给硬件或者是什么主要就是要判一下空

        //发送数据
        public void send(byte[] data) {
            if (device != null && data != null) {
                int retval = device.WriteData(data, data.length);
                if (retval > 0) {
                    //发送成功
                } else {
                    //发送失败
                }
            }
        }

    打开以及关闭的方法需要这样调用:

     switch (v.getId()) {
                case R.id.OpenButton:
                    Ch34Helper.getInstance(this).open();
                    break;
                case R.id.WriteButton:
                    byte[] to_send = toByteArray(writeText.getText().toString());
                    Ch34Helper.getInstance(this).send(to_send);
                    break;
                case R.id.CloseButton:
                    Ch34Helper.getInstance(this).close();
                    break;
            }

    在界面上的调用就很简单了,数据接收需要实现两个接口,然后把数据显示到界面:

    //初始化连接以及数据传输事件
        private void initData() {
            Ch34Helper.getInstance(this).addConnectState(this);
            Ch34Helper.getInstance(this).addGetData(this);
        }
    
    //设置连接状态显示
        @Override
        public void ConnectState(String s) {
            if (s != null && s.length() > 0)
                connectText.setText(s);
        }
        //设置接收数据显示
        @Override
        public void getData(byte[] bytes) {
            if (bytes != null && bytes.length > 0)
                readText.setText(bytes2HexString(bytes));
        }

    还有就是最后要记得在界面销毁的时候回收资源

       @Override
        protected void onDestroy() {
            super.onDestroy();
            Ch34Helper.getInstance(this).removeConnectState(this);
            Ch34Helper.getInstance(this).removeGetData(this);
            Ch34Helper.getInstance(this).close();
        }
    

    读取类完整代码:

    
    public class Ch34Helper {
        private static Context context;
        private static CH34xUARTDriver device = null;
        private Thread ConThread;
        private boolean isStart = false;
        private static final String ACTION_USB_PERMISSION = "cn.wch.wchusbdriver.USB_PERMISSION";
        private int baudRate = 115200;
        private byte stopBit = 1;
        private byte dataBit = 8;
        private byte parity = 0;
        private byte flowControl = 0;
        private int retval;
        private boolean is;
        private String UsbName;
        private boolean isRead = true;
        private int recLen = 8;
        private Timer timer = new Timer();
        private Timer _Timer = null;
        private int _Datatime = 0;
        private static Ch34Helper ch34Helper;
    
        public static Ch34Helper getInstance(Context con) {
            if (null == ch34Helper) {
                ch34Helper = new Ch34Helper();
                context = con;
            }
            return ch34Helper;
        }
    
        private class DataTimer extends TimerTask {
            @Override
            public void run() {
                //超过3秒没有数据 视为连接断开
                _Datatime++;
                if (_Datatime > 3) {
                    sentConMsg("串口已断开");
                }
            }
        }
    
        //打开串口
        public void open() {
            try {
                device = new CH34xUARTDriver((UsbManager) context.getSystemService(Context.USB_SERVICE), context, ACTION_USB_PERMISSION);
                if (!device.UsbFeatureSupported())// 判断系统是否支持USB HOST
                {
                    return;
                }
                //判断是否授权  如果没有等待几秒让用户授权
                if (device.ResumeUsbPermission() == -2) {
                    timer.schedule(authorizeTimeTask, 1000, 1000);
                } else {
                    //如果已授权 直接开启连接
                    if (setCon()) {
                        ConThread = new Thread(Conrunnable);
                        ConThread.start();
                    }
                }
            } catch (Exception e) {
                sentConMsg("初始化USB串口异常");
            }
    
        }
    
        //连接串口
        private boolean setCon() {
            if (device == null) {
                return false;
            }
            try {
                //检查是否授权
                if (device.ResumeUsbPermission() == -2) {
                    sentConMsg("授权失败");
                }
                //得到设备名称
                UsbName = device.EnumerateDevice().getDeviceName();
                //打开设备
                retval = device.ResumeUsbList();
    
                if (retval == -1) {
                    sentConMsg("打开串口失败1");
                    device.CloseDevice();
                    isStart = false;
                } else if (retval == 0) {
                    if (!device.UartInit()) {
                        sentConMsg("打开串口失败2");
                        isStart = false;
                        return false;
                    }
                    //配置串口波特率
                    is = device.SetConfig(baudRate, dataBit, stopBit, parity, flowControl);
                    if (is) {
                        sentConMsg("打开串口成功");
                        isStart = true;
                        return true;
                    } else {
                        sentConMsg("打开串口失败3");
                    }
                }
            } catch (Exception e) {
                sentConMsg("打开串口异常4");
            }
            return false;
        }
    
        //几秒后 用户已授权 然后开始连接串口
        final Handler timeConnectHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1:
                        if (recLen < 0) {
                            timer.cancel();
                            if (setCon()) {
                                ConThread = new Thread(Conrunnable);
                                ConThread.start();
                            }
                        }
                }
            }
        };
        TimerTask authorizeTimeTask = new TimerTask() {
            @Override
            public void run() {
                recLen--;
                Message message = Message.obtain();
                message.what = 1;
                timeConnectHandler.sendMessage(message);
            }
        };
    
    
        //得到搜索到的设备
        public UsbDevice getDevice() {
            if (device == null) {
                device = new CH34xUARTDriver((UsbManager) context.getSystemService(Context.USB_SERVICE), context, ACTION_USB_PERMISSION);
                return device.EnumerateDevice();
            }
            return device.EnumerateDevice();
    
        }
    
        private Runnable Conrunnable = new Runnable() {
            @Override
            public void run() {
                try {
                    byte[] buffer;
                    while (isRead) {
                        try {
                            if (!isStart) {
                                break;
                            }
                            buffer = new byte[520];
                            int length = device.ReadData(buffer, 520);
                            if (length > 0) {
                           sentConMsg("串口连接成功");
                                byte[] temp = new byte[length];
                                System.arraycopy(buffer, 0, temp, 0, length);
                                sentData(temp );
                            }
                            if (length == 0) {
                                if (_Timer == null) {
                                    _Timer = new Timer();
                                    _Timer.schedule(new DataTimer(), 0, 1000);
                                }
                                continue;
                            } else {
                                _Datatime = 0;
                            }
                        } catch (Exception e) {
                            sentConMsg("读取数据异常1");
                            continue;
                        }
                    }
                    close();
                    return;
                } catch (Exception e) {
                    sentConMsg("连接异常");
                }
            }
        };
    
        public void close() {
            if (_Timer != null) {
                _Timer.cancel();
                _Timer = null;
                _Datatime = 0;
            }
            UsbName = "";
            isRead = false;
            if (ConThread != null) {
                ConThread.interrupt();
                ConThread = null;
            }
            _Timer = null;
            _Datatime = 0;
            isStart = false;
        }
    
        //发送数据
        public void send(byte[] data) {
            if (device != null && data != null) {
                int retval = device.WriteData(data, data.length);
                if (retval > 0) {
                    //发送成功
                } else {
                    //发送失败
                }
            }
        }
    
        /**
         * 数据传输事件
         */
        private List<GetDataListener> lsDatas;
    
        public void addGetData(GetDataListener dataListener) {
            if (lsDatas == null) {
                lsDatas = new ArrayList<>();
            }
            lsDatas.add(dataListener);
        }
    
        public void removeGetData(GetDataListener dataListener) {
            if (lsDatas == null) {
                lsDatas = new ArrayList<>();
            }
            lsDatas.remove(dataListener);
        }
    
        private Handler DataHandler = new Handler() {
            public void handleMessage(Message msg) {
                if (lsDatas == null)
                    return;
                for (GetDataListener item : lsDatas) {
                    item.getData((byte[]) msg.obj);
                }
            }
        };
    
        //发送数据
        private void sentData(byte[] bytes) {
            Message message = Message.obtain();
            message.obj = bytes;
            DataHandler.sendMessage(message);
        }
        /**
         * 连接状态事件
         */
        private List<ConnectStateListener> lstConnect;
    
        public void addConnectState(ConnectStateListener connectStateListener) {
            if (lstConnect == null) {
                lstConnect = new ArrayList<>();
            }
            lstConnect.add(connectStateListener);
        }
    
        public void removeConnectState(ConnectStateListener connectStateListener) {
            if (lstConnect == null) {
                lstConnect = new ArrayList<>();
            }
            lstConnect.remove(connectStateListener);
        }
    
    
        private Handler ConnetHandler = new Handler() {
            public void handleMessage(Message msg) {
                if (lstConnect == null)
                    return;
                for (ConnectStateListener item : lstConnect) {
                    item.ConnectState((String) msg.obj);
                }
            }
        };
    
        //发送状态
        private void sentConMsg(String msg) {
            Message message = Message.obtain();
            message.obj = msg;
            ConnetHandler.sendMessage(message);
        }
    
    
    }

    activity代码:

    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener, ConnectStateListener, GetDataListener {
    
        private EditText readText, writeText;
        private TextView connectText;
        private Button writeButton, openButton, CloseButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            initData();
        }
    //初始化连接以及数据传输事件
        private void initData() {
            Ch34Helper.getInstance(this).addConnectState(this);
            Ch34Helper.getInstance(this).addGetData(this);
        }
    
    //设置连接状态显示
        @Override
        public void ConnectState(String s) {
            if (s != null && s.length() > 0)
                connectText.setText(s);
        }
        //设置接收数据显示
        @Override
        public void getData(byte[] bytes) {
            if (bytes != null && bytes.length > 0)
                readText.setText(bytes2HexString(bytes));
        }
    
        private void initView() {
            connectText = (TextView) findViewById(R.id.ConectValues);
            readText = (EditText) findViewById(R.id.ReadValues);
            writeText = (EditText) findViewById(R.id.WriteValues);
            writeButton = (Button) findViewById(R.id.WriteButton);
            openButton = (Button) findViewById(R.id.OpenButton);
            CloseButton = (Button) findViewById(R.id.CloseButton);
            CloseButton.setOnClickListener(this);
            writeButton.setOnClickListener(this);
            openButton.setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.OpenButton:
                    Ch34Helper.getInstance(this).open();
                    break;
                case R.id.WriteButton:
                    byte[] to_send = toByteArray(writeText.getText().toString());
                    Ch34Helper.getInstance(this).send(to_send);
                    break;
                case R.id.CloseButton:
                    Ch34Helper.getInstance(this).close();
                    break;
            }
    
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Ch34Helper.getInstance(this).removeConnectState(this);
            Ch34Helper.getInstance(this).removeGetData(this);
            Ch34Helper.getInstance(this).close();
        }
    
        /**
         * 将String转化为byte[]数组
         *
         * @param arg 需要转换的String对象
         * @return 转换后的byte[]数组
         */
        private byte[] toByteArray(String arg) {
            if (arg != null) {
                /* 1.先去除String中的' ',然后将String转换为char数组 */
                char[] NewArray = new char[1000];
                char[] array = arg.toCharArray();
                int length = 0;
                for (int i = 0; i < array.length; i++) {
                    if (array[i] != ' ') {
                        NewArray[length] = array[i];
                        length++;
                    }
                }
                /* 将char数组中的值转成一个实际的十进制数组 */
                int EvenLength = (length % 2 == 0) ? length : length + 1;
                if (EvenLength != 0) {
                    int[] data = new int[EvenLength];
                    data[EvenLength - 1] = 0;
                    for (int i = 0; i < length; i++) {
                        if (NewArray[i] >= '0' && NewArray[i] <= '9') {
                            data[i] = NewArray[i] - '0';
                        } else if (NewArray[i] >= 'a' && NewArray[i] <= 'f') {
                            data[i] = NewArray[i] - 'a' + 10;
                        } else if (NewArray[i] >= 'A' && NewArray[i] <= 'F') {
                            data[i] = NewArray[i] - 'A' + 10;
                        }
                    }
                    /* 将 每个char的值每两个组成一个16进制数据 */
                    byte[] byteArray = new byte[EvenLength / 2];
                    for (int i = 0; i < EvenLength / 2; i++) {
                        byteArray[i] = (byte) (data[i * 2] * 16 + data[i * 2 + 1]);
                    }
                    return byteArray;
                }
            }
            return new byte[]{};
        }
    
        /* *
         * @param bytes 字节数组
         * @return 16进制大写字符串
         */
        public static String bytes2HexString(byte[] bytes) {
            if (bytes == null) return null;
            int len = bytes.length;
            if (len <= 0) return null;
            char[] ret = new char[len << 1];
            for (int i = 0, j = 0; i < len; i++) {
                ret[j++] = hexDigits[bytes[i] >>> 4 & 0x0f];
                ret[j++] = hexDigits[bytes[i] & 0x0f];
            }
            return new String(ret);
        }
    
        private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    
    
    }

    布局就不贴了,应该难不倒你们。

    总的来说各种各样的串口读取方式其实相差不大,主要就是自己试一把,那么就没多大问题了,过两天再更新一个4孔插口串口的读取方式,希望本篇能帮助到你们。

    展开全文
  • CH341/CH340 Win10串口驱动工具

    千次下载 热门讨论 2016-06-02 16:18:18
    USB转串口CH341/CH340的WINDOWS驱动程序安装包 支持WINDOWS 98/ME/2000/XP/Server 2003/VISTA/ Server 2008/Win7/Win8/Win10 32位/64位,通过微软数字签名认证, 在计算机端将USB设备仿真为标准Serial串口设备COM? ...
  • CH340E USB-TTL驱动,用于usart传输;同样是别处搬来的,零积分方便分享下载用hhh如果安装失败试试先卸载再重新安装
  • CH341T CH340T原理图.zipCH341T CH340T原理图.zipCH341T CH340T原理图.7z
  • python实现CH340串口通信(超详细)

    万次阅读 2020-08-30 12:58:36
    代码实现CH340串口通信 UART UART全称为Universal Asynchronous Receiver/Transmitter,通用异步收发传输器。 UART一般用于电路板内部通信或者短距离通信,最常用的就是单片机,stm32等。UART通信是两个IC...

    串口通信介绍

    1. 基本概念
      串口通信(Serial Communication), 是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。

    2. UART
      UART全称为Universal Asynchronous Receiver/Transmitter,通用异步收发传输器。UART一般用于电路板内部通信或者短距离通信,最常用的就是单片机,stm32等。UART通信是两个IC(integrated circuit)进行数据通信的方式,其中一方的TX负责发送数据给对方的RX,一方的RX负责接收对方发送的数据.在这里插入图片描述

    理论上,我们的驱动板和树莓派通信,要求两个电路板上都需要有UART通信接口。但是树莓派是不存在uart接口的,只能用usb,因此,在开发版上,集成了ch340,可以和树莓派进行通信。

    烧录程序

    1. mac没有找到串口烧录的界面化软件,为了方便我在我windows虚拟机上装了FlyMcu,进行烧录
      在这里插入图片描述
    2. 连接usb后,选择port: USB SERIAL CH340,选中STMISP,配置 校验和编程后执行,取消选中 编程到FLASH时写选项字节,下拉框选择 DTR的低电平复位,RTS高电平进BootLoader。然后读器件信息,如果连接正常右边会有信息提示。
      在这里插入图片描述
      3.选择编写好的hex文件,然后点击开始编程,右边显示烧录进度在这里插入图片描述

    4.烧录完成在这里插入图片描述

    代码实现串口通信

    1. 安装pyserial库,pip install pyserial.
      第一个参数是使用USB连接串行口(cd /dev/ 然后 ls -al ttyUSB0 可以获取到),第二个参数是波特率
      在这里插入图片描述
    2. 运行代码查看led灯变亮了,然后再次运行切换下状态,这时候就会灭掉
      在这里插入图片描述
      在这里插入图片描述

    https://www.lanqiao.cn/courses/2947,提供准备好的云主机ros环境,进行实操,课程包括了 Topic 通讯, Service 通讯,ROS 自定义消息,URDF可视化,TF坐标转换等技术要点。每个技术点都会结合例子先把原理讲解清楚,为了达到学以致用的目的,我们会再进行知识拓展,针对每个技术点实现对应的生动有趣的需求,保证学完后会有很大的收获。

    展开全文
  • CH340 串口转USB 驱动

    2017-09-27 17:00:24
    CH340 串口转USB 驱动,是正对于CH340芯片的,适用于TTL串口转USB,连接到电脑上,可以实现串口调试助手查询到COM口,并实现串口数据的收发~
  • android usbhost串口编程,优化ch340驱动,支持多串口,用于wifi模块产测
  • 这个时候步骤一的工作就可以体现了,猛戳这个传送门,传送门里是官方给出的不同内核对应的驱动源码,将相应源码复制,并替换ch34x.c(我的是5.4.0-52) 4、进入解压后文件的目录(就是带有makefile文件的目录),...
  • 网上大多串口驱动程序安装后无法识别,此驱动为专用的CH340T定制,可解决这些问题
  • USB-SERIAL-CH340驱动

    2020-03-17 23:06:32
    解决win7-x64, win8-x64,win10-x64系统USB接设备console口驱动问题,以管理员身份运行,安装前根据自己系统更改兼容性(win10可以选win8的)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,430
精华内容 9,372
关键字:

ch340串口