如何查找STM32F103RET的设备ID

bis*_*nux 2 stm32 libopencm3

我被告知每个STM32F103RET设备都带有一个唯一的设备ID.如果检索ID的过程是什么?我正在运行一个系统,其中我与多个STM borads进行通信.为了区分每个STM板,我可以使用这个唯一的Id.谢谢

Sam*_*nko 6

您可以在STM32F103参考手册中找到此信息.更具体地说,您想要阅读第30.2唯一设备ID寄存器(96位).

因此,您的设备ID包含在只读寄存器中,称为U_ID.该寄存器地址是0x1ffff7e8.它是96位长,因此可以使用3个读取操作(例如)读取每个32位长.当然你不能把它放在一个变量中.所以你应该想出一些将它存储在内存中的方法.它可以是数组,也可以是结构等.

我可能会使用结构来实现此目的,使用参考手册中描述的偏移量:

#include <stdint.h>

struct u_id {
    uint16_t off0;
    uint16_t off2;
    uint32_t off4;
    uint32_t off8;
};
Run Code Online (Sandbox Code Playgroud)

如何阅读它取决于您(取决于您使用的框架,例如在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);
}
Run Code Online (Sandbox Code Playgroud)

您还需要一个功能来比较两个ID.您可以使用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;
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

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;
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

据我了解你的情况:

  1. 每个电路板都应该向主板发送一些中断(更具体地说,发送到主板上的GPIO引脚).
  2. 一旦主板接收到中断,它就会启动传输(请求)到中断来自的板(可能使用I2C,SPI,UART或类似的东西在板之间进行通信).
  3. 然后客户端板响应它的设备ID.
  4. 中断按顺序处理,因此将逐个获取设备ID.

下图说明了用于ID传输的I2C总线的情况.

图1  - 板连接

对于板1,您将执行GPIO1中断处理程序,用于板2 - GPIO 2中断处理程序.因此,您知道哪一个要求设备ID.因此,将一次获得一个设备ID.从这里你可以弄清楚如何存储这些ID.我建议使用常规数组:

struct u_id device_ids[2];
Run Code Online (Sandbox Code Playgroud)

这是伪代码,显示如何填充此数组:

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);
}
Run Code Online (Sandbox Code Playgroud)

(isr代表中断服务程序,与中断处理程序相同).

如果您确定您的两个客户端板已经准备好进行I2C传输,而主板会要求它们提供ID,那么您可以摆脱2条GPIO线路,只需使用主板上的I2C事务处理即可.