SPI slave

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

SPI slave

Сообщение balmer »

Потребовалось мне сделать общение между двумя STM32 процессорами. И вот оказалось, что slave режим никогда не делал. Быстренько по туториалам его замутил. Подключил STM32 друг к другу длинными проводами без резисторов. Естественно оказалось, что передача сбоит. Конечно быстро переделал все как надо, но осадочек остался :)

Соотвественно вопрос - как бы сделать надежную передачу/прием? Причем интересует надежность такого плана - проскочил по SCK лишний сигнал. Все последующие байты стали передаваться со сдвигом в один бит.

Собственно говоря даже понятно как от этого защищаться. В тех-же дисплеях с SPI входом команда начинается гарантированно когда CS переключается 1->0. Теоретически можно прерывание EXTI_XXX_IRQHandler повесить на CS пин в slave и там указывать "началась новая команда". Но может есть более стандартный путь?
halisi
Родился
Сообщения: 19
Зарегистрирован: Пн мар 11, 2013 01:46:59

Re: SPI slave

Сообщение halisi »

а не могли бы выложить код для Slave.Самому вот вот писать)
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: SPI slave

Сообщение balmer »

Впринципе такого кода вагон и маленькая тележка в интернете, но вот.
Код для STM32F4xxx. Пин CS не используется, предполагается, что один мастер общается с одним slave. GPIO_Speed_2MHz - из-за длинных проводов.
Спойлер

Код: Выделить всё

/*
   SPI2_SCK             - PB13 34 *
   SPI2_MISO            - PB14 35 *
   SPI2_MOSI            - PB15 36 *
*/

void SpiInit()
{
   GPIO_InitTypeDef GPIO_InitStructure;
   SPI_InitTypeDef SPI_InitStructure;
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOB, &GPIO_InitStructure);

   GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI2);
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);
   
   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
   SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
   SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
   SPI_InitStructure.SPI_CRCPolynomial = 15;
   SPI_Init(SPI2, &SPI_InitStructure);

   SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE,ENABLE);
   SPI_Cmd(SPI2, ENABLE);
   NVIC_EnableIRQ(SPI2_IRQn);

   SPI2->DR = 0x4000;
}


void SPI2_IRQHandler()
{
   if (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==SET) {
      volatile uint16_t data = SPI2->DR; //Читаем то что пришло

      SPI2->DR = data; //Отправляем обратно
   }
}
halisi
Родился
Сообщения: 19
Зарегистрирован: Пн мар 11, 2013 01:46:59

Re: SPI slave

Сообщение halisi »

Спасибо
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: SPI slave

Сообщение balmer »

Вчера, когда продумывал протокол - наткнулся на еще одну тонкость.
Хочется такого типа протокол:
Master запрашивает у Slave данные.
Slave обрабатывает запрос. (длительное время, например 100 мкс)
Slave отсылает ответ на Master.

А возможности сказать мастеру, что данные таки обработаны нет. Либо мастер должен периодически запрашивать "Готовы ли данные". Либо надо еще одну сигнальную линию "Data Ready".

Так, что даже в такой простой вещи как SPI можно не предусмотреть все заранее :)
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: SPI slave

Сообщение dosikus »

Ну дык есть же девайсы для примера , используют пины IRQ .
nRF24xxx , тачи ...
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: SPI slave

Сообщение balmer »

Не спорю. У меня самого есть микросхемы акселерометра и барометра которые похожим способом действуют. Но пока не начнешь программировать, не задумываешься, что к чему. Хорошо, что есть проводок для CS пина, который можно для этих целей приспособить.

Кстати фикс для забытых резисторов на SPI линии :music: .
Изображение
alexf58
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Сб фев 09, 2013 23:00:23

Re: SPI slave

Сообщение alexf58 »

balmer писал(а):А возможности сказать мастеру, что данные таки обработаны нет. Либо мастер должен периодически запрашивать "Готовы ли данные". Либо надо еще одну сигнальную линию "Data Ready".



Наверное я не понял проблемы, но мне представляется что возможно простое решение. Линия MISO должна стать флагом готовности.
По SPI послали команду и перевели ножку где было MISO на GPIO вход с прерыванием по изменению уровня. Slave когда готов, дергает за эту ногу и ждет дальнейших инструкций.
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: SPI slave

Сообщение balmer »

Спасибо, до такого варианта экономии линии не додумался.
Ответить

Вернуться в «ARM»