Electronic – Problem initializing SPI TX interrupt in STM32F103

interruptsspistm32

I am trying to establish SPI communication from master to slave. I am able to send bytes over to slave, and is now trying to send when the TX interrupt is triggered.

Below is code I used for master side, on STM32F103;

void spi_init() {
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    SPI_I2S_DeInit(SPI2);
    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_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 
    SPI_Init(SPI2, &SPI_InitStructure);
    SPI_Cmd(SPI2, ENABLE);
    SPI_CalculateCRC(SPI2, DISABLE);
    SPI_SSOutputCmd(SPI2, DISABLE);

    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
}

void SPI2_IRQHandler(void) {
    if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_TXE) == SET) {
        //Send from buffer
        SPI_I2S_ClearITPendingBit(SPI2, SPI_I2S_IT_TXE);
    }

    if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET) {
        //Receive
        SPI_I2S_ClearITPendingBit(SPI2, SPI_I2S_IT_RXNE);
    }
}

The problem is that the program always crashes within the spi_init() function. When I comment out either the NVIC_Init command and the SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE) command, it will not crash. But it will just not work with the two together.

Any help on what is causing the problem is appreciated.

Best Answer

You're getting stuck in your interrupt handler because you're trying to clear the TXE flag 'manually' and this doesn't work.

The TXE flag is there to tell you that the SPI module is ready for you to load another byte into its transmit register - and the act of loading this byte is what clears the TXE flag.

If you don't have any more data to send, you must disable this interrupt until such time as you do want to send more data.