Перейти к содержанию

I2C иногда выдает HAL_BUSY после включения


bobbjenkins

Рекомендуемые сообщения

Заработало. Yurkin2015 спасибо вам огромное. Вы просто гений. А как вы поняли, что нужно сдвигать влево? Можно я к вам буду обращаться за советом?

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

  • Ответов 59
  • Создана
  • Последний ответ

Топ авторов темы

1 hour ago, Uhbif said:

нужно сдвигать влево

Это написано в инструкции по эксплуатации.

Обращайтесь за советом в общем форуме, тут полно специалистов, обязательно помогут.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

А никто не может подсказать где взять программу для визуализации данных с акселерометра, гироскопа, магнетометра. Как лучше рассчитывать кватернион.

Ссылка на комментарий
Поделиться на другие сайты

Особенности хранения литиевых аккумуляторов и батареек

Потеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

А кто нибудь может подсказать как читать данные по SPI интерфейсу, используя библиотеку HAL? Имею ввиду, если использовать контроллер STM32F415RG и датчик BMX055. С I2C мне подсказали, там есть готовые функции, где например нужно указать адрес устройства и требуемый регистр. А как быть с SPI? В библиотеках HAL тоже есть готовые функции, но в них не предусмотрены ни адреса устройств, ни адреса регистров. Я пробовал читать все подряд, но мне кажется это неправильно. У него номера регистров совпадают, есть 0х02 где хранятся данные гироскопа и акселерометра. Как быть?

Ссылка на комментарий
Поделиться на другие сайты

Секреты депассивации литиевых батареек FANSO EVE Energy

Самыми лучшими параметрами по энергоемкости, сроку хранения, температурному диапазону и номинальному напряжению обладают батарейки литий-тионилхлоридной электрохимической системы. Но при длительном хранении происходит процесс пассивации. Разберем в чем плюсы и минусы, как можно ее избежать или уменьшить последствия и как проводить депассивацию батареек на примере продукции и рекомендаций компании FANSO EVE Energy. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

4 hours ago, Uhbif said:

не предусмотрены ни адреса устройств

В интерфейсе SPI нет адресов устройств, как в I2C. Зато там есть дополнительная линия сигнала CS, которая позволяет указать к какому устройству идёт обращение в данный момент. Если у нескольких устройств объединить линии клоков и данных, то линии CS не объединяются, и у каждого устройства будет свой сигнал CS.

В неактивном состоянии все сигналы CS = 1. При общении по SPI один из сигналов CS устанавливают = 0, и будет активироваться только то устройство, у которого CS = 0. Остальные проигнорируют SPI обращение.

В датчике BMX055 находятся три независимых устройства: акселерометр, гироскоп и магнитометр, и адреса внутренних регистров у них совпадают. Но у каждого из них своя линия активации SCB1, CSB2 и CSB3. Вот и пользуйте эти сигналы, когда хотите прочитать регистры какого-либо одного конкретного устройства. Например, если SCB1=0, а остальные SCB2 = 1, SCB3 = 1,то по SPI будет откликаться только акселерометр.

 

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

Понял, спасибо. А еще вопрос, но считать я получается должен все регистры? То есть у акселерометра их 64 например, и из них взять нужные мне. Например, 0х02 и так далее? Сейчас попробую.

Ссылка на комментарий
Поделиться на другие сайты

@Uhbif Не надо все регистры читать, читайте только нужные.

Например, для ускорения по оси Х пользуете посылку из 3-х байтов. Первым байтом посылаете адрес регистра 0х02 с установленной 1 в старшем бите (R/W), т.е. посылаете 0х82. Затем посылаете два нулевых байта 0х00. Во втором байте вернётся содержимое регистра 0х02, в третьем байте вернётся регистр 0х03. Вот и всё, значение по Х получено.

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

Вон оно как устроено. А  функцию брать из халовской библиотеки какую HAL_SPI_Receive  или  HAL_SPI_Transmit? Там еще есть и Transmitreceive. Секйчас буду пробовать.

Ссылка на комментарий
Поделиться на другие сайты

@Uhbif HAL_SPI_Receive() использует один и тот же буфер для передачи и приёма, т.е. сначала кладёте в буфер что хотите послать {0x82, 0x00, 0x00}, запускаете функцию и получаете на том же месте данные {0x??, accX0, accX1}.

HAL_SPI_Transmit() только передаёт байты из буфера и игнорирует приёмные байты.

HAL_SPI_TransmitReceive() передаёт и принимает байты в разные буферы.

Ссылка на комментарий
Поделиться на другие сайты

