最近在调试硬件SPI,之前使用软件模拟方式,为了提高速度,选择该方式进行替换。
花了一些时间了解寄存器跟库函数直接调用,结果要么读取不出数据(陷入等待TXE,RXNE死循环)或读取数据为0xffff,0x0101(nSS拉低之后没有跳变,或者Send/Write分开写,没有形成环形FIFO Shift,根据全双工协议,读写应该同时进行)。后来才在网上查找资料,并认真阅读STM32的RM,整理如下:
1、整体的框架如图
2、nSS详解
In slave mode, the NSS works as a standard “chip select” input and lets the slave communicate with the master. In master mode, NSS can be used either as output or input.As an input it can prevent multimaster bus collision, and as an output it can drive a slave
select signal of a single slave.
nSS的介绍在上面的图片包含了所有信息。
SSM = 1时,nSS为软件管理模式(即nSS由程序控制SSIbit决定,与硬件无关),此时Output Contorl无效(~SSM = 0 Disable OC),输入由SSI决定(SSI决定SPI为Master/Slaver,SSM = 1,多工器选择SSI 连接到 NSS input),因此输出就可以配置为GPIO用来控制其他Slaver的nSS(Master),或GPIO其他功能(Slaver)。如果为Master,可以通过把nSS配置为PP,在整个ADDR+DATA中进行Cls与Set,硬件设计中nSS不论是配置为软件管理还是硬件管理都无法自动跳变,必须通过GPIO的方式在适合的位置进行Pull Low|Pull High,实际上着并不是ST设计的缺陷,如果在每次R/W的前后对nSS进行自动跳变,读取值会错误,比如设置寄存器值,在发送ADDR后接着发送Data,在这个过程中nSS应当保持低电平,不允许跳变,因此自动跳变不满足实际需求。此时SSOE NPSS bit均无效。
SSM = 0时,nSS为硬件管理模式(即nSS由硬件GPIO口读取回来的值决定),此时多工器选择NSS External连接到NSS input,且Output Control由SSOE决定,因此可以分为两种情况:
SSOE = 1 ,此时SPI只能工作在Master Mode,此时nSS在EnableSPI之后,强制拉低,不能跳变,实际测试无法通过NSSP设置使其产生跳变。
SSOE = 0,此时nSS用于检测此时的SPI处于Master/Slaver,当我们设置为Master时,若检测该nSS为Low,会自动配置为SlaverMode,可适用于多 主机的情况。-->To be tested
3、Write/Read 函数
沿用之前软件模拟的方式,只进行读/写单项操作,会出现读取的值恒定为0x0101等,后来查看RM得知,全双工模式为读写同时在MISO与MOSI中进行,因为全双工内部配置为内部回环FIFO,通过同时RW进行Shift。所以READ/WRITE需要同时进行,才能正确读写,当读取一个值时,写入的值不影响Slaver,为DummyWrite,写入值的时候,Read回来的值为0xff。DummyWrite的值可以为任意值,一般使用0xff或0x00。全双工见图:
以上根据RM进行整理并实验。希望对其他被nSS等问题困惑的朋友有帮助,如有不同意见,欢迎讨论。