Answer the question
In order to leave comments, you need to log in
STM32F103 SPI Slave How to get out of interrupt?
in main.c there is an infinite loop where sensors are constantly polled, controlled by LEDs, and so on. And when the SPI acceptance interrupt is triggered, after reading all the bytes, control does not return and the endless loop does not resume (the LEDs do not blink, but are in the last state before the interrupt, the print does not print). I have a data packet of 32 bytes, while in the interrupt itself all 32 bytes are read.
If you remove while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); in the SPI_RW () function, then the infinite loop works, but each byte is read many times (sometimes too many) - that is, there is a problem either with this loop or with the SPI interrupt priority, I tried to set it to 7 - the same.
I put together a test bench with a minimum of code where this problem is reproduced
// SPI.c
#include "SPI.h"
#include "stdio.h"
#include "stm32f10x.h"
void SPI_Init(void) {
GPIO_InitTypeDef GPIO_InitDef;
SPI_InitTypeDef SPI_InitDef;
NVIC_InitTypeDef NVIC_InitStructure;
// initialize init structs
GPIO_StructInit(&GPIO_InitDef);
SPI_StructInit(&SPI_InitDef);
// initialize clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
// initialize A4/SS A5/SCK A7/MOSI alternate function open-drain (50 MHz)
GPIO_InitDef.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitDef.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitDef.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitDef);
// initialize A6/MISO alternate function push-pull (50 MHz)
GPIO_InitDef.GPIO_Pin = GPIO_Pin_6;
GPIO_InitDef.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitDef.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitDef);
// initialize SPI slave
// for slave, no need to define SPI_BaudRatePrescaler
SPI_InitDef.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitDef.SPI_Mode = SPI_Mode_Slave;
SPI_InitDef.SPI_DataSize = SPI_DataSize_8b; // 8-bit transactions
SPI_InitDef.SPI_FirstBit = SPI_FirstBit_MSB; // MSB first
SPI_InitDef.SPI_CPOL = SPI_CPOL_Low; // CPOL = 0, clock idle low
SPI_InitDef.SPI_CPHA = SPI_CPHA_2Edge; // CPHA = 2
SPI_InitDef.SPI_NSS = SPI_NSS_Soft; // use hardware SS
SPI_InitDef.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // APB2 72/64 = 1.125 MHz
SPI_InitDef.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitDef);
SPI_Cmd(SPI1, ENABLE);
NVIC_EnableIRQ(SPI1_IRQn);
//Enable SPI's IRQ
SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);
printf("SPI bus init success...\r\n");
}
void SPI_RW() {
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_IT_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI1);
}
// main.c
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_spi.h"
#include "SPI.h"
#ifdef OS_USE_SEMIHOSTING
extern void initialise_monitor_handles(void);
#endif
static void SysTickConfig(void) {
/* Setup SysTick Timer for 10ms interrupts */
if (SysTick_Config(SystemCoreClock / 1000))
{
/* Capture error */
while (1);
}
/* Configure the SysTick handler priority */
NVIC_SetPriority(SysTick_IRQn, 1); // if I change Priority to 0 then I can't catch SPI' interruption
}
uint8_t RX_LEN = 32;
uint8_t RX_BUF[RX_LEN] = {0};
void print_buf(uint8_t len) {
for (uint8_t i=0; i<len; i++) {
printf("0x%02x \r\n", RX_BUF[i]);
}
printf("\r\n");
}
void SPI1_IRQn(void) {
for (uint8_t i=0; i<RX_LEN; i++) {
RX_BUF[i] = SPI_RW();
}
print_buf(RX_LEN);
}
void main() {
/* Enable semihosting */
#ifdef OS_USE_SEMIHOSTING
initialise_monitor_handles();
#endif
/* SysTickConfig */
SysTickConfig();
SPI_Init();
while(1) {
printf("hello\r\n");
}
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question