Все равно что то не то. Вот посмотрите правильно ли я написал?

 

uint8_t ReadData_SPI(uint8_t pRxData)    ///это для чтения одного байта

{

HAL_StatusTypeDef status = HAL_OK;


status = HAL_SPI_Receive(&hspi2, &pRxData, 1, 0x10000);

if(status != HAL_OK) //// здесь просто проверяю что правильно отработала функция
             {
                 Led_on;
             }
            else
             {
         Led_off;
       }

return pRxData;  ////вот это и будет нужное нам значение

}
 правильно ли так посылать и получать один байт?

 

void Accel_ReadAcc_SPI(void)     ////в этой функции читаю и отправляю данные в виртуальный ком-порт

{
       vkl_accel(); //здесь подают 0 на акселерометр, чтобы можно было с него читать данные

        uint8_t desc_accel[]="Accelerometr \r\n"; ///просто выведу слово

        int8_t str[64];
       

        uint8_t data[64];


        int16_t x_acc,y_acc,z_acc;

        ReadData_SPI(0x82), // здесь просто посылаю адрес регистра, который хочу прочитать

        data[0] = ReadData_SPI(0x00); //здесь посылаю 0, чтобы прочитать значения
        data[1] = ReadData_SPI(0x00);

        ReadData_SPI(0x84),

        data[2] = ReadData_SPI(0x00);
        data[3] = ReadData_SPI(0x00);

        ReadData_SPI(0x86),

        data[4] = ReadData_SPI(0x00);
        data[5] = ReadData_SPI(0x00);

   


        x_acc = data[0] + (data[1]<<8);

        y_acc = data[2] + (data[3]<<8);

        z_acc = data[4] + (data[5]<<8);


        CDC_Transmit_FS((unsigned char*)desc_accel, strlen(desc_accel));

        HAL_Delay(1);

       sprintf(str,"X,m/s2:%10d Y,m/s2:%10d Z,m/s2:%10d\r\n", x_acc,y_acc,z_acc);


        CDC_Transmit_FS((unsigned char*)str, strlen(str));

     

        HAL_Delay(20);

            }

ну и соответственно эту функцию постоянно кручу в while. Правильно ли так делать? У меня все равно одни 0. Видимо что то не так.

 

 

 

Ссылка на комментарий
Поделиться на другие сайты

@Uhbif При чтении первый байт посылки - это всегда адрес регистра, который хотите прочитать. Поэтому нельзя посылать только один байт. Надо сразу посылать 3 байта: адрес и два байта данных.

uint8_t RxData[3];

RxData[0] = 0x82;

HAL_SPI_Receive(&hspi2, RxData, 3, 0x10000); // за один присест послали адрес регистра и прочитали два байта данных

x_acc = ((RxData[2] << 8) + RxData[1]);
x_acc = x_acc >> 4;

 

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

я сделал так как вы написали, пробую прочитать нулевой регистр. Хочу увидеть ID, должен быть 250. Он правильно его читает только первый раз, затем постоянно уменьшает значение. Я не мог понять в чем дело, но потом решил после прочтения дописывать all_off(); то есть давать единицу на акселерометр, как бы что он закончил чтение.  Он начал корректно писать 250.  Хочу вас спросить, а если читать больше регистров сразу, нормально это будет? То есть если я даю вначале 0х82, и потом читаю скажем последующие 6 байт, чтобы сразу y, z значения получить. Еще хотел спросить, а зачем вы x_acc сдвигаете вправо на 4 в конце, мне кажется не нужно.

Ссылка на комментарий
Поделиться на другие сайты

попробовал читать по 6 байт, вроде получается. Но у меня почему то не читается магнетометр, ни по I2C ни по SPI. Не знаете что может быть, может его надо как то отдельно включать?

Ссылка на комментарий
Поделиться на другие сайты

4 hours ago, Uhbif said:

давать единицу на акселерометр

Как происходит чтение акселерометра:

Сначала надо подать ноль на линию выбора акселерометра, остальные линии выбора в единице, т.е. CSB1 = 0, CSB2 = 1, CSB3 = 1. Акселерометр активируется и готов принимать байты по SPI.

Посылаете первый байт с адресом регистра, с которого хотите начать чтение, например регистр 0х02.

Посылаете второй байт, неважно какой, акселерометр одновременно с этим посылает значение из регистра 0х02.

Посылаете третий байт, неважно какой, акселерометр при этом посылает значение из следующего регистра 0х03, т.е. адрес регистра увеличивается автоматически на 1.

Посылаете четвёртый байт, неважно какой, акселерометр при этом посылает значение из регистра 0х04.

