реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> SPI на STM32F0
Влад Р.
сообщение Oct 2 2012, 16:49
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511



Всем доброго времени суток!

Пытаюсь настроить модуль SPI на STM32F0 для работы в режиме передачи мастером (полудуплекс): BIDIMODE=1 и BIDIOE=1. Данный режим в теории должен задействовать только один пин данных - MOSI. Также пытаюсь включить аппартное управление пином NSS для выбора единственного ведомого. В итоге нормальная передача не происходит, а пин NSS вообще в 1. Помогите разобраться где накосячил. Вот код функций:
Код
void SPI_Init(void)
{
  /* Включаем на выводах SPI - NSS, SCK и MOSI - режим альтернативной функции */
  GPIOA->MODER &= ~(GPIO_MODER_MODER4 | GPIO_MODER_MODER5 | GPIO_MODER_MODER7);
  GPIOA->MODER |= GPIO_MODER_MODER4_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER7_1;
  GPIOA->AFR[0] &= ~(GPIO_AFRL_AFRL4 | GPIO_AFRL_AFRL5 | GPIO_AFRL_AFRL7);

  /* Тактируем модуль SPI */
  RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
  
  /* Конфигурируем SPI */
  SPI1->CR1 |= SPI_CR1_BR;                                    // задаем частоту обмена
  SPI1->CR1 |= SPI_CR1_CPOL | SPI_CR1_CPHA;                   // задаем режим работы SPI (полярность и фазу)
  SPI1->CR1 |= SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE;             // задаем режим передачи
  SPI1->CR2 |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2;    // задаем формат данных (разрядность)
  SPI1->CR1 &= ~SPI_CR1_LSBFIRST;                             // задаем способ передачи (формат фрейма)
  SPI1->CR1 &= ~SPI_CR1_SSM;                                  // задаем режим управления NSS (аппаратное или программное)
  SPI1->CR2 |= SPI_CR2_SSOE;                                  // задаем режим внешнего вывода NSS
  SPI1->CR1 |= SPI_CR1_MSTR;                                  // задаем режим работы модуля SPI (ведущий или ведомый)
  SPI1->CR1 |= SPI_CR1_SPE;                                   // включаем модуль SPI
}

void SPI_Transfer(uint8_t data)
{
  /* Помещаем данные на передачу */
  SPI1->DR = data;
  
  /* Ждем окончания передачи */
  while (!(SPI1->SR & SPI_SR_TXE));
  while (SPI1->SR & SPI_SR_BSY);
}


З.Ы. Само собой порт A предварительно тактирован.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Oct 2 2012, 21:09
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Там надо управлять ещё битами SSM и SSI.
Легко видно в отладчике. Иначе мастер автоматом сбрасывается.
Сейчас скинуть не могу - на работе исходники. Поковыряйтесь - сами разберётесь. Я работал с stm32f407. Думаю там аналогично. Хотя и в NXP тоже что-то подобное было ...
Go to the top of the page
 
+Quote Post
Влад Р.
сообщение Oct 2 2012, 21:52
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511



Во-первых, лоханулся с NSS - он отрабатывает нормально, просто я не туда ткнул щупом. Данные передаю на дисплей от Nokia 3310. Я поменял полярность и фазу синхронизации:
Код
SPI1->CR1 |= SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE;             // задаем режим передачи

Передача теперь идет, но с диким косяком - после передачи каждого столбца (1 байта) на дисплей передается еще один пустой. В отладке вызова функций передачи пустых байтов я не увидел. Такое впечатление, что котроллер передает не 1 байт, а сразу 2. В результате на дисплейе - растянутая картинка с пробелами на каждом втором столбике. Странно, вообщем, ведь я задал разрядность 8 бит:
Код
SPI1->CR2 |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2;    // задаем формат данных (разрядность)

Из-за чего может такое происходить?

SasaVitebsk, спасибо, что откликнулись!

Цитата(SasaVitebsk @ Oct 3 2012, 00:09) *
Там надо управлять ещё битами SSM и SSI.
Иначе мастер автоматом сбрасывается.


SSM управляю - я его отключаю))) Почему? Это нужно, чтобы аппартно подавать NSS (при условии одного ведомого) на соответсвующий пин установкой бита SSOE.
А если SSM отключен, то и SSI управлять не нужно, по крайней мере так говорит мануал:
Цитата
Bit 8 SSI: Internal slave select
This bit has an effect only when the SSM bit is set.
Go to the top of the page
 
