Jump to content

john2103

Members
  • Content Count

    19
  • Joined

  • Last visited

Community Reputation

1 Обычный

About john2103

  • Rank
    Новенький

Информация

  • Город
    Архангельск

Электроника

  • Стаж в электронике
    3-5 лет
  • Сфера радиоэлектроники
    STM32

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Я знаю, это просто что бы выработать привычку установки нужного бит. А то потом пропускаю в нужных местах. Опять же, буду знать, когда буду с ним разбираться! Спасибо! Что касается DFF Нас интересует последний клок передачи 8 битного массива: Его длительность На следующим скрине, импульс изменения DFF флага: Функция передачи при этом имеет вид: void SPI1_STM32F1_write_16bit_irq(uint16_t *data, int32_t len_16bit) { if(len_16bit<=0) return; while(SPI1->SR & SPI_SR_BSY) ; A3_true; SPI1->CR1 |= SPI_CR1_DFF; A3_false; flag =1; tx_index_16_bit = 0; tx_len_16_bit = len_16bit; tx_data_16_bit = data; SPI1->CR2 |= SPI_CR2_TXEIE; } Как видно изменение бита DFF произошло, раньше чем закончился крайний клок. Это произошло потому, что выбранная мной скорость работы SPI модуля ( SPI1->CR1 |= SPI_CR1_BR// --- BR[2:0]: Выбор скорости передачи // 000: fPCLK/2 // 001: fPCLK/4 // 010: fPCLK/8 // 011: fPCLK/16 // 100: fPCLK/32 // 101: fPCLK/64 // 110: fPCLK/128 // 111: fPCLK/256 на много меньше, чем скорость работы ядра контроллера.Флаг BSY опускается в 0 раньше, чем SCK опускает линию на крайнем импульсе и программа успевает выполнить смену DFF за это время. Как это видно на рис 3 Длительность этого импульса (3 рисунок) намного меньше чем длительность клока (2 рисунок) 0.5 мкС. Если в функцию передачи добавить включение и отключение SPI (SPE = 0 ... SPE = 1) перед и после DFF соответственно, функция будет иметь вид: void SPI1_STM32F1_write_16bit_irq(uint16_t *data, int32_t len_16bit) { if(len_16bit<=0) return; while(SPI1->SR & SPI_SR_BSY) ; A3_true; SPI1->CR1 &= ~SPI_CR1_SPE; SPI1->CR1 |= SPI_CR1_DFF; SPI1->CR1 |= SPI_CR1_SPE; A3_false; flag =1; tx_index_16_bit = 0; tx_len_16_bit = len_16bit; tx_data_16_bit = data; SPI1->CR2 |= SPI_CR2_TXEIE; } На рис 4, видно что длительность увеличилась, но все еще меньше чем конец SCK Поэтому, все равно есть лишняя передача. Как только длительность этого импульса выходит за пределы крайнего клока минимум на больше чем 0,25 мкС, все начинает работать правильно. Как я понял, что бы все работало правильно, изменение DFF не должно начинаться и заканчиваться пока идет клок сигнал (И как видно вкл и откл модуля на это не влияет) На рисунке 5 показано, когда модуль начинает правильно работать: Как видно пропала лишняя передача. Не понял вопроса ? 8Мгц - это внешний кварц который установлен на отладочной плате. 72 Мгц - это частота с которой работает контроллер (с 8 Мгц частота через PLL увеличивается до 72 Мгц) /256 - это предделитель выставленный для SPI Частота работы SPI 281.25 Кбит/с
  2. Настройки порта самого те?
  3. Доброго времени суток, товарищи! Для тех, кому все же интересно! Наконец добрался до компа и провел тесты. Можно сказать выяснил в чем проблема... (но все же это условно). По совету @MasterElectric добавил несколько контрольных пинов и с помощью ЛА отслеживал изменения. Весь перечень того что делал не привожу, нет смысла, самое интересно: #define A0_true GPIOA->BSRR |= GPIO_BSRR_BS0 #define A0_false GPIOA->BSRR |= GPIO_BSRR_BR0 #define A1_true GPIOA->BSRR |= GPIO_BSRR_BS1 #define A1_false GPIOA->BSRR |= GPIO_BSRR_BR1 #define A2_true GPIOA->BSRR |= GPIO_BSRR_BS2 #define A2_false GPIOA->BSRR |= GPIO_BSRR_BR2 #define A3_true GPIOA->BSRR |= GPIO_BSRR_BS3 #define A3_false GPIOA->BSRR |= GPIO_BSRR_BR3 #define A4_true GPIOA->BSRR |= GPIO_BSRR_BS4 #define A4_false GPIOA->BSRR |= GPIO_BSRR_BR4 ......... void SPI1_STM32F1_write_8bit_irq(uint8_t *data, int32_t len_8bit) { A1_true; if(len_8bit<=0) return; A4_true; while(SPI1->SR & SPI_SR_BSY) ; A4_false; A3_true; SPI1->CR1 &= ~SPI_CR1_SPE; A0_true; SPI1->CR1 &= ~SPI_CR1_DFF; A0_false; SPI1->CR1 |= SPI_CR1_SPE; A3_false; flag =0; tx_index_8_bit = 0; tx_len_8_bit = len_8bit; tx_data_8_bit = data; SPI1->CR2 |= SPI_CR2_TXEIE; A1_false; } void SPI1_STM32F1_write_16bit_irq(uint16_t *data, int32_t len_16bit) { A2_true; if(len_16bit<=0) return; A4_true; while(SPI1->SR & SPI_SR_BSY) ; A4_false; A3_true; SPI1->CR1 &= ~SPI_CR1_SPE; A0_true; SPI1->CR1 |= SPI_CR1_DFF; A0_false; SPI1->CR1 |= SPI_CR1_SPE; A3_false; flag =1; tx_index_16_bit = 0; tx_len_16_bit = len_16bit; tx_data_16_bit = data; SPI1->CR2 |= SPI_CR2_TXEIE; A2_false; } A1_true / A1_false - Начало / конец Передачи 8 бит A2_true / A2_false - Начало / конец Передача 16 бит A4_true / A4_false - Ожидание флага BSY A3_true / A3_false - Откл SPE =0, Вкл SPE = 1 A0_true / A0_false - Включение (или отключение ) бита DFF При том коде, что записан выше, интересны флаги A4_false, A0_false и A3_false, относительно последнего CLOCKа! Видно что BSY срабатывает, когда реально еще идет "крайний CLOCK", происходит смена бита DFF(еще время уходит на переключение флага A3_true) и заканчивается раньше чем крайний КЛОК, но при этом включение SPE = 1 происходит после него. (А1 - А2 А самое главное более 0,25 мкс после "крайнего клока") и код работает как надо, никаких лишних передач! Если убрать флаги переключения DFF, но при этом оставить включение и отключение SPI (SPE = 0, SPE = 1), то получим: .... A3_true; SPI1->CR1 &= ~SPI_CR1_SPE; // A0_true; SPI1->CR1 &= ~SPI_CR1_DFF; // A0_false; SPI1->CR1 |= SPI_CR1_SPE; A3_false; ..... A3_true; SPI1->CR1 &= ~SPI_CR1_SPE; // A0_true; SPI1->CR1 |= SPI_CR1_DFF; // A0_false; SPI1->CR1 |= SPI_CR1_SPE; A3_false; ..... Несмотря на смену DFF при отключенном модуле (SPE = 0), время выполнения откл SPI смены DFF и вкл SPI меньше чем выполнение крайнего клока. (Есть ненужная передача 0x00) Предыдущий код работал потому что переключение флагов, вносило своего рода задержки. Когда я убрал эти переключения, время на выполнение всех операций сократилось и стало меньше чем окончание передачи. Поэтому и пошли ошибки. После этого я закоментил строки: //A3_true; //SPI1->CR1 &= ~SPI_CR1_SPE; .... //SPI1->CR1 |= SPI_CR1_SPE; //A3_false; Видно, что бит DFF меняется во время крайнего КЛОКА, отключение SPI вообще не происходит, есть лишний бит 0x00. После этого я просто добавил несколько __NOP(); перед сменой DFF. (Экспериментально, я нашел), что бы пропала лишня передача 0х00 и код стал правильно работать, смена DFF должна заканчиваться через ~0,25 мкс после крайнего клока, что бы все правильно работало (При том что сам модуль я не отключаю SPE =1 и я его не трогаю) void SPI1_STM32F1_write_8bit_irq(uint8_t *data, int32_t len_8bit) { A1_true; if(len_8bit<=0) return; A4_true; while(SPI1->SR & SPI_SR_BSY) ; A4_false; __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); ..... ..... __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); // A3_true; //SPI1->CR1 &= ~SPI_CR1_SPE; // A0_true; SPI1->CR1 &= ~SPI_CR1_DFF; A0_false; //SPI1->CR1 |= SPI_CR1_SPE; // A3_false; flag =0; tx_index_8_bit = 0; tx_len_8_bit = len_8bit; tx_data_8_bit = data; SPI1->CR2 |= SPI_CR2_TXEIE; A1_false; } Как видно, все работает правильно, никаких лишних передач нет, все работает как надо. При этом сам модуль я не отключал (SPE =1 и я его не трогал). ИТОГИ: На самом деле было много экспериментов, я рассказал об основном. Сделать вывод можно такой.... Битность "на лету" менять можно, но смена должна заканчиваться не раньше, чем ~0,25мкс после крайнего тика(всего массива!!!!)! И даже если битность менять, только во время отключения модуля, то включать его тоже нельзя раньше чем ~0,25 мкс после крайнего тика, иначе (чисто моя теория) модуль думает, что до этого он передавал 16 битные данные, 8 передал и надо еще 8. Отсюда и появлялись "лишние" передачи. Вот такая особенность. Это все было про кварц 8 Мгц, частота ядра 72 Мгц, частота SPI /256 Надеюсь это кому то пригодиться =) @MasterElectric Спасибо за совет!
  4. Развернутые коментарии??? Так это я для себя, что бы запомнить какие регистры, какие биты, как называются, для чего служат! А за этот совет, спасибо, обязательно попробую!
  5. А если я сейчас для примера возьму и изменю объем массива на 300 элементов 1000 или еще больше??? Это что изменить? У вас появиться решение? Я понял, на счет битности и согласен, что битф все равно идут подрят, ну предположим, вот задачу поставили именно так, реализовать именно смену битности! Вы можете, что подсказать конкретное по этому поводу?
  6. В чем проблема с моим cmsis, что я делаю не так?
  7. в самом начале топика озвучил! Изучаю! Можно так сделать или нет? Судя по всему прочитанному, это можно сделать, по факту не получилось! Стало просто интересно, этого вообще сделать нельзя или я что то не то делаю. Если есть опыт подскажите, буду очень благодарен. На практике я бы нашел рабочее решение, более простое, но тут чисто интерес, можно или нет Его уроки, я все давно пересмотрел и не по одному разу, но если ты заметил, он использует hal и ll. А я говорю про cmsis.
  8. Немного офтоп. Конечно Ваш ответ, просто лучший! Хоть кто то помог! Какие прерывания? dma? по завершению приема? передачи ? что значит непрерывная? Просто включил прерывание и все само волшебным образом передается? Если вы хотели помочь, то информативность Вашего сообщения 0! Если поиздеваться, то зачем, я не говорю что я ас! И я читал RF, но мне тяжело, темболее на английском, вот и смотрел попутный материал, где был
  9. Сейчас увеличил скорость работы spi до Так если я правильно все понимаю, то это и есть BSY флаг? Нет? Сейчас увеличил скорость работы SPI, левые посылки пропали. первый скрин скоросьть /256, второй /32 Где то в прерываниях я косячу, что то где то не так проверяю
  10. Пытаюсь, уже дня три, но постоянно в отладчике проскакиваю. Сейчас буду пытаться
  11. Я вот сейчас сижу и смотрю на схему выше И у меня тоже гипотеза почти как ваша .... Только вот думаю, а не может ли SPI "думать", что у него есть еще один, не принятый байт? и поэтому даже после флага BSY он шлет SCK, но вот почему он передает то 0x00 то 0xFE я не могу понять. (Или я немного не так понимаю смысл подписи к самой нижней картинке RX buffer) Хотя такая версия как у вас у меня тоже была. Просто не знаю как бы ее проверить ... Рубить тактирование модуля ?
  12. Прерывание нет. void SPI1_STM32F1_write_16bit_irq(uint16_t *data, int32_t len_16bit) { ..... SPI1->CR1 &= ~SPI_CR1_SPE; SPI1->CR1 |= SPI_CR1_DFF; SPI1->CR1 |= SPI_CR1_SPE; .... } В самой функции передачи происходит отключение модуля и переключение разрядности. И как писали выше, битность вроде можно менять на живую Забыл вставить это в шапке проги #define SPI1_Enable SPI1->CR1 |= SPI_CR1_SPE А дизэйбл не прописывал, дальше я и включал и выключал в функции передачи напрямую битами.
  13. Я знаю. И картинку смотрел. Я неправильно выразился. Если передавать большой объем данных с опросом флага, то программа "фактически" встанет, пока все не передаст все (DMA - пока в принципе не рассматриваю). С прерыванием она может выполнять какие то фоновые задачи в это время. Ну это так... для меня же пока основная задача, понять насколько хорошо я понял принципы. Только что убрал, все так же не правильные передачки проскакивают. В принципе строки отключения и включения spi, появились когда я искал причину появления этих лишних передач.
  14. Попробовал еще При такой конструкции SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_16bit_irq( data_16bit, 3); SPI1_STM32F1_write_16bit_irq( data_16bit, 3); SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_16bit_irq( data_16bit, 3); SPI1_STM32F1_write_16bit_irq( data_16bit, 3); получается 0xAA 0xBB 0xCC 0xAA 0xBB 0xCC 0x00 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF 0xAA 0xBB 0xCC 0xAA 0xBB 0xCC 0xFE 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF
  15. В том то и дело. По логике... Как я думаю spi не будет отключатся раньше чем выплюнет крайний бит и не примет если есть что, т.к. я отслеживаю флаг BSY. Но ощущение, что не смотря на то, что я проверил бит BSY и вроде как модуль закончил все дела,я его остановил и изменил количество бит на передачу, он почему то считает что в DR занесено значение 0x00 и выплевывает его, хотя этого нигде нет. Может конечно и моя функция на передачу с прерыванием вообще как то не так построена. Если передать SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_8bit_irq( data_8bit, 3); То все норм 0xAA 0xBB 0xCC 0xAA 0xBB 0xCC 0xAA 0xBB 0xCC Проверил если SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_8bit_irq( data_8bit, 3); SPI1_STM32F1_write_16bit_irq( data_16bit, 3); SPI1_STM32F1_write_16bit_irq( data_16bit, 3); SPI1_STM32F1_write_16bit_irq( data_16bit, 3); То после 8 битных передач опять появляется одна передача 0x00, а потом все норм по 16 бит как положено, ничего лишнего
×
×
  • Create New...