如何找到STM32F103RET的设备ID
How to find the device id of a STM32F103RET
我被告知每个 STM32F103RET 设备都带有一个唯一的设备 id.If 那么检索 ID 的过程是什么?我是 运行 一个系统,其中我与多个 STM 板进行通信.为了区分每个 STM 板,我可以使用这个唯一的 ID。
谢谢
您可以在 STM32F103 Reference Manual 中找到此信息。更具体地说,您想阅读章节 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;
};
如何阅读它取决于您(取决于您使用的框架,例如在 libopencm3 you have MMIO32 macro 中)。在一般情况下,我会做这样的事情:
#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);
}
您还需要一个函数来比较两个 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;
}
你可以这样使用它:
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;
}
更新
据我了解你的情况:
- 你的每个板子都应该在主板上发送一些 interrupt to your master board (more specifically, to GPIO 引脚。
- 一旦主板接收到中断,它会启动传输(请求)到中断来自的板(可能使用I2C, SPI, UART或类似的东西在板之间进行通信)。
- 然后客户端板用它的设备 ID 响应。
- 中断是按顺序处理的,所以设备ID会一个一个获取。
下图说明了使用 I2C 总线进行 ID 传输的情况。
对于板 1,您将执行 GPIO1 中断处理程序,对于板 2 - GPIO 2 中断处理程序。因此,您知道要向哪一个请求设备 ID。所以设备ID将一次获得一个。从这里您可以了解如何存储这些 ID。我建议使用常规数组:
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
代表Interrupt Service Routine,与中断处理程序相同)。
如果您确定您的两个客户端板已准备好在主板要求它们提供 ID 时进行 I2C 传输,您可以去掉 2 条 GPIO 线,只使用从主板到随时随地的客户。
打开记事本并写下:
openocd -f interface/jlink.cfg -f board/olimex_stm32_h103.cfg -c "init" -c "stm32f1x.cpu mdw 0x1FFFF7E8 3" -c "exit"
@pause
然后将其保存为 ".bat" 文件然后 运行 它!
我被告知每个 STM32F103RET 设备都带有一个唯一的设备 id.If 那么检索 ID 的过程是什么?我是 运行 一个系统,其中我与多个 STM 板进行通信.为了区分每个 STM 板,我可以使用这个唯一的 ID。 谢谢
您可以在 STM32F103 Reference Manual 中找到此信息。更具体地说,您想阅读章节 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;
};
如何阅读它取决于您(取决于您使用的框架,例如在 libopencm3 you have MMIO32 macro 中)。在一般情况下,我会做这样的事情:
#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);
}
您还需要一个函数来比较两个 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;
}
你可以这样使用它:
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;
}
更新
据我了解你的情况:
- 你的每个板子都应该在主板上发送一些 interrupt to your master board (more specifically, to GPIO 引脚。
- 一旦主板接收到中断,它会启动传输(请求)到中断来自的板(可能使用I2C, SPI, UART或类似的东西在板之间进行通信)。
- 然后客户端板用它的设备 ID 响应。
- 中断是按顺序处理的,所以设备ID会一个一个获取。
下图说明了使用 I2C 总线进行 ID 传输的情况。
对于板 1,您将执行 GPIO1 中断处理程序,对于板 2 - GPIO 2 中断处理程序。因此,您知道要向哪一个请求设备 ID。所以设备ID将一次获得一个。从这里您可以了解如何存储这些 ID。我建议使用常规数组:
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
代表Interrupt Service Routine,与中断处理程序相同)。
如果您确定您的两个客户端板已准备好在主板要求它们提供 ID 时进行 I2C 传输,您可以去掉 2 条 GPIO 线,只使用从主板到随时随地的客户。
打开记事本并写下:
openocd -f interface/jlink.cfg -f board/olimex_stm32_h103.cfg -c "init" -c "stm32f1x.cpu mdw 0x1FFFF7E8 3" -c "exit"
@pause
然后将其保存为 ".bat" 文件然后 运行 它!