stm32f103c8t6 использование 2-х SPI
- Войдите на сайт для отправки комментариев
Вс, 21/07/2019 - 05:25
Здравствуйте.
Суть проблемы подключил к плате два SPI устройства
SPI 1 модуль nrf24L01
SPI 2 TFT млдуль на ILI9341
суть проблемы не работает SPI 1
дисплей работает нормально, nrf24L01 не принимает данные(работает только на приём)
вот код
#include <SPI.h> #include <SoftWire.h> #include "Wire.h" #include "Adafruit_GFX_AS.h" #include "Adafruit_ILI9341_STM.h" #include "uRTCLib.h" #include "nRF24L01_STM32.h" #include "RF24_STM32.h" RF24 radio(PA4,PA1);// CE, CSN const uint64_t pipe = 0xF0F1F2F3F4LL; SPIClass SPI_2(2); SoftWire SWire(PB6, PB7, SOFT_FAST);//SCL, SDA, uRTCLib rtc(0x68, 0x57); #define TFT_CS PB12 #define TFT_DC PB11 #define TFT_RST PB10 Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST); // Use hardware SPI void setup() { // SPI.setModule(1); SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); //SPI.setClockDivider(SPI_CLOCK_DIV16); radio.begin(); delay(10); radio.setChannel(9); //radio.setRetries(15,15); radio.setDataRate(RF24_1MBPS); radio.setPALevel(RF24_PA_HIGH); radio.openReadingPipe(1,pipe); // открываем первую трубу с индитификатором "pipe" radio.startListening(); // включаем приемник, начинаем слушать трубу Wire.begin(); tft.begin(SPI_2, 16000000); // set direct frequency value in MHz tft.fillScreen(ILI9341_BLACK); } void loop(void) { // for(uint8_t rotation=0; rotation<4; rotation++) { tft.setRotation(1); // testText(); delay(1000); tft.setTextColor(ILI9341_YELLOW,ILI9341_BLACK); tft.setTextSize(4); rtc.refresh(); tft.setCursor(0, 0); tft.print(" "); tft.setCursor(0, 0); tft.print(rtc.hour()); tft.print(':'); tft.print(rtc.minute()); tft.print(':'); tft.println(rtc.second()); tft.print("Temp: "); tft.println(rtc.temp()); int data; if (radio.available()){ // проверяем не пришло ли чего в буфер. radio.read(&data, sizeof(data)); // читаем данные, указываем сколько байт читать tft.print("Nrf: "); tft.println(data); } }
если в эту же плату записываю другой код только на передачу с NRF24L01 ,но без других устройств (часы,дисплей) то передача работает. Вот код
#include <SPI.h> #include "nRF24L01_STM32.h" #include "RF24_STM32.h" // Set up nRF24L01 radio on SPI-1 bus (MOSI-PA7, MISO-PA6, SCLK-PA5) ... IRQ not used? RF24 radio(PA4,PA1);// CE, CSN const uint64_t pipe = 0xF0F1F2F3F4LL; // Radio pipe addresses for the 2 nodes to communicate. int data = 1; void setup(){ Serial1.begin(9600); delay(1000); Serial.println("\n\rRF24 Sensor Receiver"); SPI.begin(); SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(MSBFIRST); // Setup and configure rf radio radio.begin(); // optionally, increase the delay between retries & # of retries //radio.setRetries(15,15); radio.setChannel(9); radio.setDataRate(RF24_1MBPS); radio.setPALevel(RF24_PA_HIGH); // Open pipes to other nodes for communication // This simple sketch opens two pipes for these two nodes to communicate // back and forth. // Open 'our' pipe for writing // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) radio.openWritingPipe(pipe); // открываем трубу на передачу. } void loop(){ delay(1000); data++; // читаем значение radio.write(&data, sizeof(data)); // отправляем данные и указываем сколько байт пакет Serial1.print("data: "); Serial1.println(data); }
Может кто сталкивался с подобной проблемой...
А прием без других устройств? Зачем передачу показывать, если прием не работает?
Придётся пробовать, но тогда дисплей придётся другой цеплять......
Зачем дисплей? Выводи в сериал по шнурку, которым шьёш.
попробовал простой скрипт работает
а основной с TFT бесконечно быстро выдаёт пустые данные, тоесть вроде бы данные приходят но пусто и быстро данные должны приходить раз в секунду
А в сериал что выходит из последней программы? Вроде одно и тоже должно быть на экране и в сериале. К тому же экран очень быстро перерисовывается. Зачем в лупе каждый раз инициализировать экран? Экран у Вас перерисовывается много раз в секунду. Повесте перерисовку экрана раз в секунду с помощью блинк без делэя.
В сериал постоянно очень быстро лелит
Yesy nfr24l01-
то есть срабатывает команда
экспериментальным путём убрав всё что связано с SPI2 и построчно добавляя,
понял что проблемы вознмкаю после добавления
наверное какой то конфликт с SPI1 возникает
по поводу прорисовки дисплея пока не заморачивался потому что главное с SPI разобраться.
Спасибо за советы.
Это не конфликт spi. Это конфликт библиотеки и назначения spi. Плохо написанная библиотека не понимает что ей инстанс поменяли. Нужно лезть в библиотеку и руками править назначение spi. При прямом програмировании всё бы работало без проблем. Как помочь не знаю. Смотрите в библиотеке место где идет инициализация. Должна быть команда привязки к конкретному spi. Для себя раз можно поменять. Может быть поможет это https://www.stm32duino.com/viewtopic.php?t=278
Как вариант можно попробывать не создавать доп. класс, а менять каждый раз SPI, к которому идёт обращение, SPI.setModule();
нашёл вроде что то полезное , https://www.stm32duino.com/viewtopic.php?t=3813
но в англитйском не очень, попробовал библиотеку с изменениями дисплей не заработал
вообще,
зарегистрировался на
Arduino for STM32 но почемуто нет ссылок не на открытие тем не на посты, думаю там бы помогли грустно.
В теме что Вы нашли всё написано. Надо модифицировать либу, хотя на это и ругаются, что не правильно либу править, но другого решения не предложили. Как вариант самому написать кусок вывода точки и подсунуть его либе.
Кому интересно проблему решил, заменил файлы библиотеки на файлы из этой темы https://www.stm32duino.com/viewtopic.php?t=3813
вот рабочая версия скрипта
Как всегда, dimax прав. Для STM32F103C8T6 во всяком случае. Порядок такой:
SPI.setModule(1);
... (обращение к устройству 1)
SPI.setModule(2);
... (обращение к устройству 2)
Для указанной платы SPI1 - это PA7/PA6/PA5/PA4, SPI2 - PB15/PB14/PB13/PB12 (соответственно MOSI, MISO, SCK, SS).
Как всегда, dimax прав. Для STM32F103C8T6 во всяком случае. Порядок такой:
SPI.setModule(1);
... (обращение к устройству 1)
SPI.setModule(2);
... (обращение к устройству 2)
этот вариант, как и писал Dimax - требуется только для старых библиотек, в которых жестко задан один SPI. Сейчас уже в большинстве библиотек есть поддержка SPIClass и описанного выше извращения не требуется.
Делайте так, как описана у Вадима в сообщении #11
b707, спасибо за замечание. Но тогда при передаче данных и прочем общении необходимо будет писать что-то вроде SPI_2.transfer. А эта передача скрыта в библиотеке. Неудобно. Проще перед обращением к конкретному устройству (методами библиотеки) указать SPI.setModule(1) или SPI.setModule(2).
b707, спасибо за замечание. Но тогда при передаче данных и прочем общении необходимо будет писать что-то вроде SPI_2.transfer. А эта передача скрыта в библиотеке. Неудобно. Проще перед обращением к конкретному устройству (методами библиотеки) указать SPI.setModule(1) или SPI.setModule(2).
Это неправильно.
Один экземпляр класса не должен работать более чем с одним набором пинов.
Кроме того, один экземпляр класса SPI может поочередно работать с несколькими устройствами.
Так что то, что кому-то "проще", не всегда оказывается правильным.
Тем более, что в своей аргументации Вы явно не правы: заводится два (или больше) экземпляра одного и того же класса, которые и можно назвать, скажем SPI_1 и SPI_2 (принципиально, что это именно экземпляры одного и того же класса), и каждый сконфигурировать на определенные пины и на работу с конкретным устройством.
Если библиотека "привыкла" к использованию имени экземпляра "SPI", то никто не мешает назвать один из экземпляров именно так.
В принципе, конечно, можно сделать о обертку над классом, в котором предусмотреть функции типа setModule, но это явно увеличивает ресурсоемкость, снижает универсальность, да и вообще можно рассматривать как костыли. Причем, не совсем удобные. Но некоторые склонны рассматривать привычку как удобство, так что кому-то такой подход может показаться и удобным. Только не нужно его пропагандировать, т.к. это явно шаг не в ту сторону.
b707, спасибо за замечание. Но тогда при передаче данных и прочем общении необходимо будет писать что-то вроде SPI_2.transfer. А эта передача скрыта в библиотеке. Неудобно.
в большинстве современных библиотек для СТМ32 в конструкторе предусмотрен параметр, принимающий ссылку на конкретный экземпляр SPI, поэтому ничего внутри библиотеки переписывать не придется.
Снова говорю - смотрите код в сообщении #11 - там есть пример при обращении к дисплею, обратите внимание на последний парметр
в большинстве современных библиотек для СТМ32 в конструкторе предусмотрен параметр, принимающий ссылку на конкретный экземпляр SPI, поэтому ничего внутри библиотеки переписывать не придется.
Снова говорю - смотрите код в сообщении #11 - там есть пример при обращении к дисплею, обратите внимание на последний парметр
Если предусмотрен, то, конечно, хорошо. Но не всегда:
Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST);
b707, спасибо за замечание. Но тогда при передаче данных и прочем общении необходимо будет писать что-то вроде SPI_2.transfer. А эта передача скрыта в библиотеке. Неудобно. Проще перед обращением к конкретному устройству (методами библиотеки) указать SPI.setModule(1) или SPI.setModule(2).
Это неправильно.
Один экземпляр класса не должен работать более чем с одним набором пинов.
Кроме того, один экземпляр класса SPI может поочередно работать с несколькими устройствами.
Так что то, что кому-то "проще", не всегда оказывается правильным.
Тем более, что в своей аргументации Вы явно не правы: заводится два (или больше) экземпляра одного и того же класса, которые и можно назвать, скажем SPI_1 и SPI_2 (принципиально, что это именно экземпляры одного и того же класса), и каждый сконфигурировать на определенные пины и на работу с конкретным устройством.
Если библиотека "привыкла" к использованию имени экземпляра "SPI", то никто не мешает назвать один из экземпляров именно так.
В принципе, конечно, можно сделать о обертку над классом, в котором предусмотреть функции типа setModule, но это явно увеличивает ресурсоемкость, снижает универсальность, да и вообще можно рассматривать как костыли. Причем, не совсем удобные. Но некоторые склонны рассматривать привычку как удобство, так что кому-то такой подход может показаться и удобным. Только не нужно его пропагандировать, т.к. это явно шаг не в ту сторону.
"Привыкнуть" к использованию экземпляра с именем "SPI" может не только одна, но и другие библиотеки, одновременно используемые. Что тут поделаешь - их авторы так распорядились. Универсальные средства бывают, но редко. В каждом конкретном случае приходится чем-то поступаться: ресурсами, временем, надежностью. Пропаганда - это навязывание, да еще и в свою пользу. Мы же с вами ищем решения, удобные для любого.
Если предусмотрен, то, конечно, хорошо. Но не всегда:
Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST);
эта строчка ничего не доказывает, у библиотеки может быть несколько конструкторов - один с указанием SPI. другой без. Надо видеть исходники библиотеки.
Но даже если там нет поддержки SPIClass - добавить ее в общем-то несложно, это можно сделать почти автозаменой SPI. на какое-нить my_SPI и определить my_SPI в парметрах
если только в библиотеке есть поддержка ДМА - тогда чуть сложнее... но не намного.
"Привыкнуть" к использованию экземпляра с именем "SPI" может не только одна, но и другие библиотеки, одновременно используемые. Что тут поделаешь - их авторы так распорядились.
Я рискну напомнить, что SPI позволяет единственному устройству работать со многими внешними устройствами. Так что, если библиотеки "заточены" под единственный SPI, можно им и не мешать - пусть работают с единственным (у меня во многих проектах по SPI подключается несколько устройств, но использовать два канала SPI мне не приходилось еще ни разу).
Универсальные средства бывают, но редко. В каждом конкретном случае приходится чем-то поступаться: ресурсами, временем, надежностью.
Универсальность - это когда уже чем-то поступились. Обычно имеющимися ресурсами (универсальное решение, как правило, проигрывает по производительности потребляет больше ресурсов).
Мы же с вами ищем решения, удобные для любого.
Для этого нужно договориться, что мы подразумеваем под удобством. В частности, включаем ли мы в понятие удобства привычки. Если включаем, то найти решение "удобное для любого", скорее всего, не получится.
Совершенно верно: понятия должны быть закреплены. Удовлетворение привычкам, очевидно, в понятие "удобство" входит. Для конкретного индивида.
Конструктор один единственный:
Arduino_ST7789(int8_t DC, int8_t RST, int8_t CS = -1);
Вы предлагаете корректировать библиотеку. Можно. Но можно, как мы видели, обойтись и без этого. В любом случае полезно знать имеющиеся варианты решения задачи.