# SPI 驱动 # 这一节详细讲解 TI CC13x0/CC26x0 SDK 开发平台,基于 TI-RTOS 的 SPI 驱动实现。主要了解 SPI 驱动的分层实现、驱动接口以及结合开发板板载 SPI Flash 调试。 ## 概述 ## SPI (Serial Perripheral Interface)串行外设接口,是 Motorala 公司推出的一种同步串行接口技术。它能够使 MCU 以全双工(数据能够同时进行双向传输)的同步串行方式与各种外围设备进行高速数据通信。 SPI 主要用在 EEPROM 、 Flash 、实时时钟( RTC )、数模转换器( ADC )、数字信号处理器( DSP )以及数字信号解码器之间。只占用芯片的 4 根管脚来实现控制和数据传输,现在很多芯片上也集成了 SPI 技术。SPI 有时也称为 SSI(同步串行接口),SPI 的控制方式采用主-从模式( Master - Slave )。 SPI 驱动程序能够驱动芯片与外围设备在 SPI 总线上进行数据的传输和接收。SPI 驱动程序接口是典型的 RTOS 应用程序调用接口,它们被重定向到 `SPI_FxnTalble` 中指针指定的特定驱动程序,增强了程序的移植性。 ## SPI 驱动的分层实现 ## 虽然在应用层直接调用几个驱动接口就可以在 SPI 总线上发送数据,但驱动程序内部从接口函数到底层硬件的操作是多层封装的。如图 1 所示是SPI驱动程序的分层实现图。 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/qudongfencengtu.png) 图1. SPI 驱动程序的分层实现 图 1 表明开发者只需要直接调用中间件层的驱动接口(例如:SPI_init、SPI_open 等等)就可以实现 SPI 的驱动功能。中间件层就是程序中的 SPI.c 和 SPI.h 所在层。 中间件层规范统一了应用程序的调用接口,对于 TI 不同类型的芯片平台在这一层给出的接口是一样的,应用层都是调用相同的接口来实现 SPI 功能。这样做的好处是增强了程序的可移植性,不管你的平台怎么换,应用程序都是不变的。 中间件层往下就是业务逻辑层,从业务逻辑层开始往下根据不同的芯片平台其接口封装实现就不尽相同了。以CC26XX芯片平台为例,业务逻辑层就位于 SPICC26XXDMA.c 和 SPICC26XXDMA.h 所在的层。 业务逻辑层采用 DMA 的数据传输方式,主要操控 DMA 进行数据传输以及调用驱动库中的一些函数实现相应功能。需要注意的是:这一层封装的驱动接口函数被全部放在一个函数指针结构体中。 如清单 1 所示,中间件层不直接调用这些驱动接口,而是通过一个配置文件( CC2640R2_LAUNCHXL.c )将装有驱动接口指针的结构体指针注册到 SPI_config 中。 如清单 2 所示,这样中间件层通过调用 SPI_config 中的结构体指针就可以指定使用业务逻辑层的驱动接口了。 清单1.业务逻辑层驱动接口指针结构体 ```C const SPI_FxnTable SPICC26XXDMA_fxnTable = { SPICC26XXDMA_close, SPICC26XXDMA_control, SPICC26XXDMA_init, SPICC26XXDMA_open, SPICC26XXDMA_transfer, SPICC26XXDMA_transferCancel }; ``` 清单2. SPI_config 中的驱动接口结构体指针注册 ```C const SPI_Config SPI_config[CC2640R2_LAUNCHXL_SPICOUNT] = { { .fxnTablePtr = &SPICC26XXDMA_fxnTable, .object = &spiCC26XXDMAObjects[CC2640R2_LAUNCHXL_SPI0], .hwAttrs = &spiCC26XXDMAHWAttrs[CC2640R2_LAUNCHXL_SPI0] }, { .fxnTablePtr = &SPICC26XXDMA_fxnTable, .object = &spiCC26XXDMAObjects[CC2640R2_LAUNCHXL_SPI1], .hwAttrs = &spiCC26XXDMAHWAttrs[CC2640R2_LAUNCHXL_SPI1] }, }; ``` 业务逻辑层再往下就是驱动库层( driver library ),业务逻辑层直接调用这一层的接口函数进行相应逻辑操作。驱动库层位于 ssi.c 和 ssi.h 所在的层,这一层就开始与硬件接触,进行相应寄存器操作来实现 SPI 驱动了。 ## SPI 的驱动配置 ## 之前已经提到 SPI 的配置数组 SPI_config[],它位于相应芯片平台的配置文件中。以 CC26XX 芯片平台为例,其配置文件为 CC2640R2_LAUNCHXL.c 。清单 3 是 CC2640R2_LAUNCHXL.c 中关于 SPI 的配置代码段。 清单3. UART 的配置代码段 ```C /* * =============================== SPI DMA =============================== */ #include #include SPICC26XXDMA_Object spiCC26XXDMAObjects[CC2640R2_LAUNCHXL_SPICOUNT]; const SPICC26XXDMA_HWAttrsV1 spiCC26XXDMAHWAttrs[CC2640R2_LAUNCHXL_SPICOUNT] = { { .baseAddr = SSI0_BASE, .intNum = INT_SSI0_COMB, .intPriority = ~0, .swiPriority = 0, .powerMngrId = PowerCC26XX_PERIPH_SSI0, .defaultTxBufValue = 0, .rxChannelBitMask = 1< Download -> Download Active Application ** 。如图 10 所示将程序下载到调试板中。 7. 打开串口调试助手,连接上对应的端口,在[ CC13X0/CC26X0 Evaluation Board ](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-16843957259.1.4e9ffef7qpJP8Z&id=554782561045&scene=taobao_shop)上按下复位键,可以看到 Manufacturer/Device ID 被打印到串口调试工具上,如图 11 所示。 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/chuankoudisplay.png) 图11. Manufacturer/Device ID 被打印出来 8. 如图 12 所示,将逻辑分析仪的各个通道分别连接[ CC13X0/CC26X0 Evaluation Board ](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-16843957259.1.4e9ffef7qpJP8Z&id=554782561045&scene=taobao_shop)上对应的 SPI 四个端口** SS/CS **(DIO20)、** SCK **(DIO10)、** SDO/MOSI **(DIO9)、** SDI/MISO **(DIO8),对于具体是哪几个 IO 口可以在文档[ CC13X0CC26X0EvaluationBoard ](http://docs.leconiot.com/doku.php?id=cc2640r2f:leconiot:cc13x0_cc26x0_evaluation_board:cc13x0_cc26x0_evaluation_board)中查看。 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/logicAnalyzerlink.jpg) 图12. 逻辑分析仪的通道连接 9. 打开逻辑分析仪( Saleae Logic 1.1.15 ),首先配置好 SPI 接口,软件右侧** Analyzers **下的 SPI 选项下配置,如图13所示。 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/editlogicanlyzer.png) 图13. SPI 接口的配置 10. 选择之后你可以看到如图 14 所示的配置界面,将各个端口对应的通道配置好,点击** Save **保存。 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/edititem.png) 图14. 逻辑分析仪的配置界面 11. 如图 15 所示点击界面上方的** Start **按钮,会弹出如图 16 所示的界面。 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/logicanlyzerstart.png) 图15. Start 界面 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/startgetdata.png) 图16. 弹出的界面 12. 在[ CC13X0/CC26X0 Evaluation Board ](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-16843957259.1.4e9ffef7qpJP8Z&id=554782561045&scene=taobao_shop)上按下复位键,点击图 16 所示界面的** stop **按钮。 13. 这样就可以看到向 Flash 输入数据、读出数据的时序图。如图17所示,输入的指令与程序是完全符合的,读出 Manufacturer/Device ID 与串口打印的结果也是完全符合的。 ![](http://www.leconiot.com/md_res/cc2640r2f/peripheral_driver/spi/images/logicanlyzer.png) 图17. Flash 输入数据、读出数据的时序图 ## 加入我们 ## 文章所有代码、工具、文档开源。加入我们[**QQ群 591679055**](http://shang.qq.com/wpa/qunwpa?idkey=d94f12d37c3b37892af4b757c6dc34bea140f3f3128a8d68e556a3d728148e85)获取更多支持,共同研究CC2640R2F&BLE5.0。

CC2640R2F&BLE5.0-乐控畅联 © Copyright 2017, 成都乐控畅联科技有限公司.