STM32学习-18-[I2C]读数据
主要实现一个函数

数据读取的流程

从机向主机发送,有效数据后面要加ACK表示应答,最后一帧后面加NAK表示数据发送完成
发送起始位和地址

先向START寄存器写1
然后确定状态寄存器的SB

先清空AF标志位
写入要发送的数据
确定寄存器的值
最后清空ADDR,使用固定的步骤,读取SR1和SR2
如何发送ACK和NAK

图中被影响的字节分别是字节2和字节3,是正在被接收的字节别作用
如何发送停止位

直接写STOP寄存器就好
图中字节一发送完成后就会发送停止位
Size = 1

Size = 2

Size > 2

完整代码实现
//
// I2Cx:目标I2C外设
// Addr:从机地址
// pBuffer:接收缓存区
// Size:接收的字节大小
//
int My_I2C_ReceiveBytes(I2CType *I2Cx, uint8_t Addr, uint8_t *pBuffer, uint16_t Size){
// 发送起始位
I2C_GenerateSTART(I2Cx, ENABLE);
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET);
// 寻址
I2C_ClearFlag(I2Cx, I2C_FLAG_AF); // 清楚AF寄存器
// 发送地址与RW#
I2C_SendData(I2Cx, Addr | 0xfe);
// 等待ACK回应
while(1){
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == SET) break; // 收到ACK
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF) == SET){
I2C_GenerateSTOP(I2Cx, ENABLE); // 发送停止位
return -1; // 寻址失败
}
}
// 接收数据
if(Size == 1){
// 清除ADDR
I2C_ReadRegister(I2Cx, I2C_Register_SR1);
I2C_ReadRegister(I2Cx, I2C_Register_SR2);
// 向ACK写0
I2C_AcknowledgeConfig(I2Cx, DISABLE);
// 发送停止位
I2C_GenerateSTOP(I2Cx, ENABLE);
// 等待RxNE置位
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET);
// 读取数据
pBuffer[0] = I2C_ReceiveData(I2Cx);
}
else if(Size == 2){
// 清除ADDR
I2C_ReadRegister(I2Cx, I2C_Register_SR1);
I2C_ReadRegister(I2Cx, I2C_Register_SR2);
// 向ACK写1
I2C_AcknowledgeConfig(I2Cx, ENABLE);
// 等待RxNE置位
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET);
// 读取第一个数据
pBuffer[0] = I2C_ReceiveData(I2Cx);
// 向ACK写0
I2C_AcknowledgeConfig(I2Cx, DISABLE);
// 发送停止位
I2C_GenerateSTOP(I2Cx, ENABLE);
// 等待RxNE置位
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET);
// 读取第二个数据
pBuffer[1] = I2C_ReceiveData(I2Cx);
}
else{
// 清除ADDR
I2C_ReadRegister(I2Cx, I2C_Register_SR1);
I2C_ReadRegister(I2Cx, I2C_Register_SR2);
// 向ACK写1
I2C_AcknowledgeConfig(I2Cx, ENABLE);
for(int i = 0; i < Size - 1; ++i){
// 等待RxNE置位
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET);
// 读取数据
pBuffer[i] = I2C_ReceiveData(I2Cx);
}
// 向ACK写0
I2C_AcknowledgeConfig(I2Cx, DISABLE);
// 发送停止位
I2C_GenerateSTOP(I2Cx, ENABLE);
// 等待RxNE置位
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET);
// 读取最后一个数据
pBuffer[Size - 1] = I2C_ReceiveData(I2Cx);
}
}

浙公网安备 33010602011771号