Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.79/28: Рейтинг темы: голосов - 28, средняя оценка - 4.79
sdo
1

Вопрос по инициализации SPI

24.11.2015, 18:37. Показов 5641. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени!

Уже пару дней пытаюсь заставить работать SPI на STM32F030 и как то все безрезультатьно.
Конечная цель - подцепить 595 микросхемку и поуправлять уже ей.

#include "stm32f0xx.h"

int main (void)
{
//SPI1 GPIO Port Init <> PA4, PA5, PA7 as AF, Output Push_Pull, HSpeed 50MHz,
RCC -> AHBENR |= RCC_AHBENR_GPIOAEN; // GPIO Periph clock enable
GPIOA -> MODER &= ~(GPIO_MODER_MODER4 | GPIO_MODER_MODER5 | GPIO_MODER_MODER7); //Clear mode bit for SPI
GPIOA -> MODER |= (GPIO_MODER_MODER4_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER7_1); //Confikure PA4, PA5, PA6 Ottirnate Mode
GPIOA -> OTYPER &= ~(GPIO_OTYPER_OT_4 | GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_7); // Ensure push pull mode selected--default
GPIOA -> OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR4 | GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR7); // Ensure maximum speed setting (even though it is unnecessary)
GPIOA -> AFR[0] |= (GPIO_AFRL_AFRL4 | GPIO_AFRL_AFRL5 | GPIO_AFRL_AFRL7); //Confikure PA4, PA5, PA6 as Ottirnate Functions AFR[0]=AFRL

//SPI1 Config
RCC -> APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI Periph clock enable
SPI1 -> CR1 = 0x00; //Clear CR1
SPI1 -> CR1 &= ~(SPI_CR1_BR); // Freq dividid by 2
SPI1 -> CR1 |= (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE); //bidirectional mode, only transmit
SPI1 -> CR1 |= (SPI_CR1_MSTR); // Master Mode
SPI1 -> CR1 |= (SPI_CR1_CPOL); //CK 1 when idle
SPI1 -> CR1 |= (SPI_CR1_CPHA); //Strobi by second edge
SPI1 -> CR1 |= (SPI_CR1_SSM); //
SPI1 -> CR1 |= (SPI_CR1_SSI); //
SPI1 -> CR2 |= (SPI_CR2_DS); // 16 bit length
SPI1 -> CR2 |= (SPI_CR2_SSOE);
SPI1 -> CR1 |= (SPI_CR1_SPE); //SPI enable

while (1)
{
SPI1 -> DR = 0x01;
__asm {NOP}
}

}

Можете подсказать, где у меня грубая ошибка...?
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.11.2015, 18:37
Ответы с готовыми решениями:

Вопрос по spi
Заметил, при работе с spi, что при передаче байта по spi, ответ генерируется в любом случае. То...

SPI DMA вопрос
читаю даташит. Там в таблице каналов дма STEAM5 и STEAM7 это SPI3_TX. Могу ли я отправлять буфер...

Вопрос по SPI (а может и по C в Keil)
Есть вот такая функция чтения данных с флэш-памяти: void FL_ReadData (uint32_t Address, uint32_t...

ILI9341 SPI DMA, SPI, UART библиотеки
Доброго времени, форумчане... Посоветуйте библиотек плиз... 0) Либа для работы с контроллером по...

16
0 / 0 / 0
Регистрация: 18.08.2014
Сообщений: 50
24.11.2015, 20:12 2
Я с данной серией процов не работал , но думаю ошибка где то тут GPIO_AFRL_AFRL4
0
0 / 0 / 0
Регистрация: 13.01.2013
Сообщений: 140
24.11.2015, 23:51 3
Самое первое, afr не правильно программируется, там по 4 бита на пин.
С регистром CR1 тоже причуды, сначала очистка, потом ещё сброс битов, видимо мусор от отладки.
У меня на f050 SPI через DMA пашет, как положено, если найду, выхожу код.
UPD:
Смотрим, чему равен, например, #define GPIO_AFRL_AFR4 ((uint32_t)0x000F0000)
Эта константа для сброса, а не для установки. Установка номера альтернативного режима в примерах от ST примерно так:
Код
   GPIOA->AFR[1] |= (1 << ((9 - 8) * 4)) | (1 << ((10 - 8) * 4));   // AFR1 для пинов 9 и 10 (по 4 бита на один пин)
Вот код для STM32F050F4P6, хотя он порезан, но может чем то поможет. Здесь используется только циклический вывод в SPI1 из буфера с помощью DMA_Channel3:
Код
volatile uint8_t Buffer[BUF_LEN];

