Android Things:外设I/O接口-SPI

一、接口简介


串行外围接口(Serial Peripheral Interface)设备通常需要快速的数据传输速率。SPI适合高带宽使用情况,如外部非易失性存储器和图形显示,许多传感器除了I2C也支持SPI。

SPI总线是一种同步的串行接口: 这意味着它依赖于共享的时钟信号来同步设备之间的数据传输。控制时钟信号的设备被称为master。其它所有连接的外设被认为是Slaves。每个设备连接到同一组数据信号以形成总线。从理论上讲,SPI数据传输率是仅限于master切换时钟信号的快慢。时钟速度通常在16MHz到25MHz范围。高速共享时钟允许SPI外设更快的传输数据,比UART错误更少。

SPI支持全双工数据传输:意味着master和slave可以同时交换数据。为了支持全双工传输,总线必须提供下列单独的信号,使得SPI最少四线接口:

  • Master出Slave入(MOSI);
  • Mater入Slave出(MISO);
  • 共享时钟信号(CLK);
  • 共同的接地参考(GND);

SPI支持同一总线连接多个从设备:和I2C不同,slave设备使用硬件寻址。每个slave都需要外部芯片选择信号,来让master定位特定的设备作为数据传输的目标。如果仅仅使用一个slave这个信号就不必须。

Android Things:外设I/O接口-SPI_第1张图片
SPI引脚图

二、接口使用


1. 打开连接
创建PeripheralManagerService对象,使用你想打开端口的名称,调用open()方法打开连接。

public class HomeActivity extends Activity {
    // SPI Device Name
    private static final String SPI_DEVICE_NAME = ...;

    private SpiDevice mDevice;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Attempt to access the SPI device
        try {
            PeripheralManagerService manager = new PeripheralManagerService();
            mDevice = manager.openSpiDevice(SPI_DEVICE_NAME);
        } catch (IOException e) {
             Log.w(TAG, "Unable to access SPI device", e);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mDevice != null) {
            try {
                mDevice.close();
                mDevice = null;
            } catch (IOException e) {
                Log.w(TAG, "Unable to close SPI device", e);
            }
        }
    }
}

2. 配置时钟和数据模式
在一个SPI总线连接建立之后,配置数据传输速率和操作模式来匹配同一条总线上的Slave设备。为了成功的传输数据,在总线的所有设备必须具有相同的时钟和数据格式行为。

设置SPI模式,定义了时钟信号的极性和相位。你选择的属性基于三个属性:


Android Things:外设I/O接口-SPI_第2张图片
image.png
  • 闲置级别:当没有数据传输的时候,时钟信号的级别(或高或低);
  • 前沿:每个时钟脉冲的前沿;
  • 后沿:每个时钟脉冲前沿相反过渡;

支持以下模式:
- MODE0-时钟信号闲置为低,数据传输在前时钟边沿;
- MODE1-时钟信号闲置为高,数据传输在后时钟边沿;
- MODE2-时钟信号闲置为低,数据传输在前时钟边沿;
- MODE3-时钟信号闲置为高,数据传输在后时钟边沿;

设置如下SpiDevice参数:
- 频率:以Hz为单位指定共享时钟信号。时钟信号的能力在不同的设备之间有所不同。在设置这个值之前,你应该确认下你设备支持的频率。
- xxx:指定在总线上传输的每个字节中比特的顺序,这也被称为数据的字节序。默认情况下,数据将会把最高有效位(MSB)首先发送。
- 每个字的比特:配置一次传输的比特数,...,默认的值是8比特每字。

public void configureSpiDevice(SpiDevice device) throws IOException {
        // Low clock, leading edge transfer
        device.setMode(SpiDevice.MODE0);

        device.setFrequency(16000000);     // 16MHz
        device.setBitsPerWord(8);          // 8 BPW
        device.setBitJustification(false); // MSB first
}

3. 传输数据

  • SPI支持半双工和全双工数据传输。
  • 大多数应用程序应该都使用半双工write()或read()方法与Slave设备交换数据。
// Half-duplex data transfer
public void sendCommand(SpiDevice device, byte[] buffer) throws IOException {
      // Shift data out to slave
      device.write(buffer, buffer.length);

      // Read the response
      byte[] response = new byte[32];
      device.read(response, response.length);
      ...
}
  • 要想执行全双工交换使用transfer()方法。这个而方法接受读和写两个缓冲。写缓冲包含发送给Slave的数据,然而读缓冲是空的来接受Slave的数据。数据的长度必须小于或者等于数据缓冲的最小缓冲的大小。常见的全双工传输缓冲区大小是相等的。
// Full-duplex data transfer
public void sendCommand(SpiDevice device, byte[] buffer) throws IOException {
      byte[] response = new byte[buffer.length];
      device.transfer(buffer, response, buffer.length);
    ...
}

4. 关闭连接
当你完成和外部设备的通信,调用close()方法关闭连接并释放资源。此外在现有端口关闭之前,你不能打开相同端口的新连接。

public class HomeActivity extends Activity {
    // SPI Device Name
    private static final String SPI_DEVICE_NAME = ...;
    private SpiDevice mDevice;

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mDevice != null) {
            try {
                mDevice.close();
                mDevice = null;
            } catch (IOException e) {
                Log.w(TAG, "Unable to close SPI device", e);
            }
        }
    }
}

三、案例演示


