Как найти идентификатор устройства 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;
}
ОБНОВИТЬ
Как я понимаю вашу ситуацию
- Каждая из ваших плат должна посылать некоторые прерывания на вашу основную плату (точнее, на вывод GPIO на основной плате).
- Как только ведущая плата получает прерывание, она инициирует передачу (запрос) на плату, откуда пришло прерывание (возможно, используя I2C, SPI, UART или что-то подобное для связи между платами).
- Затем клиентская плата отвечает своим идентификатором устройства.
- Прерывания обрабатываются последовательно, поэтому идентификаторы устройств будут получены один за другим.
На рисунке ниже показан случай использования шины I2C для передачи идентификатора.
Для платы 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" и запустите!