void SPI_init()
{
/* Включаем тактирование PA */
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;

/* Push-pull для PA4, PA5 & PA7 */
/* No pull-up & pull-down для PA4, PA5 & PA7 */

/* Установка максимальной скорости пинов PA4 (SPI1_NSS), PA5 (SPI1_SCK), PA7 (SPI1_MOSI) */
GPIOA->OSPEEDR |=   GPIO_OSPEEDER_OSPEEDR4_1 | GPIO_OSPEEDER_OSPEEDR4_0 |
GPIO_OSPEEDER_OSPEEDR5_1 | GPIO_OSPEEDER_OSPEEDR5_0 |
GPIO_OSPEEDER_OSPEEDR7_1 | GPIO_OSPEEDER_OSPEEDR7_0;

/* Установка альтернативного режима для PA4, PA5 & PA7 */
GPIOA->MODER |=   GPIO_MODER_MODER4_1 |
GPIO_MODER_MODER5_1 |
GPIO_MODER_MODER7_1;

/* Включаем тактирование SPI1 */
RCC->APB2ENR |=   RCC_APB2ENR_SPI1EN;

/* Старший бит вперед */
SPI1->CR1 |=   SPI_CR1_MSTR |               /* Мастер */
//               SPI_CR1_BR_2 | SPI_CR1_BR_0;   /* BaudRate = Fpclk / 64 => 0b101 */
SPI_CR1_BR_1 | SPI_CR1_BR_0;   /* BaudRate = Fpclk / 16 => 0b011 */

/* Стр. 792 */
SPI1->CR2 |=   SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0 |   /* Размер данных 8 бит = 0b0111 */
SPI_CR2_TXDMAEN |                        /* DMA на передачу */
SPI_CR2_SSOE;
}

void DMA_init()
{
/* Включаем тактирование DMA1 */
RCC->AHBENR |= RCC_AHBENR_DMA1EN;

/* Запись в SPI1 */
DMA1_Channel3->CPOR = (uint32_t)(&(SPI1->DR));
/* Вывод из буфера */
DMA1_Channel3->CMAR = (uint32_t)Buffer;
/* Длина пересылки, не более 16 бит */
DMA1_Channel3->CNDTR = (uint16_t)(sizeof(Buffer));

/* SPI - 8 bit, MEM - 8 bit */
DMA1_Channel3->CCR |=   DMA_CCR_CIRC |               /* Циклическая передача */
DMA_CCR_PL_1 | DMA_CCR_PL_0 |   /* Very high priority */
DMA_CCR_DIR |               /* Read from Memory */
DMA_CCR_MINC;               /* Increment memory */
}

void DMA_stort()
{
DMA1_Channel3->CCR |=   DMA_CCR_EN;
}

void SPI_stort()
{
SPI1->CR1 |=   SPI_CR1_SPE;
}

int main()
{
/* Инициализируем буфер DMA */
DMABuffer_init();

DMA_init();
SPI_init();

SPI_stort();
DMA_stort();

while(1)
{
}
}
Для разборок помогают snippets примеры от ST, я туда заглядываю, когда что то не так.
Ссылка: https://my.st.com/st-extranet-... s/PF260157 : Example Code snippets covering STM32 F0 serie
0
sdo
25.11.2015, 11:55 4
Выходит, что для SPI, да и исходя из твоего примера так же, будет:
GPIOA->AFR[0] |= (0<<(4*4)) | (0<<(4*5)) | (0<<(4*7));
Что, как понимаю, равнозначно вообще отсутствию этой записи?

Спасибо за ссылку на snippets!

UPD:
Текущее состояние:
#include "stm32f0xx.h"

int main (void)
{
//SPI1 GPIO Port Init -> PA4, PA5, PA7 as AF, Output Push_Pull, HSpeed 50MHz,
RCC -> AHBENR |= RCC_AHBENR_GPIOAEN; // GPIO Periph clock enable
GPIOA -> MODER |= (GPIO_MODER_MODER4_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER7_1); //Confikure PA4, PA5, PA6 Ottirnate Mode
GPIOA -> OTYPER &= ~(GPIO_OTYPER_OT_4 | GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_7); // Ensure push pull mode selected--default
GPIOA -> OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR4 | GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR7); // Ensure maximum speed setting (even though it is unnecessary)
//GPIOA->AFR[0] |= (0<<(4*4)) | (0<<(4*5)) | (0<<(4*7)); //Confikure PA4, PA5, PA6 as Ottirnate Functions AFR[0]=AFRL

//SPI1 Config
RCC -> APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI Periph clock enable
SPI1 -> CR1 |= (SPI_CR1_MSTR); // Master Mode
SPI1 -> CR1 &= ~(SPI_CR1_BR); // Freq dividid by 2
SPI1 -> CR1 |= (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE); //bidirectional mode, only transmit
//SPI1 -> CR1 |= (SPI_CR1_CPOL); //CK 1 when idle
//SPI1 -> CR1 |= (SPI_CR1_CPHA); //Strobi by second edge
SPI1 -> CR1 |= (SPI_CR1_SSM); //
SPI1 -> CR1 |= (SPI_CR1_SSI); //
SPI1 -> CR2 |= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0); // 8 bit length
SPI1 -> CR2 |= (SPI_CR2_SSOE); //NSS as output
SPI1 -> CR1 |= (SPI_CR1_SPE); //SPI enable

