精华内容
下载资源
问答
  • 做了一些Android驱动板的串口通信,对控制卡,继电器开关,麦克风,PWM风机等进行操作,进行一下记录分享。其中,包含了Android自身的串口操作及Usb转串口的操作。本篇主要介绍串口基础内容和基于谷歌官方android-...

    前言

    做了一些Android驱动板的串口通信,对控制卡,继电器开关,麦克风,PWM风机等进行操作,进行一下记录分享。其中,包含了Android自身的串口操作及Usb转串口的操作。本篇主要介绍串口基础内容和基于谷歌官方android-serialport-api库 对Android设备进行的串口操作,下一篇中将给出基于Usb转串口驱动库usb-serial-for-android 的相关内容及操作。

    串口通信

    串行接口是一种可以将接收来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接收的串行数据流转换为并行的数据字符供给CPU的器件。

    一般完成这种功能的电路,我们称为串行接口电路。

    串口按位(bit)发送和接收字节的通信方式即串口通信。尽管比按 字节 (byte)的 并行通信 慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信(RS232是要用在近距离传输上最大距离为30M,RS485用在长距离传输最大距离1200M)。通信使用3根线完成,分别是地线、发送、接收。

    串口参数

    串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配。

    波特率

    这是一个衡量符号传输速率的参数。指的是信号被调制以后在单位时间内的变化,即单位时间内载波参数变化的次数,如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps。一般调制速率大于波特率,比如曼彻斯特编码)。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。

    数据位

    这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。

    停止位

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

    奇偶校验位

    串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位为1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。

    串口开发

    在Android开发中,对串口数据的读取和写入,实际上是是通过I/O流读取,写入文件数据。串口使用完毕需要关闭(文件关闭)。串口关闭,即是文件流关闭。

    开发流程

    1. 获取设备串口地址;
    2. 配置(波特率,校验位等),建立指定串口通信;
    3. 串口写入及接收返回的数据;
    4. 结束通信,串口关闭。

    使用过程

    基于谷歌官方android-serialport-api 编译修改,主要包含SerialPortFinderSerialPort,进行串口地址的获取和串口内容的开启、写入、读取及关闭。

    1. 通过SerialPortFinder获取所有串口地址,进行串口的选取(使用中通常来说如果插入Usb串口设备如:USB转485/442USB转TTL串口线,会显示为/dev/ttyUSB0 之类的串口地址。);
    public class SerialPortFinder {
    
        public class Driver {
            public Driver(String name, String root) {
                mDriverName = name;
                mDeviceRoot = root;
            }
    
            private String mDriverName;
            private String mDeviceRoot;
            Vector<File> mDevices = null;
    
            Vector<File> getDevices() {
                if (mDevices == null) {
                    mDevices = new Vector<>();
                    File dev = new File("/dev");
                    File[] files = dev.listFiles();
                    if (files == null) {
                        return mDevices;
                    }
                    int i;
                    for (i = 0; i < files.length; i++) {
                        if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
                            Log.d(TAG, "Found new device: " + files[i]);
                            mDevices.add(files[i]);
                        }
                    }
                }
                return mDevices;
            }
    
            public String getName() {
                return mDriverName;
            }
        }
    
        private static final String TAG = "SerialPort";
    
        private Vector<Driver> mDrivers = null;
    
        Vector<Driver> getDrivers() throws IOException {
            if (mDrivers == null) {
                mDrivers = new Vector<Driver>();
                LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
                String l;
                while ((l = r.readLine()) != null) {
                    // Issue 3:
                    // Since driver name may contain spaces, we do not extract driver name with split()
                    String drivername = l.substring(0, 0x15).trim();
                    String[] w = l.split(" +");
                    if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
                        Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
                        mDrivers.add(new Driver(drivername, w[w.length - 4]));
                    }
                }
                r.close();
            }
            return mDrivers;
        }
    
        public String[] getAllDevices() {
            Vector<String> devices = new Vector<String>();
            // Parse each driver
            Iterator<Driver> itdriv;
            try {
                itdriv = getDrivers().iterator();
                while (itdriv.hasNext()) {
                    Driver driver = itdriv.next();
                    Iterator<File> itdev = driver.getDevices().iterator();
                    while (itdev.hasNext()) {
                        String device = itdev.next().getName();
                        String value = String.format("%s (%s)", device, driver.getName());
                        devices.add(value);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return devices.toArray(new String[devices.size()]);
        }
    
        public String[] getAllDevicesPath() {
            Vector<String> devices = new Vector<String>();
            // Parse each driver
            Iterator<Driver> itdriv;
            try {
                itdriv = getDrivers().iterator();
                while (itdriv.hasNext()) {
                    Driver driver = itdriv.next();
                    Iterator<File> itdev = driver.getDevices().iterator();
                    while (itdev.hasNext()) {
                        String device = itdev.next().getAbsolutePath();
                        devices.add(device);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return devices.toArray(new String[devices.size()]);
        }
    }
    
    1. 核心库libserial_port.so加载,通过使用谷歌官方android-serialport-api库 libs中已经编译生成的libserial_port.so文件或对jni文件夹下c文件进行重新编译生成所需,不要忘记在.gradle文件中配置jni路径。

      sourceSets {
          main {
              jniLibs.srcDirs = ['libs']
          }
      }
      
    2. 选取串口地址后,结合比特率及标志位,即可通过已加载核心库libserial_port.so进行串口打开操作;

      public class SerialPort {
      
          private FileDescriptor mFd;
          private FileInputStream mFileInputStream;
          private FileOutputStream mFileOutputStream;
      
          public SerialPort(File device, int baudRate, int flags) throws SecurityException, IOException {
      
              mFd = open(device.getAbsolutePath(), baudRate, flags);
              if (mFd == null) {
                  throw new IOException();
              }
              mFileInputStream = new FileInputStream(mFd);
              mFileOutputStream = new FileOutputStream(mFd);
          }
      
          public InputStream getInputStream() {
              return mFileInputStream;
          }
      
          public OutputStream getOutputStream() {
              return mFileOutputStream;
          }
      
          private native static FileDescriptor open(String path, int baudrate, int flags);
      
          public native void close();
      
          static {
              System.loadLibrary("serial_port");
          }
      }
      
    3. 编写的控制类,统一进行串口地址获取,打开,读取,写入及关闭操作:

    public class SerialController {
    
        private ExecutorService mThreadPoolExecutor = Executors.newCachedThreadPool();
        private InputStream inputStream;
        private OutputStream outputStream;
        private boolean isOpened = false;
        private OnSerialListener mOnSerialListener;
    
        /**
         * 获取所有串口路径
         *
         * @return 串口路径集合
         */
        public List<String> getAllSerialPortPath() {
            SerialPortFinder mSerialPortFinder = new SerialPortFinder();
            String[] deviceArr = mSerialPortFinder.getAllDevicesPath();
            return new ArrayList<>(Arrays.asList(deviceArr));
        }
    
        /**
         * 打开串口
         *
         * @param serialPath 串口地址
         * @param baudRate   波特率
         * @param flags      标志位
         */
        public void openSerialPort(String serialPath, int baudRate, int flags) {
            try {
                SerialPort serialPort = new SerialPort(new File(serialPath), baudRate, flags);
                inputStream = serialPort.getInputStream();
                outputStream = serialPort.getOutputStream();
                isOpened = true;
                if (mOnSerialListener != null) {
                    mOnSerialListener.onSerialOpenSuccess();
                }
                mThreadPoolExecutor.execute(new ReceiveDataThread());
            } catch (Exception e) {
                if (mOnSerialListener != null) {
                    mOnSerialListener.onSerialOpenException(e);
                }
            }
        }
    
        /**
         * 关闭串口
         */
        public void closeSerialPort() {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                isOpened = false;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 发送串口数据
         *
         * @param bytes 发送数据
         */
        public void sendSerialPort(byte[] bytes) {
            if (!isOpened) {
                return;
            }
            try {
                if (outputStream != null) {
                    outputStream.write(bytes);
                    outputStream.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 返回串口是否开启
         *
         * @return 是否开启
         */
        public boolean isOpened() {
            return isOpened;
        }
    
        /**
         * 串口返回数据内容读取
         */
        private class ReceiveDataThread extends Thread {
            @Override
            public void run() {
                super.run();
                while (isOpened) {
                    if (inputStream != null) {
                        byte[] readData = new byte[1024];
                        try {
                            int size = inputStream.read(readData);
                            if (size > 0) {
                                if (mOnSerialListener != null) {
                                    mOnSerialListener.onReceivedData(readData, size);
                                }
                            }
    
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    
        /**
         * 设置串口监听
         *
         * @param onSerialListener 串口监听
         */
        public void setOnSerialListener(OnSerialListener onSerialListener) {
            this.mOnSerialListener = onSerialListener;
        }
    
        /**
         * 串口监听
         */
        public interface OnSerialListener {
    
            /**
             * 串口数据返回
             */
            void onReceivedData(byte[] data, int size);
    
            /**
             * 串口打开成功
             */
            void onSerialOpenSuccess();
    
            /**
             * 串口打开异常
             */
            void onSerialOpenException(Exception e);
        }
    
    
    }
    

    以上就是本篇主要介绍的串口通信基础知识及Android串口内容调用。除了Google官方驱动库外,我们实际操作中可能还需要用到Usb转串口内容的操作,将在下篇给出具体内容。

    访问Github项目查看具体代码实现:

    https://github.com/MickJson/AndroidUSBSerialPort

    参考资料:

    百度百科串口通信:https://baike.baidu.com/item/串口通信

    谷歌串口通信库:https://github.com/cepr/android-serialport-api

    欢迎点赞/评论,你们的赞同和鼓励是我写作的最大动力!

    展开全文
  • 麦克风阵列要点

    2018-04-01 21:09:55
    1.流程麦克风()à放大器(MC1468ID)àA/D转换(AD7606)à数据采集,存储(TMS320DM642---DSP)2.上位机通信MAX3232转换芯片建立DM642与上位机转换通道9针串口 RS232协议3.不足只计算方位角、俯仰角7.主瓣,旁瓣...

    1.流程

    麦克风()à放大器(MC1468IDàA/D转换(AD7606à数据采集,存储(TMS320DM642---DSP

    2.上位机通信

    MAX3232转换芯片建立DM642与上位机转换通道

    9针串口 RS232协议

    3.不足

    只计算方位角、俯仰角


    7.主瓣,旁瓣

    在主瓣最大辐射方向两侧,辐射强度降低 3 dB(功率密度降低一半)的两点间的夹角定义为波瓣宽度(又称波束宽度或主瓣宽度或半功率角)。波瓣宽度越窄,方向性越好,作用距离越远,抗干扰能力越强。

     

    旁瓣使声能量扩散,衰减增多。目前减少旁瓣的最简单的方法是:减少物体的尺寸,使其小于或者等于波长的一半,此时将不会产生旁瓣效应。

    8.波束宽度

    信号的波束宽度,指的是在最大辐射方向两侧,辐射功率下降3dB的两个方向的夹角

    9.波长

    波长(wavelength)是指波在一个振动周期内传播的距离。也就是沿着波的传播方向,相邻两个振动位相相差2π的点之间的距离。波长λ等于波速u和周期T的乘积,即λ=uT。同一频率的波在不同介质中以不同速度传播,所以波长也不同

    10. 载波

    在通信技术上,载波(carrierwave, carrier signalcarrier)是由振荡器产生并在通讯信道上传输的电波,被调制后用来传送语音或其它信息。载波频率通常比输入信号的频率高,输入信号调制到一个高频载波上,就好像搭乘了一列高铁或一架飞机一样,然后再被发射和接收。载波是传送信息(话音和数据)的物理基础和承载工具。

    11.方向图

    阵列输出的绝对值与来波方向之间的关系

    1. 阵列输出的直接相加(不考虑信号及其来向)即静态方向图

    2. 带指向的方向图,信号的指向通过控制加权的相位来实现

    展开全文
  • 微型FM麦克风模块频率设置工具,通过串口进行频率设置. 范围76.0MHZ-108.0MHZ. 如FM收音机接收模块,或者FM发射模块,可以对这些模块进行写频.
  • 4麦克风阵列录音效果回声消除语音转文字测试 硬件性能指标 连线方式 串口通信命令 串口有RS232,TTL,直接用了TTL的串口模块。 供电12V3A主要考虑功放电流,实测电流不到1A。 喇叭声音比较好,是...

    4麦克风阵列录音效果回声消除语音转文字测试

     

    硬件性能指标

    连线方式

    串口通信命令

     

    串口有RS232,TTL,直接用了TTL的串口模块。

    供电12V3A主要考虑功放电流,实测电流不到1A。

    喇叭声音比较好,是电视机用的那种喇叭,音量也足够大。

    语音转文字效果不错,无论是否有音乐播放,基本不影响识别效果。

    识别的标点符号是软件处理问题,将标点放在了前面。

    用在广告机,ATM,智能机器人等场景还是很不错的。

     

    展开全文
  • 大家好我是人见人爱、花见花开的大魔王。 usb协议还是很烦的,cube很大程度上减轻了工作量。...多路麦克风阵列的usb设备怎么做。 打印机设备怎么搞。 hid设备怎么弄。 u盘怎么做。。。这个应该不会去写

    大家好我是人见人爱、花见花开的大魔王。

    usb协议还是很烦的,cube很大程度上减轻了工作量。但是不灵活是个大问题。

    比如我要配置一个usb接口既有虚拟串口又有usb声卡又有hid控制的设备怎么办呢?

    多弄几个芯片之后加个usb hub?不存在的!成年人的世界我都要~!

    下面为所有项目的规划列表~~~

    虚拟串口

    usb声卡。

    usb的各种控制,比如静音接打电话控制音量。

    多路麦克风阵列的usb设备怎么做。

    打印机设备怎么搞。

    hid设备怎么弄。

    u盘怎么做。。。这个应该不会去写。

    怎么把这些弄到一起,一根usb线一个漂漂亮亮的挂载一大串设备,cdc设备的集成到底怎么弄!

    所有所有的这些,咱们慢慢来!

    这次我们再来一个usb的声卡。本着柿子捡软的捏的原则开撸。。。

    1.cubemx配置

    用内部晶振就不配置外置的了

    先来个1ms定时器

    usb配置一下

    nvic搞一下

    middleware层配置

    调整一下堆和栈的大小,因为st的usb库里面有malloc。太小了肯定不行。

    点击生成

    2.程序修改

    目标做一个测试的demo:

    1.让程序1s给我的上位机发一次“我是大帅哥”

    2.上位机发啥下位机返回什么

    先来个全局变量

    引用一下头文件

    弄一个字符串

    中断文件中引用一下

    开一下定时器

    写个1s发一次的逻辑

    接收回调处理一下

    下载程序就可以看到结果了

    波特率随意设置就好

    展开全文
  • 还在为科大讯飞家的四/六麦克风阵列停产而烦恼吗?好消息是基于科大讯飞软核的全新替代产品已经来了,为新老用户使用带来了巨大便利,无缝衔接产品,不用担心产品量产后买不到麦克风阵列的问题。 新的麦克风阵列...
  • 首先要解决语音输入问题,经过一段时间的研究,发现想要实现远处也能控制就必须用到麦克风阵列,在万能的某宝上搜了一下,发现了一个宝贝,技术支持也比较给力。 usb供电,自带喇叭功放,自带回声消除,方向指示...
  • 做服务机器人需要用到麦克风阵列进行远场拾音,声学设备比较麻烦,会有很多坑,不太容易集成到设备中。使用现成的产品可以快速完成产品开发,有方便开发嵌入的板卡,还有带壳体方便安装在大型机箱里面的。 集成...
  • 最近项目在搞机顶盒这块,也接触了很多硬件知识,特此记录 1:需要设备: 1..android板子:RK3288 安卓一体板(深圳某厂商) ... 中控机控制功能:控制外放设备的麦克风大小,音量大小,静音,话筒音,音调大小等 3...
  • (也可以把录音线直接插到麦克风孔当音频输入,二合一的耳机孔不行,需要转换头) ,但每次用之前必须说出唤醒词,虽然可以设置任意唤醒词,但还是觉得不是很满意。所以就需要自己在代码了对主板进行操作了,比如...
  • matlab向串口发送指令代码适用于mbed和STM32系列MCU的I2S驱动程序 该存储库包含在STM32F4系列设备上使用I2S外设的所有必需文件。 驱动程序详细信息 这是来自的叉子。 此代码已被修改以与mbed-os版本6.2.0一起使用。 ...
  • Maix-Bit V2.0原理图

    2020-02-20 12:02:08
    Maix-Bit V2.0开发板原理图,不同于老版本,带麦克风,usb转串口芯片为CH552T,有需要的可以下载作为参考,
  • 应用笔记:SIM800C使用网络时间(NTP)同步功能 介绍 1.1SIM800C SIM800C模块可支持4频GSM/... 两路串口(一路三线串口与一路全功能串口) 一路USB接口,便于用户调试、下载软件 一路音频接口,包含麦克风
  • 笔者前段时间做的麦克风阵列上的本地AI引擎(ASR、TTS、NLP)用于语音交互,其中的结果通过串口协议发送给PC机上,在Github找了个两个串口模块,分别是WzSerialPort和CSerialPort,二者均封装了Windows的API,从工程...
  • 通过两个单片机实现距离的测量,主机控制扬声器发出一定频率的声音同时计数器开始计数,从麦克风接收到声音后经过放大滤波输出信号到从单片机,从单片机接收到信号后向通过串口向主机发送数据,主机接收到串口发送的...
  • 音频处理器的使用

    2019-09-30 03:24:41
    流程:声源 -- 麦克风 -- 音频处理器、经过音频处理器中的功率放大 -- 扬声器。 首先是对音频处理器的各个接口的功能...在它的后端,从右至左依次是:电源、扬声器、网口、串口、USB接口、输出/输入接口、麦克风接...
  • FPGA基础入门【17】开发板音频接口控制配置

    千次阅读 多人点赞 2019-09-03 23:20:56
    上一篇教程介绍的是NEXYS4开发板上的温度传感器,用上了串口通信和I2C接口,这次使用的加速度传感器使用的是SPI接口,是除了I2C之外另一种常用的接口,实用性很高 FPGA基础入门【17】开发板音频接口控制配置开发板...
  • PurpleTooth配有一个3.5mm插孔的麦克风插孔(带有附加的4针通孔麦克风适配器),一个耳机/线路输出3.5mm插孔(带附加的4针通孔左/右扬声器适配器) ,七个按钮音量,音轨,播放和配对控制,串行到微型和FTDI支持,...
  • SIM800L介绍

    千次阅读 2020-07-06 16:17:59
    SIM800L模块可支持4频GSM/GPRS,工作的频段为:GSM850、EGSM900、DCS1800和PCS1900MHz。 模块的尺寸只有17.815.... 两路音频接口,包含麦克风输入和受话器输出。  可编程的通用输入输出接口(GPIO)。  一路SI
  • 因为项目需要,需要使用语音识别技术,先立帖,再慢慢完善。 语音识别 = 录入 + 降噪 + 识别 + 动作。...因为降噪需要,可能需要多个麦克风如6麦。 识别的关键属性的字典大小。 动作可以用串口输出。...
  • 大家好我是人见人爱、花见花开的大魔王。 usb协议还是很烦的,cube很大程度上减轻了工作量。但是不灵活是个大问题。...多路麦克风阵列的usb设备怎么做。 打印机设备怎么搞。 hid设备怎么弄。 u盘怎么做。。。这个应
  • 大家好我是人见人爱、花见花开的大魔王。 usb协议还是很烦的,cube很大程度上减轻了工作量。但是不灵活是个大问题。 比如我要配置一个usb...多路麦克风阵列的usb设备怎么做。 打印机设备怎么搞。 hid设备怎么弄..
  • 2.同步串口0(McBSP0)初始化为I2S模式; 3.同步串口1(McBSP1)初始化为SPI模式; 4.中断控制寄存器初始化; 5.McBSP0发送中断服务程序; 6.McBSP0接收中断服务程序; 7.中断向量表; 8.NANDFLASH驱动程序; 9.TLV...
  • 包含STM32F103RxT6、LD3320A语音识别芯片模块(Y-05)、ESP8266、LED、SD卡、OLED屏0.96寸、蜂鸣器、麦克风、3.5mm音频输入输出口、继电器、串口电路,有其他需求可以自行修改(缺陷:7805稳压电路电流不足,可以...
  • 扩展板:四通道麦克风扩展板,GY-521 MPU-6050模块,直流电机驱动模块,锂电池电源组件 RT-Thread版本:RT-Thread Nano 开发工具及版本:STM32CubeMX 5.6.1 MDK 5.20 RT-Thread使用情况概述采用STM32CubeMX生成RT-...
  • 通过VLC软件网络串口流播放拾音器的声音。 二、设备 笔记本 IP 10.0.1.203 拾音器:淘宝某款 IP 10.0.1.201,该拾音器实际就是IPCAMRA主板加麦克风,支持ONVIF协议 三、思路 支持Onvif协议的摄像机可直接通过...
  • 麦克风FFT频谱-麦克风频谱图 重力球迷宫-重力小球走迷宫 蓬松的鸟 M5StickC项目(在./other_projects和./demo中) 规格:官方最初的demo 8563_RTC:RTC StickWatch2PowerManagment,AXP192:电源管理 docs:一些...
  • mini2440开发板 简介

    2011-01-12 16:37:42
    三星S3C2440A,主频400MHZ,最高533MHZ 板载64 SDRAM,32bit数据总线 SDRAM时钟频率高达100MHZ 128M Nand Flash, 2M Nor Flash,掉电非易失 ...标配NEC 3.5吋 TFT电阻触摸屏 ...1个立体音频输出口,1个麦克风...
  • 香橙派4是一款开源的单板电脑,使用...麦克风端口,3.5mm和HDMI2.0音频输出口,千兆以太网口,USB3.0,USB2.0,Type-C等常规标准接口,还有调试串口,40pin树莓派兼容扩展口。本篇介绍下香橙派4在Linux系统下如何使用SPI
  • 红外遥控/数码管显示/2路led跑马灯/光热敏/时钟/18b20温度/flash存储//键盘/AD/DA/继电器/蜂鸣器/喇叭/麦克风/TFT2.6彩色触摸屏/几种液晶显示接口/LED/USB通信/max232电脑串口通信/485工业总线通讯/SD存储卡读写文件...

空空如也

空空如也

1 2 3
收藏数 56
精华内容 22
关键字:

串口麦克风