解決STM 32 SPI半障害NSSが引き上げられない

4783 ワード

周知のように、STM 32 SPIは半障害者でNSSは自動的に引き上げることができないので、SPIを使ってチャンスからずっと使えるようになり、ホストが1対多の場合、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ピンはPA 15である.配置過程は以下のコードである.
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();
	}
}