while (1)
{
SPI1 -> DR = 0x01;
__asm {NOP}
}
}

SPI завелся.
0 / 0 / 0
Регистрация: 11.10.2015
Сообщений: 117
25.11.2015, 14:36 5
Цитата Сообщение от sdo
Выходит, что для SPI, да и исходя из твоего примера так же, будет:
GPIOA->AFR[0] |= (0<<(4*4)) | (0<<(4*5)) | (0<<(4*7));
Что, как понимаю, равнозначно вообще отсутствию этой записи?

Спасибо за ссылку на snippets!

UPD:
Текущее состояние:
#include "stm32f0xx.h"

int main (void)
{
//SPI1 GPIO Port Init -> PA4, PA5, PA7 as AF, Output Push_Pull, HSpeed 50MHz,
RCC -> AHBENR |= RCC_AHBENR_GPIOAEN; // GPIO Periph clock enable
GPIOA -> MODER |= (GPIO_MODER_MODER4_1 | GPIO_MODER_MODER5_1 | GPIO_MODER_MODER7_1); //Confikure PA4, PA5, PA6 Ottirnate Mode
GPIOA -> OTYPER &= ~(GPIO_OTYPER_OT_4 | GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_7); // Ensure push pull mode selected--default
GPIOA -> OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR4 | GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR7); // Ensure maximum speed setting (even though it is unnecessary)
//GPIOA->AFR[0] |= (0<<(4*4)) | (0<<(4*5)) | (0<<(4*7)); //Confikure PA4, PA5, PA6 as Ottirnate Functions AFR[0]=AFRL

//SPI1 Config
RCC -> APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI Periph clock enable
SPI1 -> CR1 |= (SPI_CR1_MSTR); // Master Mode
SPI1 -> CR1 &= ~(SPI_CR1_BR); // Freq dividid by 2
SPI1 -> CR1 |= (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE); //bidirectional mode, only transmit
//SPI1 -> CR1 |= (SPI_CR1_CPOL); //CK 1 when idle
//SPI1 -> CR1 |= (SPI_CR1_CPHA); //Strobi by second edge
SPI1 -> CR1 |= (SPI_CR1_SSM); //
SPI1 -> CR1 |= (SPI_CR1_SSI); //
SPI1 -> CR2 |= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0); // 8 bit length
SPI1 -> CR2 |= (SPI_CR2_SSOE); //NSS as output
SPI1 -> CR1 |= (SPI_CR1_SPE); //SPI enable

while (1)
{
SPI1 -> DR = 0x01;
__asm {NOP}
}
}

SPI завелся.
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
25.11.2015, 14:41 6
я с F0 серией не работал, но разве там SPL нет? Или напрямую с регистрами принципиально? На крайний случай там можно подсмотреть пример рабочего кода.
0
0 / 0 / 0
Регистрация: 13.01.2013
Сообщений: 140
25.11.2015, 17:41 7
Цитата Сообщение от sdo
Выходит, что для SPI, да и исходя из твоего примера так же, будет:
GPIOA->AFR[0] |= (0<<(4*4)) | (0<<(4*5)) | (0<<(4*7));
Что, как понимаю, равнозначно вообще отсутствию этой записи?
Да, так и есть. У тебя раньше устанавливались все 4 бита, а это, если не ошибаюсь, запрещенная комбинация или несуществующая. Потому и не работало.

snippets, да, я там смотрю, разбираюсь, а потом использую. Я вообще сначала зашел на сайт, посмотрел все материалы на свой камень, выкачал то, что нужно и не нужно, в первую очередь 00091 RM, софт, опять же.

