0. 引言

与第二篇can对应,第三篇本来想写lin的,毕竟都是车身上常用的总线。但是lin比较麻烦,所以先拖后一下,先把SPI记录一下。
SPI在我们的系统架构中是S32K和ADAS之间做数据传输用的,毕竟速率够高,一般都是上M,数据量能传的比较大。

1. 准备

1.1 SPI基础知识

这部分不再赘述了,可以参见SPI基础要点
SPI是个全双工的总线,在发送的时候同时也在接收。

1.2 开发环境

1.2.1 软件开发环境

SDK: S32 DESIGN STUDIO for ARM,Version : 2018.R1。
Lib: RTM3.0.0。
Compnent:can_pal。

1.2.2 硬件环境

为了通用,硬件没用项目的硬件,还是使用的就是官网的黄色长条开发板,在第一篇里介绍过。

因为手头已经没有SPI的调试环境了,这一篇我就纯写分析和一些问题记录,不上板实测了,如果哪里有问题,可以一起讨论。

2. Demo

2.1 Demo工程选择

SPI相关的自带demo有3个,如下:
在这里插入图片描述

  • LPSPI_S32K144:主要是基于寄存器来做的,用的不是SDK的库,先略过。
  • lpspi_dma_s32k144: 使用DMA来做的SPI数据接收。
  • lpspi_transfer_s32k144:最基本的SPI的传输例程

另外,去网上下载了一个例程,也比较有参考性。

  • spi_pal_s32k144:忘了从哪找到的了,貌似是从NXP的社区下载的。原地址找不到了,

注意,如果导入demo之后编译不过,可以重新生成一下代码,再编译。
在这里插入图片描述
在这里插入图片描述

2.2 Demo分析

这里选用最简单的lpspi_transfer_s32k144工程来做分析。
程序说明很简单;
在这里插入图片描述
从SPI0 发送 数据到SPI1,使用引脚如下:
在这里插入图片描述

2.3 接口分析

其实SPI的接口很简单,除去GPIO的初始化之外,跟SPI的控制器有关系的且常用就是:

  1. LPSPI_DRV_MasterInit
  2. LPSPI_DRV_MasterTransfer(Blocking)
  3. LPSPI_DRV_SlaveInit
  4. LPSPI_DRV_SlaveTransfer(Blocking)

因为我们只用从模式,这里分析一下从机的两个接口,master其实类似,就是主机提供时钟,直接发送,从机准备数据,等待时钟再发送。

2.3.1 LPSPI_DRV_SlaveInit

这个接口其实就是把在pe中图像化配置的参数都init进去,没啥特别要说的。
在这里插入图片描述

2.3.2 LPSPI_DRV_SlaveTransfer(Blocking)

这个就是传输数据的接口,Blocking是有一个发送超时的机制。注意,这个接口只是把要发送的数据的地址和长度配置进去,并不是真的发送掉了。
从机的发送需要等主机给时钟才能发送。
需要注意的就是:
要发送的buffer的数据,不要调用完发送接口就修改,因为这个时候还没真正的发掉,一旦修改了,等主机的时钟过来的时候,真正发出去的就是修改后的数据了。
这个真正发送的过程,可以在来时钟的时候使用中断实现或者dma实现,这个是库里做好的,我们只要选择功能即可。
在这里插入图片描述

3. 调试实际遇到的问题

3.1 SPI波形很丑

因为我们是S32K做从机,前期调试的时候,是从网上买了一个USB转SPI的设备,Ginkgo USB-SPI来调试的。
就是这个第三方设备发送,S32K接收,但是波形一直很丑。
想不出来为什么,各种波形都实验了。
后来发现要把时钟频率降低。。
36Mhz做不出来。
估计买的调试器太垃圾了。

之前调试:
在这里插入图片描述

频率调低之后:
在这里插入图片描述

3.2 模式配置异常

S32K是和xilinx的7020通信的,7020是linux做主,S32k做从。
linux这边,使用的模式mode1,即CPOL = 0,CPHA = 0。
但是S32K这边同模式配置来接收,一直异常。
S32K这边的CPOL要配置成1才能接收对。
没办法,这个问题一直遗留着,还没解。

3.3 总线busy,无法发送

在实际使用中,Spi总线上有时候会偶现出现错误,一旦出现了错误,就会导致控制器认为总线是busy态,上一次的数据没有发送完,新的SPI一直发不出去。
调试遇到的实际情况就是在调用发送接口是,进去获取总线状态就是busy,然后就return了,不会进发送的流程。
我们最后采用的方案是:
在发送之前获取一些总线状态,如果不是预期的状态,就采用强制中断,重新初始化的方式来进行恢复。

LPSPI_DRV_SlaveAbortTransfer(LPSPICOM1);
LPSPI_DRV_SlaveDeinit(LPSPICOM1);
LPSPI_DRV_SlaveInit(LPSPICOM1,&lpspiCom1State,&lpspiCom1_SlaveConfig0);    			//SPI

逻辑如下:
在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