嵌入式开发原创教程嵌入式入门 05
I2C 与 SPI 传感器接入:读设备 ID 和完整寄存器
用两个最小实验理解 I2C 地址、寄存器读取、SPI 模式、片选和错误恢复。

实验目标
- 用 I2C 读取传感器设备 ID;
- 用 SPI 读取一个寄存器;
- 知道地址、模式、片选和超时分别怎么检查;
- 在通信失败时能定位到硬件或软件层。
一、I2C 最小实验
假设传感器 7 位地址为 0x68,设备 ID 寄存器为 0x75。
uint8_t who_am_i = 0U;
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read(&hi2c1,
(uint16_t)(0x68U << 1),
0x75U,
I2C_MEMADD_SIZE_8BIT,
&who_am_i,
1U,
100U);
if (status == HAL_OK)
{
HAL_UART_Transmit(&huart2, (uint8_t *)"I2C OK\r\n", 8, 100);
}
else
{
HAL_UART_Transmit(&huart2, (uint8_t *)"I2C FAIL\r\n", 10, 100);
}I2C 检查顺序
- SDA/SCL 是否接反;
- 是否有上拉电阻;
- 设备地址是否左移;
- 寄存器地址是 8 位还是 16 位;
- 总线是否被拉低;
- 设备供电和地是否正常。
二、SPI 最小实验
假设从机设备 ID 寄存器为 0x75,读取时最高位置 1。
uint8_t tx[2] = { 0xF5U, 0x00U };
uint8_t rx[2] = { 0U, 0U };
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(&hspi1,
tx,
rx,
2U,
100U);
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
if (status == HAL_OK)
{
uint8_t device_id = rx[1];
(void)device_id;
}SPI 检查顺序
- CPOL 和 CPHA 是否与从机一致;
- 片选是否低有效;
- MISO/MOSI 是否接反;
- 时钟频率是否超过从机上限;
- 数据位宽是否为 8 位;
- 读写命令的最高位和地址长度是否匹配。
三、错误恢复
通信失败时不要无限重试。建议:
for (uint8_t retry = 0U; retry < 3U; retry++)
{
if (sensor_read_once() == HAL_OK)
{
break;
}
HAL_Delay(10);
}连续失败后记录错误码,不要在主循环里疯狂打印。
四、实验顺序
- 先只读设备 ID;
- 再读一个配置寄存器;
- 写入一个安全配置;
- 读回确认;
- 最后读取连续数据。
参考资料:


