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

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


bobbjenkins

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

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

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

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

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

1 hour ago, Uhbif said:

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

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

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

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

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

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

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

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

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

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 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
Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

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

Понял, спасибо. А еще вопрос, но считать я получается должен все регистры? То есть у акселерометра их 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 пользователей онлайн

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

×
×
  • Создать...