sdo
|
|
1 | |
Вопрос по инициализации SPI24.11.2015, 18:37. Показов 5641. Ответов 16
Метки нет (Все метки)
Доброго времени!
Уже пару дней пытаюсь заставить работать 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} } } Можете подсказать, где у меня грубая ошибка...? |
24.11.2015, 18:37 | |
Ответы с готовыми решениями:
16
Вопрос по spi SPI DMA вопрос Вопрос по SPI (а может и по C в Keil) ILI9341 SPI DMA, SPI, UART библиотеки |
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 бита на один пин) Код
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) { } } Ссылка: 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
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
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) } |
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 | |
03.12.2015, 22:49 | |
Помогаю со студенческими работами здесь
17
Вопрос по SPI Вопрос по SPI Помогите разжевать - вопрос по инициализации Вопрос по SPI Вопрос по spi вопрос по таймингам SPI Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |