解決STM 32 SPI半障害NSSが引き上げられない
4783 ワード
周知のように、STM 32 SPIは半障害者でNSSは自動的に引き上げることができないので、SPIを使ってチャンスからずっと使えるようになり、ホストが1対多の場合、SPIスレーブが互いに干渉する問題が発生します.
私はGPIO割り込みを利用して、NSSピンの代わりに、使用過程は以下のコードで示しています.
1.SPIの初期化 のIOポートは、NSSのピンが先ではありません.
2.SPIを再初期化し、初期化方式はスレーブサブモードで、このときSPIを使用しないでください.
3.NSSピンをGPIO割込みに配置する.ここでNSSピンはPA 15である.配置過程は以下のコードである.
4.GPIO割込みサービス関数を書き、この関数の主な仕事はNSSピンのレベルを判断し、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ピンは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();
}
}