STM32 SPI NSS 引脚为不能拉高问题

使用过 STM32 的SPI 的朋友可能都会发现一个问题,那就是其NSS引脚 在硬件模式下无法自动拉高,可能也因为这个原因致使  。大部分朋友在使用SPI时候都是优先选用软件 控制NSS引脚的工作模式。

最近想用 SPI 直接 DMA 对一传感器进行数据通信,想直接用SPI的硬件NSS控制模式来操作SPI(之前一直是软件模式,这次对 CPU时间比要求较高,不想再用软件去切换引脚 ):

引脚配置 及 SPI DMA 配置如下:

/* 引脚配置 */
  GPIO_InitStructure.GPIO_Pin =  SPI_MASTER_PIN_NSS | SPI_MASTER_PIN_SCK | SPI_MASTER_PIN_MOSI | SPI_MASTER_PIN_MISO; // 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(SPI_MASTER_GPIO, &GPIO_InitStructure);


/* SPI_配置 ----*/
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;  // 36M/4 = 9M
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI_MASTER, &SPI_InitStructure);

SPI_SSOutputCmd(SPI_MASTER, ENABLE);
SPI_I2S_DMACmd(SPI_MASTER, SPI_I2S_DMAReq_Tx, ENABLE);
SPI_Cmd(SPI_MASTER, ENABLE);

SPI_Cmd(SPI_MASTER, ENABLE);

DMA_DeInit(SPI_MASTER_Tx_DMA_Channel);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI_MASTER_DR_Base;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = BufferSize;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(SPI_MASTER_Tx_DMA_Channel, &DMA_InitStructure);

DMA_Cmd(SPI_MASTER_Tx_DMA_Channel, ENABLE);
while( DMA_GetFlagStatus(DMA1_FLAG_TC3) == RESET );

采用以上的配置发现,使能DMA 后,SPI有时钟和数据输出,说明SPI可以成功发送数据,但是问题的全程NSS引脚一直拉低( 按常理应该是SPI在发送数据时,NSS拉低,数据发送完成后NSS自动拉高才对),检查电路连接没有问题后再回去看ST官方手册发现其NSS的高低电平定义如下:

STM32 SPI NSS 引脚为不能拉高问题_第1张图片

       意思是说 SPI主模式下,启用石硬件NSS控制模式,并且NSS输出使能后,只要SPI模块打开,其NSS引脚就输出低电平,而且低电平将持续到SPI模块关闭(注意这里并不是发送数据完成,这就尴尬了,还用要手动去开关SPI模块),到这里是乎找到些线索,那就手动去关闭SPI和使能模块吧,将会用来下面的两个接口函数(也可以直接操作寄存器):

SPI_Cmd(SPI_MASTER, DISABLE);

SPI_Cmd(SPI_MASTER, ENABLE);

可以当我手动关闭SPI后,再去看NSS引脚电平时,发现其还是处于拉低状态(好坑呀,怎么还是低),不过这次的低电平好像还不如开启时低的那么稳定(用示波器看),怀疑此时NSS引脚处释放状态(内部并没有控制输出),给它外部上拉一个10K到3.3V的上拉电阻后,发现NSS引脚被成功拉高,进一步证实了前面的怀疑。这时后发现ST文档也好鸡贼,它并没有说明SPI模块关闭后NSS引脚会被拉高,只是说了在模块并闭前 NSS引脚都是低电平。这样一来发现又回到了解放前,感觉还是不能直接用硬件NSS模式。

如果非要用NSS硬件模式,电路设计时最好给NSS引脚接外部上拉电阻到高电平,不然就只好用NSS软件管理模式,用软件用切换NSS引脚电平。

真心感觉STM32 的SPI 硬件NSS功能太鸡肋,绝大多数场景都不适用。



        




你可能感兴趣的:(嵌入式软件)