下面我们就通过spi接口,控制Max7219模块的显示来演示接口的使用。
1. 硬件准备

  • 树莓派开发板 1块
  • 面包板 1块
  • Max7219点阵模块
  • 杜邦线(公对母)若干

2. 电路搭建(注意,没有找个对应的元器件图,下图多一个引脚)

Android Things:外设I/O接口-SPI_第3张图片
电路图

3. 代码编写
SpiDemo\app\src\main\java\com\chengxiang\spidemo\MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String SPI_DEVICE_NAME = "SPI0.0";

    private static final byte OP_NOOP = 0;
    private static final byte OP_DIGIT0 = 1;
    private static final byte OP_DIGIT1 = 2;
    private static final byte OP_DIGIT2 = 3;
    private static final byte OP_DIGIT3 = 4;
    private static final byte OP_DIGIT4 = 5;
    private static final byte OP_DIGIT5 = 6;
    private static final byte OP_DIGIT6 = 7;
    private static final byte OP_DIGIT7 = 8;
    private static final byte OP_DECODEMODE = 9;
    private static final byte OP_INTENSITY = 10;
    private static final byte OP_SCANLIMIT = 11;
    private static final byte OP_SHUTDOWN = 12;
    private static final byte OP_DISPLAYTEST = 15;

    public static final byte[] ALIEN_FRAME_1 = new byte[]{
            (byte)0b00001000,
            (byte)0b00011000,
            (byte)0b00001000,
            (byte)0b00001000,
            (byte)0b00001000,
            (byte)0b00001000,
            (byte)0b00001000,
            (byte)0b00000000
    };

    public static final byte[] ALIEN_FRAME_2 = new byte[]{
            (byte)0b00011000,
            (byte)0b00100100,
            (byte)0b00100100,
            (byte)0b00000100,
            (byte)0b00001000,
            (byte)0b00010000,
            (byte)0b00111110,
            (byte)0b00000000
    };
    public static final byte[] ALIEN_FRAME_3 = new byte[]{
            (byte)0b00011000,
            (byte)0b00100100,
            (byte)0b00000100,
            (byte)0b00011000,
            (byte)0b00000100,
            (byte)0b00100100,
            (byte)0b00011000,
            (byte)0b00000000
    };

    public static final byte[][] FRAMES = new byte[][]{ALIEN_FRAME_1, ALIEN_FRAME_2, ALIEN_FRAME_3};
    private SpiDevice mDevice;
    private byte[] spidata = new byte[2];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        try {
            //打开SPI接口连接
            PeripheralManagerService manager = new PeripheralManagerService();
            mDevice = manager.openSpiDevice(SPI_DEVICE_NAME);

            //设置SPI信号模式、频率、每个字比特数等
            mDevice.setMode(SpiDevice.MODE0);
            mDevice.setFrequency(1000000);
            mDevice.setBitsPerWord(8);
            mDevice.setBitJustification(false);

            //设置译码模式,0-用于驱动LED点阵屏
            spiTransfer(OP_DECODEMODE, 0);
            //设置扫描限制,显示7行
            spiTransfer(OP_SCANLIMIT, 7);
            //设置显示器检测,0-一般模式
            spiTransfer(OP_DISPLAYTEST, 0);
            //设置停机为false
            spiTransfer(OP_SHUTDOWN, 1);
            //设置显示强度为3
            spiTransfer(OP_INTENSITY, 15);

            while (true) {
                for (int i = 0; i < FRAMES.length; i++) {
                    for (int j = 0; j < FRAMES[i].length; j++) {
                        spiTransfer((byte) (OP_DIGIT0 + j), FRAMES[i][j]);
                    }
                    Thread.sleep(500);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mDevice != null) {
            try {
                mDevice.close();
                mDevice = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void spiTransfer(byte opcode, int data) throws IOException {
        spidata[0] = opcode;
        spidata[1] = (byte) data;
        mDevice.write(spidata, 2);
    }
}

4. 运行结果
运行程序,显示器上闪烁显示1,2,3数字如下:

Android Things:外设I/O接口-SPI_第4张图片
显示数字2

Android Things:外设I/O接口-SPI_第5张图片
显示数字3


1.抛弃各种找元器件的烦恼,来“1024工场”旗舰店,一次性买到你所想要的:树莓派套装—专为Android Things打造。

Android Things:外设I/O接口-SPI_第6张图片
树莓派套装

电脑用户,点击如下链接进入淘宝宝贝页面:
https://item.taobao.com/item.htm?spm=686.1000925.0.0.3f11c9ed68fPu7&id=549263158263
手机用户,打开淘宝客户端扫描二维码:
Android Things:外设I/O接口-SPI_第7张图片
宝贝二维码

2.完整和持续更新的《使用Android打开物联网开发大门——Andoid Thigns开发》文档,欢迎大家阅读!
https://www.kancloud.cn/workshop1024/android_things_develop/360773
Android Things:外设I/O接口-SPI_第8张图片
这里写图片描述

3.新技术,新未来!欢迎大家关注“1024工场”微信服务号,时刻关注我们的最新的技术讯息。(甭客气!尽情的扫描或者长按!)
Android Things:外设I/O接口-SPI_第9张图片
服务号

4.加入“Android Things开发”QQ讨论群,一起学习一起Hi。(甭客气!尽情的扫描或者长按!)
Android Things:外设I/O接口-SPI_第10张图片
qq群

你可能感兴趣的:(Android Things:外设I/O接口-SPI)