Как найти идентификатор устройства STM32F103RET

Мне сказали, что каждое устройство STM32F103RET имеет уникальный идентификатор устройства. Так какова процедура получения идентификатора? Я использую систему, в которой я обмениваюсь информацией с более чем одной борадой STM. Для дифференциации каждой платы STM я могу использовать этот уникальный идентификатор. Спасибо

1 ответ

Решение

Вы можете найти эту информацию в Справочном руководстве STM32F103. Более конкретно, вы хотите прочитать главу 30.2 Регистр уникального идентификатора устройства (96 бит).

Таким образом, идентификатор вашего устройства содержится в регистре только для чтения и называется U_ID. Этот адрес регистрации 0x1ffff7e8, Его длина составляет 96 бит, поэтому его можно прочитать (например), используя 3 операции чтения, каждая длиной 32 бита. Конечно, вы не можете держать его в одной переменной. Таким образом, вы должны придумать способ сохранить его в памяти. Это может быть массив или структура и т. Д.

Я бы, вероятно, использовал структуру для этой цели, используя смещения, описанные в Справочном руководстве:

#include <stdint.h>

struct u_id {
    uint16_t off0;
    uint16_t off2;
    uint32_t off4;
    uint32_t off8;
};

Как читать его, зависит от вас (зависит от того, какую платформу вы используете, например, в libopencm3 у вас есть макрос MMIO32 для этого). В общем случае я бы сделал что-то подобное:

#define MMIO16(addr)  (*(volatile uint16_t *)(addr))
#define MMIO32(addr)  (*(volatile uint32_t *)(addr))
#define U_ID          0x1ffff7e8

/* Read U_ID register */
void uid_read(struct u_id *id)
{
    id->off0 = MMIO16(U_ID + 0x0);
    id->off2 = MMIO16(U_ID + 0x2);
    id->off4 = MMIO32(U_ID + 0x4);
    id->off8 = MMIO32(U_ID + 0x8);
}

Вам также понадобится функция для сравнения двух идентификаторов. Вы можете использовать memcmp() или какая-то пользовательская функция в этом отношении. Я бы предпочел обычай в этом случае:

#include <stdbool.h>

/* Returns true if IDs are the same */
bool uid_cmp(struct u_id *id1, struct u_id *id2)
{
    return id1->off0 == id2->off0 &&
           id1->off2 == id2->off2 &&
           id1->off4 == id2->off4 &&
           id1->off8 == id2->off8;
}

Вы можете использовать это так:

int main(void)
{
    struct u_id id1 = { 0x0, 0x1, 0x2, 0x3 };
    struct u_id id2;
    bool same_id;

    uid_read(&id2);
    same_id = uid_cmp(&id1, &id2);

    printf("%s\n", same_id ? "equal" : "not equal");
    return 0;
}

ОБНОВИТЬ

Как я понимаю вашу ситуацию

  1. Каждая из ваших плат должна посылать некоторые прерывания на вашу основную плату (точнее, на вывод GPIO на основной плате).
  2. Как только ведущая плата получает прерывание, она инициирует передачу (запрос) на плату, откуда пришло прерывание (возможно, используя I2C, SPI, UART или что-то подобное для связи между платами).
  3. Затем клиентская плата отвечает своим идентификатором устройства.
  4. Прерывания обрабатываются последовательно, поэтому идентификаторы устройств будут получены один за другим.

На рисунке ниже показан случай использования шины I2C для передачи идентификатора.

Рис. 1 - Платы соединений

Для платы 1 будет выполнен обработчик прерываний GPIO1, для платы 2- обработчик прерываний GPIO 2. Следовательно, вы знаете, какой запросить идентификатор устройства. Таким образом, идентификатор устройства будет получен по одному. Отсюда вы можете выяснить, как хранить эти идентификаторы. Я предлагаю использовать обычный массив:

struct u_id device_ids[2];

Вот псевдокод, показывающий, как заполнить этот массив:

void gpio1_isr(void)
{
    uint8_t i2c_buf[12];

    i2c_get(i2c_buf);
    memcpy(&device_ids[0], i2c_buf, 12);
}

void gpio2_isr(void)
{
    uint8_t i2c_buf[12];

    i2c_get(i2c_buf);
    memcpy(&device_ids[1], i2c_buf, 12);
}

(isr расшифровывается как служба обработки прерываний, которая аналогична обработчику прерываний).

Если вы уверены, что ваши две клиентские платы готовы к передаче I2C в то время, когда мастер-плата будет запрашивать у них идентификаторы, вы можете избавиться от 2 линий GPIO и просто использовать транзакции I2C от мастер-платы до клиентов в любое время.

Откройте блокнот и напишите это:

openocd -f interface/jlink.cfg -f board/olimex_stm32_h103.cfg -c "init" -c "stm32f1x.cpu mdw 0x1FFFF7E8 3" -c "exit"

@pause

Затем сохраните его как файл ".bat" и запустите!

Другие вопросы по тегам