И так далее.

Когда прочитали все нужные регистра, переводите сигнал выбора в 1, т.е. CSB1 = 1, при этом акселерометр деактивирует свой SPI интерфейс.

Всё, сеанс связи с акселерометром закончен.

 

4 hours ago, Uhbif said:

сдвигаете вправо на 4

Потому что в регистрах датчика данные записаны со сдвигом влево на 4.

 

3 hours ago, Uhbif said:

не читается магнетометр

У магнитометра адреса регистров отличаются от других датчиков. Вы опрашиваете правильные адреса?

Кроме того, у магнитометра есть регистры управления состоянием датчика. При включении питания магнитометр проводит внутреннюю инициализацию и впадает в спячку. Для измерений надо перевести его в рабочий режим. Для этого надо установить в единичку Power Control бит в регистре 0х01, затем установить оба бита Opmode[1:0] в нули в регистре 0х06. После этого магнитометр начнет периодически измерять магнитное поле и результаты складывать в регистры данных.

 

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

по чтению все правильно, читаться корректно начал, когда только стал 1 записывать ему по сеансу окончания чтения.

Насчет сдвига вправо, если смотреть даташит, да вроде кажется надо сдвинуть вправо на 4, но ведь слева 4 старших разряда запишутся нули, тогда мы можем знак потерять, старший бит у числа int16_t как раз определяет знак, если там 1 значит -. Или может быть более корректно использовать запись

x_acc = X_acc>>4 + 0x8000; типа того?

Насчет магнетометра регистры правильно пишу. И что странно там внизу надпись есть, если хотите ID его прочитать запишите в регистр 4В power control bit - 1. Я так делал и он ID корректно читал, но данных с регистров все равно не было. Вернее были 1, но это я так понял значения X,Y,Z self-test они по умолчанию там 1. Хотя если power control bit не устанавливать в 1, то были 0. Я думал, надо где то оси включать, но по даташиту речь вроде только о прерываниях идет.

В любом случае большое вам спасибо за помощь! Редко кто так толково объясняет как вы, без вас бы я не разобрался.

Ссылка на комментарий
Поделиться на другие сайты

9 minutes ago, Uhbif said:

запишутся нули

А вот и нет. Если переменная типа int16_t, то операция сдвига такой переменной обладает способностью растягивать знаковый бит, т.е. если число отрицательное, то при сдвиге слева запишутся единички, а не нули. При сдвиге вправо знаковый бит не теряется.

Кроме power control надо ещё opmode[] биты устанавливать.

Ссылка на комментарий
Поделиться на другие сайты

переделал как вы посоветовали, магнитометр все равно корректно не выдает.

сделал инициализацию. 

void InitMag_SPI(void);
     void InitMag_SPI(void)

    {

         vkl_magnet();
         uint8_t TxData[3];
    TxData[0] = 0xCB;
    TxData[1] = 0x01; // пишу 1 в последний бит
    TxData[2] = 0x00; //устанавливаю режим норм

HAL_SPI_Transmit(&hspi2, &TxData, 3, 0x10000);

  all_off();

  HAL_Delay(20);

            }

 

Чтение

 

 void ReadMag_SPI(void);
   void ReadMag_SPI(void)

  {

       vkl_magnet();
   
  HAL_StatusTypeDef status = HAL_OK;

  uint8_t RxData[7];
  RxData[0] = 0xC2;

  uint16_t x_mag, y_mag;
  int16_t z_mag;

  uint8_t desc_mag[]="Magnetometr_SPI \r\n";

 

  int8_t str[64];

  status = HAL_SPI_Receive(&hspi2, &RxData, 7, 0x10000);

  if(status != HAL_OK)
               {
                   Led_on;
               }
              else
               {
           Led_off;
         }

  x_mag = ((RxData[2]<<8) + RxData[1]);
  x_mag = x_mag>>3;
  y_mag = ((RxData[4]<<8) + RxData[3]);
  y_mag = y_mag>>3;
  z_mag = ((RxData[6]<<8) + RxData[5]);
  z_mag = z_mag>>3;

   CDC_Transmit_FS((unsigned char*)desc_mag, strlen(desc_mag));

         HAL_Delay(1);


                   sprintf(str,"x_mag:%d y_mag:%d  z_mag:%d\r\n", x_mag,y_mag,z_mag);
                    CDC_Transmit_FS((unsigned char*)str, strlen(str));


                         all_off();


         HAL_Delay(20);

    

         }

Как вы  считаете так ли я делаю?

Ссылка на комментарий
Поделиться на другие сайты

