Переполнение в прерывании ведомого устройства ST32 HAL SPI

У меня проблема с ST32F030 и Slave SPI

Я пытаюсь заставить его ответить на команду spi: -

Мастер отправляет 0x05, подчиненный отвечает массивом из 7 байтов. Это вроде работает в первый раз, но затем теряется синхронизация и устанавливается бит OVR. Я не могу понять почему.

Вот код: -

int main(void)
{
   HAL_Init();
   /* Configure the system clock */
   SystemClock_Config();
   /* Initialize all configured peripherals */
   MX_SPI1_Init();
   spi_init();

   while (1)
   {
      HAL_SPI_Receive_IT(&hspi1, &spiData[0], 1);
   }
}

/* SPI1 init function */
static void MX_SPI1_Init(void)
{
   hspi1.Instance = SPI1;
   hspi1.Init.Mode = SPI_MODE_SLAVE;
   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
   hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
   hspi1.Init.NSS = SPI_NSS_SOFT;
   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
   hspi1.Init.CRCPolynomial = 7;
   hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
   hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
   /* SPi priority interrupt configuration */
   HAL_NVIC_SetPriority(SPI1_IRQn, 1, 1);
   if (HAL_SPI_Init(&hspi1) != HAL_OK)
   {
      Error_Handler();
   }
}


void spi_init()
{
      HAL_SPI_Receive_IT(&hspi1, spiData, 1);
}

void SPI1_IRQHandler(void)
{
   HAL_SPI_IRQHandler(&hspi1);
}

uint8_t spiData[8];
uint8_t edgesmsg[7];

void spi_interrupt()
{
   uint8_t c;

   c = spiData[0];
   if ( c == 0x05)
      HAL_SPI_Transmit(&hspi1, edgesmsg, 7, 1000);
}

Любые предложения с благодарностью получены


person OXO    schedule 28.08.2017    source источник
comment
Не могли бы вы также предоставить spi_init().   -  person Guillaume Michel    schedule 29.08.2017
comment
spi_init добавлен, но он немного избыточен   -  person OXO    schedule 30.08.2017


Ответы (1)


Ваша проблема в том, что вы все время пытаетесь читать из SPI, не завершая предыдущую операцию, поэтому вы получаете переполнение (бит OVR). Постарайтесь лучше упорядочить вещи.

Например, удалите HAL_SPI_Receive_IT(&hspi1, &spiData[0], 1); из основного цикла и вместо этого вызовите его в обработчике прерывания. Код должен быть:

int main(void)
{
   HAL_Init();
   /* Configure the system clock */
   SystemClock_Config();
   /* Initialize all configured peripherals */
   MX_SPI1_Init();
   spi_init();

   while (1)
   {
      //Do not call HAL_SPI_Receive_IT here
      //HAL_SPI_Receive_IT(&hspi1, &spiData[0], 1);
   }
}



void spi_interrupt()
{
   uint8_t c;

   c = spiData[0];
   if ( c == 0x05)
   {
       HAL_SPI_Transmit(&hspi1, edgesmsg, 7, 1000);
   }

   //Re-enable interrupt to read next sequence
   HAL_SPI_Receive_IT(&hspi1, &spiData[0], 1);
}

Это принцип. Вы снова включаете прерывание после обработки своего пакета. Однако я не уверен, каковы ваши намерения, и вам может потребоваться адаптировать приведенный выше код.

Также обратите внимание, что любой обработчик прерывания должен быть максимально быстрым. Поэтому на самом деле неприемлемо вызывать HAL_SPI_Transmit (функцию опроса) в обработчике прерывания spi_interrupt. Вы должны либо вызвать HAL_SPI_Transmit_IT, либо вообще не использовать прерывание. В первом случае снова остерегайтесь секвенирования.

person Guillaume Michel    schedule 30.08.2017
comment
Спасибо. Поскольку это ведомое устройство, оно должно очень быстро отвечать на полученный опрос, в противном случае ведущее устройство выполнит синхронизацию, а ведомое устройство не загрузит значения. Все это довольно сбивает с толку, и этому не способствует отсутствие документации для HAL. - person OXO; 30.08.2017
comment
OK. Имеет смысл. Я не понял, что это был раб. HAL довольно хорошо документирован в STM32CubeF0. Особенно инструкция по эксплуатации UM1785. - person Guillaume Michel; 30.08.2017