[MSP-EXP432E401Y] MSP432E401系列QSSI外设高级模式下FSS引脚的控制

[复制链接]

2

主题

12

帖子

150

积分

二氧化硅

Rank: 2

积分
150
楼主
查看: 6140回复: 11 发表于 2021-4-11 17:55:12   只看该作者
在普通的SPI传输中,MSP432E的硬件FSS引脚会在每次传输完成一个字节以后拉高,而很多外设都在读取/写入大量数据时都要求传输多字节过程中片选信号保持低。因此MSP432E单片机提供了高级模式,使FSS在整个传输过程中保持低电平,下面是技术参考手册的原文(第23章1527页,SSInFSS Function)

For enhanced modes of operation, the SSInFss signal can be programmed to assert low at the start of each byte transfer for one clock or the entire frame. This is configured by programming the FSSHLDFRM bit in the SSICR1 register. The EOM bit is also provided to signify end of frame transmission. This bit is embedded in the TXFIFO entry for use at the interface to de-assert SSInFss at the appropriate time. The FSSHLDFRM bit can also be used when operating in 8-bit legacy SSI mode.
对此我的理解是,当使能了高级模式以后,SPI传输过程中FSS引脚将不会被拉高,直到EOM位被置位,标志下一字节是帧结束,此字节数据被发送完成后FSS引脚才会重新拉高

在MSP432E系列的Driverlib当中,有开启高级模式和发送帧结束字节的函数,如下所示
  1. void SSIAdvFrameHoldEnable(uint32_t  ui32Base)
  2. void SSIAdvDataPutFrameEnd(uint32_t  ui32Base, uint32_t         ui32Data )
复制代码

根据技术参考手册和Driverlib的说明,我认为使用高级模式进行spi传输应该在配置和启动外设以后,首先调用开启高级模式的函数,然后使用 SSIDataPut() 函数发送一些数据,到最后一个字节时,则调用 SSIAdvDataPutFrameEnd() 函数发送最后一个字节并指示FSS引脚拉高。代码如下
  1.     /* Enable clocks to GPIO Port Q and configure pins as SSI */
  2.     MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
  3.     while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOQ)))
  4.     {
  5.     }

  6.     MAP_GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
  7.     MAP_GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
  8.     MAP_GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
  9.     MAP_GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1);
  10.     MAP_GPIOPinTypeSSI(GPIO_PORTQ_BASE, (GPIO_PIN_0 | GPIO_PIN_1 |
  11.                                          GPIO_PIN_2 | GPIO_PIN_3));

  12.     /* Enable the clock to SSI-0 module and configure the SSI Master */
  13.     MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
  14.     while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_SSI3)))
  15.     {
  16.     }

  17.     MAP_SSIConfigSetExpClk(SSI3_BASE, systemClock, SSI_FRF_MOTO_MODE_0,
  18.                            SSI_MODE_MASTER, 100000, 8);
  19.     MAP_SSIEnable(SSI3_BASE);

  20.     SSIAdvFrameHoldEnable(SSI3_BASE);
  21.     SSIDataPut(SSI3_BASE, 0xAA);
  22.     SSIDataPut(SSI3_BASE, 0xAA);
  23.     SSIDataPut(SSI3_BASE, 0xAA);
  24.     SSIDataPut(SSI3_BASE, 0xAA);

  25.     SSIAdvDataPutFrameEnd(SSI3_BASE, 0xBB);
  26.     SSIAdvFrameHoldDisable(SSI3_BASE);
复制代码


但是逻辑分析仪抓取的波形显示并没有起到预期的效果,FSS引脚仍然在传输每个字节以后置高。逻辑分析仪得到的波形如下所示

2

主题

12

帖子

150

积分

二氧化硅

Rank: 2

积分
150
沙发
发表于 2021-4-11 17:58:22   只看该作者


我在网络上关于此的信息不多,希望了解的大佬不吝赐教

73

主题

469

帖子

1007

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1007
板凳
发表于 2021-4-12 17:48:32   只看该作者
pikka 发表于 2021-4-11 17:58
我在网络上关于此的信息不多,希望了解的大佬不吝赐教

用的SDK是哪个版本?

2

主题

12

帖子

150

积分

二氧化硅

Rank: 2

积分
150
4#
发表于 2021-4-12 21:48:53   只看该作者
shengxiang 发表于 2021-4-12 17:48
用的SDK是哪个版本?

SDK 是 SimpleLink MSP432E4 MCU SDK(4.20.00.12),IDE 是 CCS 10,编译器是 CCS Compiler

73

主题

469

帖子

1007

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1007
5#
发表于 2021-4-13 16:51:02   只看该作者
pikka 发表于 2021-4-12 21:48
SDK 是 SimpleLink MSP432E4 MCU SDK(4.20.00.12),IDE 是 CCS 10,编译器是 CCS Compiler


经过排查,这个问题和SDK版本,CCS版本无关。

你的理解基本都是对的,但是忽略里一个重要的特性:

SSI外设,带有FIFO缓冲区,往数据寄存器写数据,是往FIFO里边写数据。如果只是发送1个字节,和平常的发送没太大区别。

但是,如果一次性发送多个字节,这个时候要注意, CPU往FIFO里边写数据的速度 是快于 SSI外设对外发送数据的。
往FIFO里边写完数据了,数据存在FIFO里,还没发送完。 CPU可以继续往下执行,SSI外设也接着慢慢往外发送数据。

问题就出在这, SSI数据还没发送完,你就把 配置给修改了,所以达不到预期的效果。

你的代码只要加个延时就没问题了。

73

主题

469

帖子

1007

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1007
6#
发表于 2021-4-13 16:54:10   只看该作者
shengxiang 发表于 2021-4-13 16:51
经过排查,这个问题和SDK版本,CCS版本无关。

你的理解基本都是对的,但是忽略里一个重要的特性:
  1.     uint32_t tempDelay;
  2.     while(1)
  3.     {
  4.         SSIAdvFrameHoldEnable(SSI3_BASE);
  5.         SSIDataPut(SSI3_BASE, 0xAA);
  6.         SSIDataPut(SSI3_BASE, 0xAA);
  7.         SSIDataPut(SSI3_BASE, 0xAA);
  8.         SSIDataPut(SSI3_BASE, 0xAA);
  9.         SSIAdvDataPutFrameEnd(SSI3_BASE, 0xBB);
  10.         for(tempDelay=100;tempDelay>0;tempDelay--); //添加个延时,等待FIFO里边的数据发送完
  11.         SSIAdvFrameHoldDisable(SSI3_BASE);

  12.         for(tempDelay=60000;tempDelay>0;tempDelay--);
  13.         for(tempDelay=60000;tempDelay>0;tempDelay--);
  14.         for(tempDelay=60000;tempDelay>0;tempDelay--);

  15.     }
复制代码

73

主题

469

帖子

1007

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1007
7#
发表于 2021-4-13 16:54:49   只看该作者
示波器只有两个通道:
黄线是 数据线
蓝线是 片选信号


73

主题

469

帖子

1007

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1007
8#
发表于 2021-4-13 17:04:43   只看该作者

2

主题

12

帖子

150

积分

二氧化硅

Rank: 2

积分
150
9#
发表于 2021-4-13 18:44:25   只看该作者
shengxiang 发表于 2021-4-13 16:51
经过排查,这个问题和SDK版本,CCS版本无关。

你的理解基本都是对的,但是忽略里一个重要的特性:

非常感谢解答

2

主题

12

帖子

150

积分

二氧化硅

Rank: 2

积分
150
10#
发表于 2021-4-13 18:57:29   只看该作者
shengxiang 发表于 2021-4-13 16:51
经过排查,这个问题和SDK版本,CCS版本无关。

你的理解基本都是对的,但是忽略里一个重要的特性:

我进一步思考了不同频率下,延时长度的设置问题

首先,单独使用SPI的经典模式或者单独使用高级模式都不会引起问题,因为这时候不需要反复使能和禁用高级模式,问题只出现在两者混合使用的时候。如果没有添加延时,会出现两种问题:
1、使用普通模式发送数据,发送完FSS引脚没有拉高,这是由于还未发送完CPU已经执行了使能高级模式的语句
2、使用高级模式发送数据,发送中FSS引脚拉高,这是由于还未发送完CPU已经执行了禁用高级模式的语句

因此,混合使用两种模式时,普通模式和高级模式发送后都要添加延时,且延时时间应经过计算。我个人的分析结果如下:在外设配置为1MHz,数据位8bit的情况下,发送单个字节需要的时间是10us,包含发送数据的8us和两字节间隔2us,因此发送一个byte的延时时间可设置为10us。使用阻塞发送传输超过8byte的数据时,CPU会在FIFO满的情况下等待,因此按8byte算即可,再算上数据寄存器的1byte,延时100us是合适的选择。若将spi频率设置为100k,则对应延时时间乘10,其他频率应可以此类推。

73

主题

469

帖子

1007

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1007
11#
发表于 2021-4-14 14:57:57   只看该作者
pikka 发表于 2021-4-13 18:57
我进一步思考了不同频率下,延时长度的设置问题

首先,单独使用SPI的经典模式或者单独使用高级模式都不 ...


有个状态寄存器,可以考虑下,譬如说忙标识,FIFO是否为空等,可以使用起来。

2

主题

12

帖子

150

积分

二氧化硅

Rank: 2

积分
150
12#
发表于 2021-4-14 15:01:19   只看该作者
shengxiang 发表于 2021-4-14 14:57
有个状态寄存器,可以考虑下,譬如说忙标识,FIFO是否为空等,可以使用起来。 ...

对哦,我还想复杂了hhh
快速回复 返回顶部 返回列表