解决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)