@Klaxons

STM32F103 SPI Slave Как выйти из прерывания?

в main.c есть бесконечный цикл, где постоянно опрашиваются датчики, управляется светодиодами и тд. И вот когда срабатывает прерывание на приемку SPI, после чтения всех байтов - управление не возвращается и бесконечный цикл не возобновляется (светодиоды не мигают а находятся в последнем состоянии перед прерывание, принт не печатает). Пакет данным у меня 32 байта, при этом в самом прерывании все 32 байта считываются.

Если убрать while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); в ф-ции SPI_RW(), то бесконечный цикл работает, но каждый байт считывается по много раз (иногда слишком много) - то есть проблема либо с этим циклом, либо с приоритетом прерывания у SPI, пробовал ему 7 выставлять - то же самое.

Я собрал тестовый стенд с минимум кода, где эта проблема воспроизводится
// 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");
}
}


Помогите разобраться и пофиксить этот баг
  • Вопрос задан
  • 414 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы