解决STM32 SPI 半残废 NSS无法拉高
眾所周知,STM32 ?SPI是個半殘廢,NSS無法自動拉高,所以使用SPI 從機會一直使能,當主機是一對多的時候,就會出現SPI從機互相干擾的問題。
我利用GPIO中斷,代替NSS引腳,使用過程如下代碼所示
1.初始化SPI ?的IO口,其中NSS引腳先不管。
?
void GPIO_SPI12_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//----- 第1步:打開SPI部件的時鐘 --------------------------------------------------------------------------------------------
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
//----- 第2步:打開SPI相關的引腳為復用推挽輸出 -----------------------------------------------------------------------------
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
/* SPI SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = SPI12_SCK_PIN;
GPIO_Init(SPI12_SCK_GPIO_PORT, &GPIO_InitStructure);
/* SPI MOSI pin configuration */
GPIO_InitStructure.GPIO_Pin = SPI12_MOSI_PIN;
GPIO_Init(SPI12_MOSI_GPIO_PORT, &GPIO_InitStructure);
/* SPI MISO pin configuration */
GPIO_InitStructure.GPIO_Pin = SPI12_MISO_PIN;
GPIO_Init(SPI12_MISO_GPIO_PORT, &GPIO_InitStructure);
// STM32 SPI 的CS引腳不會自動拉高,所以用GPIO中斷代替
// GPIO_InitStructure.GPIO_Pin = SPI12_CS_PIN;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
// GPIO_Init(SPI12_CS_GPIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(SPI12_SCK_GPIO_PORT, SPI12_SCK_SOURCE, SPI12_SCK_AF);
GPIO_PinAFConfig(SPI12_MOSI_GPIO_PORT, SPI12_MOSI_SOURCE, SPI12_MOSI_AF);
GPIO_PinAFConfig(SPI12_MISO_GPIO_PORT, SPI12_MISO_SOURCE, SPI12_MISO_AF);
// GPIO_PinAFConfig(SPI12_CS_GPIO_PORT, SPI12_CS_SOURCE, SPI12_CS_AF);
}
?
?
2.再初始化SPI,初始化方式是從機子模式,這時候先不要使能SPI。
void?SPI12_Config(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_RxFIFOThresholdConfig(SPI1,SPI_RxFIFOThreshold_QF);
//----- 第3步:配置SPI的參數設定 --------------------------------------------------------------------------------------------
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //雙線雙向全雙工
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; //設置為主模式SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //發送接收8 位數據
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //時鐘懸空為低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //數據捕獲于第二個時鐘沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信號由軟件管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //設置波特率為去64 分頻
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //數據傳輸從MSB 位開始
SPI_InitStructure.SPI_CRCPolynomial =?7; //校驗
SPI_Init(SPI1, &SPI_InitStructure);
SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,DISABLE);
SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,DISABLE);
SPI_ITConfig(SPI1, SPI_IT_RXNE,DISABLE); //接收中斷失能
SPI_ITConfig(SPI1, SPI_IT_TXE, DISABLE); //發送中斷失能
//----- 第4步:使能SPI1, 配置完畢 ------------------------------------------------------------------------------------------
SPI_Cmd(SPI1, DISABLE);
}
?
?
?3. 將NSS引腳配置成GPIO中斷,這里NSS 引腳為PA15,配置過程如下代碼
void?Exti_15_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // 配置中斷時鐘
//----- 設置外部中斷引腳,用戶根據實際情況自行修改 ------------------------------------------------------------------------------
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; // 輸入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2; // 快速
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;?// 上拉
GPIO_Init(GPIOA, &GPIO_InitStructure);
//----- 設置NVIC初始化 ------------------------------------------------------------------------------
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn; // 中斷通道
NVIC_InitStructure.NVIC_IRQChannelPriority =?0; // 中斷優先級(0-3)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能
NVIC_Init(&NVIC_InitStructure);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, GPIO_PinSource15);?//連接中斷線路
EXTI_InitStructure.EXTI_Line = EXTI_Line15; //設置中斷線路
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;?//雙沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE;?//中斷線使能
EXTI_Init(&EXTI_InitStructure);?//初始化中斷
}
?
?
4. 寫GPIO中斷服務函數,該函數的主要工作判斷NSS引腳的電平,若NSS為低電平則使能SPI,否則失能SPI。
void SPI1_NSS_Handler(void)
{
if(GPIO_ReadInputDataBit(SPI12_CS_GPIO_PORT,SPI12_CS_PIN)!=RESET)
{
SPI_Cmd(SPI1,DISABLE);
}
else
{
SPI_Cmd(SPI1,ENABLE);
}
}
void EXTI4_15_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line15) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line15);
SPI1_NSS_Handler();
}
}
總結
以上是生活随笔為你收集整理的解决STM32 SPI 半残废 NSS无法拉高的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32 CAN 过滤器、滤波屏蔽器配
- 下一篇: stm32之spi之NSS管脚信号