+Quote Post
Влад Р.
сообщение Oct 3 2012, 18:24
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511



Пробовал играть с битами DS[3:0] в регистре SPI1_CR2, чтобы управлять разрядностью передаваемых данных, - визуально результат не меняется. Такое впечатление, что эти биты вообще игнорируются и МК устанавливает разрядность в 16 бит. Чувствую где-то накосячил, но где не пониманию(((

Хм... наткнулся на такую же проблему (последний комментарий): http://hackaday.com/2012/05/30/video-revie...iscovery-board/
К сожалению без решения((( Я в отчаянии!(((

Сообщение отредактировал Влад Р. - Oct 3 2012, 20:33
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Oct 4 2012, 05:55
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Насколько я понял из чтения различных форумов, аппаратный NSS не работает. Дёргайте его программно, и ваше отчаянье пройдётsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Влад Р.
сообщение Oct 4 2012, 17:59
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511



Цитата(AHTOXA @ Oct 4 2012, 08:55) *
Насколько я понял из чтения различных форумов, аппаратный NSS не работает. Дёргайте его программно, и ваше отчаянье пройдётsm.gif


AHTOXA, спасибо за участие в обсуждении!
Тоже попадались такие заметки об аппаратном NSS, но я думаю это имеет отношение только к более ранней серии STM32F1, в STM32F0 с аппаратным NSS проблем я не заметил. Но все равно переписал под программное дергание CS на дисплейе - проблема не решилась. На всякий случай попробовал и режим transmit-only (BIDIMODE=0 RXONLY=0), который также используется для полнодуплексного обмена, если задействован пин MISO. Это тоже не дало результата. Проблема осталась: длина фрейма всегда остается равной 16 бит. Кто еще может протестировать SPI на STM32F0, желательно с использованием осциллографа???
Go to the top of the page
 
+Quote Post
Влад Р.
сообщение Oct 5 2012, 21:59
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511



Проверил тот же код с небольшими изменениями (из-за различия в структуре регистров) на STM32F1 (на STM32VLDISCOVERY). Все заработало, даже аппаратное управление NSS. А вот результат работы на STM32F0 как если бы при работе с STM32F1 устанавливать бит SPI_CR1_DFF. Т.е. STM32F0 упорно не хочет менять размер фрейма. Кто-нибудь может подкинуть код для STM32F0, который заставит работать SPI с 8-битными фреймами?
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Oct 19 2012, 13:07
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



Код
#define SPI1_DR_8b          (*(__IO uint8_t *)((uint32_t)SPI1 + 0x0C))
#define SPI2_DR_8b          (*(__IO uint8_t *)((uint32_t)SPI2 + 0x0C))

Дальше как обычно...

Код
SPI1_DR_8b = 0xFF;





Цитата(AHTOXA @ Oct 4 2012, 08:55) *
Насколько я понял из чтения различных форумов, аппаратный NSS не работает. Дёргайте его программно, и ваше отчаянье пройдёт sm.gif

В STM32F0 работает...
Go to the top of the page
 
+Quote Post
Влад Р.
сообщение Oct 20 2012, 19:16
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511



Цитата(HHIMERA @ Oct 19 2012, 16:07) *
Код
#define SPI1_DR_8b          (*(__IO uint8_t *)((uint32_t)SPI1 + 0x0C))
#define SPI2_DR_8b          (*(__IO uint8_t *)((uint32_t)SPI2 + 0x0C))

Дальше как обычно...

Код
SPI1_DR_8b = 0xFF;


Спасибо, помогло)))
Видимо где-то с преобразованием типов напортачил...
Go to the top of the page
 
+Quote Post
rvark85
сообщение Nov 18 2013, 14:13
Сообщение #10





Группа: Новичок
Сообщений: 1
Регистрация: 18-11-13
Пользователь №: 79 245



Заработало, но не пойму как и как. Обьясните пожалуйста как работает эта связка?

Код
#define SPI1_DR_8b          (*(__IO uint8_t *)((uint32_t)SPI1 + 0x0C))
#define SPI2_DR_8b          (*(__IO uint8_t *)((uint32_t)SPI2 + 0x0C))
и
Код
SPI1_DR_8b = 0xFF;
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 05:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.01458 секунд с 7
ELECTRONIX ©2004-2016