Регистр с которого начнем запись 4B или 0100 - 4 в двоичной форме, старший бить нужно записать 1, для операции записи. то есть 1100 или С.

Общая запись 0хСВ; По крайней мере я так думаю.

Ссылка на комментарий
Поделиться на другие сайты

1 hour ago, Uhbif said:

старший бить нужно записать 1,

Вам надо проверить гипотезу "в каких случаях старший бит устанавливаем в 1 ?"

У меня нет такого датчика BMX055 и никогда не было. Я просто во время перекуров читаю описание датчика и пересказываю его Вам своими словами. Процесс пойдёт гораздо быстрее, если Вы тоже почитаете дейташит на датчик.

Похоже, что существует только multiple read, а записать можно всего лишь по одному байту, т.е. каждый раз нужно начинать с адреса регистра + только один байт для записи.

bmx055.png

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

ПРиветствую всех, у меня проблема с UARTom, по нему не получается передавать текст, он сыплет какую то ерунду. Скорости, и остальные настройки ком-порта проверил. STM32F415RG. Что интересно, если развернуть виртуальный ком-порт на USB, то там все работает корректно. Может у кого-нибудь была такая проблема?

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Сообщения

    • @DownHouse , насчёт номинала затворного резистора вам уже сказали. Он образует RC-цепочку с ёмкостью затвора транзистора. На высоких частотах ШИМ работать не будет. Кроме того, у транзисторных оптопар есть такой параметр: Как видите, ток коллектора может быть даже меньше входного тока в светодиод. Быстро управлять затвором мощного полевика, у которого ёмкость под 10 нФ, таким маленьким током не получится. Так что и тут ограничение на частоту ШИМ. По закону Ома он считается. Какой ток коллектора сможет выдать транзистор оптопары, такое напряжение на R2 и получится. Естественно с "упором" в напряжение питания. Выше него не прыгнешь. Транзистор оптопары войдёт в насыщение, выходной ток оптопары станет меньше максимального, который может выдать её транзистор, ток будет ограничен значением сопротивления R2. Например, при коэффициенте передачи тока оптопары, равным единице, при напряжении питания 5 В, при токе в светодиод оптопары 10 мА и при сопротивлении резистора R2 500 Ом, напряжение на нём будет 10 мА * 0,5 кОм = 5 В. Но если оптрон посредственный, с коэффициентом передачи тока 0,5, то при тех же условиях, выходной ток коллектора транзистора оптрона будет не больше 5 мА, и напряжение выше 2,5 В на R2 не поднимется. Если пороговое напряжение открывания полевого транзистора выше, то он не откроется. Чтобы схема работала при установке любого экземпляра оптопары, без отбора, схема проектируется исходя из наихудших значений параметров. В вашем случае минимально-допустимое сопротивление R2 будет 1 кОм (10 мА/2 * 1 кОм = 5 В).  
    • Алексей, ну ты-то уже опытный в аудиотехнике волк и понимаешь, что все эти буквенные обозначения на латинице у производящих е-cap-ы контор по факту означают разные потребительские характеристики. А товарищ @Алексей Акулиничев в этом ещё новичок; натрёт в залобье мозолей, с опытом тоже начнёт разбираться в "who из где". 
    • Смотря для чего оптимальный. Если вы КПД блока под 99% вытягиваете, то нужен очень маленький. Но при этом будет сильное недоиспользование габаритной мощности "железа" сердечника. Если задача по-максимуму использовать возможности сердечника - то ограничивается только максимальной температурой сердечника, точкой Кюри...
    • Примерно так. НО! Если у этих динамиков НЧ реально от 40Гц, то кубики пенопласта будут тереться друг об друга , создавая заметные на слух "артефакты", поэтому надо бы запастись тонким поролоном, или плотной тканью прокладывая его/её между ними, или обворачивая их. ЗЫ. Чем дешевле динамик и чем проще кажется реализация на нём более-менее ровно играющей акустической системы,тем  больше возни с ним. Это уже не раз доказанный практикой факт.
    • Вот спасибо. Это прям для меня.  Я не про этот резистор. Про этот резистор я понял. Я не понимаю нужен ли резистор перед 4 выводом оптопары. Да я пока думаю нужен ли он будет (в смысле ШИМ). Точности большой по температуре не нужно будет. R1 будет от 150 - 200 Ом, а вот R2 не очень понимаю как считать (как я понимаю этот резистор будет затвор транзистора на землю сажать пока оптопара закрыта,  5-10 кОм думаю) Вот так сделал.
×
×
  • Создать...