По поводу SPL & CUBE: Я как то куб посмотрел (SPL раньше видел), в баню, предпочитаю весь этот hitt не использовать, если что то не так, то и не поймешь, почему не работает, а ковыряться в их исходниках еще то удовольствие. Короче, каждому своё, мне проще ДШ и примеры, а потом ваять.
0
Oxford
25.11.2015, 17:51 8
SPL используйте.
sdo
25.11.2015, 18:16 9
SPL немного пользовал, как и Cube. Слишком много лишнего. И далеко не всегда понимаешь как что происходит и где ошибка.
К тому же все равно приходится лезть в RM и перекапываешь содержание регистров в конце концов. В общем раза в 2 больше работы выходит на одну и ту же задачу. Но это так же - мое мнение.
kysoft, так что поддерживаю, много лучше один раз разобраться и понимать что как и зачем делаешь.
Oxford
25.11.2015, 19:17 10
Я на этом МК запускал CoOS, кучу периферии, дисплей графический со шрифтами и все это с SPL.
И при этом в RM не залез ни разу и работало все с первого раза. Как вы программируете вообще не понятно. SPI и то не можете запустить и прогаете без библиотеки и читаете RM.
1 / 1 / 0
Регистрация: 14.02.2013
Сообщений: 408
25.11.2015, 20:30 11
C SPL ничего не работает, без SPL - всё! SPL - зло!
1
Oxford
25.11.2015, 20:41 12
SPL forever!!! Без SPL тьма.
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
25.11.2015, 21:13 13
С SPL порой проще найти ошибку. Не все наизусть помнят регистры, биты, маски и прочее. А SPL везде одно и то же.
0
sdo
03.12.2015, 14:13 14
Снова в продолжение этого вопроса.
SPL хорошо, все остальное зло, знаю. Но вопрос на другую тему.

Пытаюсь прописать прерывание по окончанию передачи данных. Как итог - программа просто не выходит из прерывания. Причем входит в него даже если в цикле в main ничего нет.
Плюс почему то не сбрасывается бит TXE.

В чем может быть проблема?

Код
//SPI1 Config
RCC -> APB2ENR |= RCC_APB2ENR_SPI1EN;                                             // SPI Periph clock enable
SPI1 -> CR1 |= (SPI_CR1_MSTR);                                                      // Master Mode
SPI1 -> CR1 |= (SPI_CR1_BR);                                                          // Freq dividid by 256
SPI1 -> CR1 |= (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE);                        // bidirectional mode, only transmit
SPI1 -> CR2 |= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0);          // 8 bit length
SPI1 -> CR2 |= (SPI_CR2_SSOE);                                                      // NSS as output
SPI1 -> CR2 |= (SPI_CR2_TXEIE);                                                      // Tx buffer Empty Ymtirrupt Enable
SPI1 -> CR1 |= (SPI_CR1_SPE);                                                         // SPI enable

NVIC_EnableIRQ(SPI1_IRQn);

while (1)
{
while((SPI1->SR & SPI_SR_BSY)) {}                              // Woyting while SPI busy

for (i = 0; i < 100; i++) {   __asm  {NOP};   }
for (i = 0; i < 100; i++) {   __asm  {NOP};   }
for (i = 0; i < 100; i++) {   __asm  {NOP};   }
for (i = 0; i < 100; i++) {   __asm  {NOP};   }

GPIOA -> BRR = GPIO_BSRR_BS_4;                                    // input (CS down)
SPI1 -> DR = 0x1001;                                                   // Send data to SPI
}

void SPI1_IRQHomdler(void)
{
GPIOA -> BSRR = GPIO_BSRR_BS_4;                                    // latch data (CS up)
}
Выкладывать код нужно с использованием тэгов [code].
0 / 0 / 0
Регистрация: 01.02.2011
Сообщений: 300
03.12.2015, 16:36 15
При входе в прерывание надо самому сбрасывать флаг прерывания. А потом выполнять другое действие.
0
sdo
03.12.2015, 17:10 16
Да, спасибо! Уже разобрался с последовательностью срабатывания прерывания и флагом TXE.
Цель - среагировать по окончанию передачи данных.
А TXE встает в 1 при опустошении регистра DR. Но его опустошение еще не говорит о том, что данные переданы!
Поэтому даже при запуске прерывания приходится проверять флаг занят или нет в данный момент SPI, т.е. BSY.
Очень удобно, если надо передать большое количество данных, но совершенно не подходит для передачи только одной команды.
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
03.12.2015, 22:49 17
для 1 байта используйте Transfer Complete, или как-то так. Под рукой документации нет, могу напутать. В общем бит, который показывает что не только fifo пустой, но и DR пустой, т.е. передача полностью завершена. TXE удобно использовать при передаче массива, а на последнем байте ждете не TXE а TC.
0
03.12.2015, 22:49
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.12.2015, 22:49
Помогаю со студенческими работами здесь

Вопрос по SPI
Всем привет! Мучает такой вопрос. При передаче байта по SPI на каждый импульс тактового сигнала...

Вопрос по SPI
Господа, Есть тупой вопрос по поводу SPI. В даташите на мегу 16 есть такой пример инициализации...

Помогите разжевать - вопрос по инициализации
Мужики помогите понять код. Хотелось бы разобраться до точки. После АВР-кого ассемблера я что то не...

Вопрос по SPI
Направьте в нужное русло. Требуется поработать с микросхемой по SPI. Хочу попробовать это сделать...

Вопрос по spi
Имеются две системы управления двигателями, на Avr - главная система управления, на Motorolе -...

вопрос по таймингам SPI
Вот снял лог.анализатором кусок процесса общения меги с SD-карточкой. из готового и нормально...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru