STM32学习-17-[I2C]写数据
I2C模块的内部结构框图

其中绿色的的是发送数据寄存器 接收数据寄存器 和 移位寄存器
粉红色的为状态寄存器SR1和SR2
橙色的是配置的一些参数
数据发送过程的简介

- 发送起始位的时候只需要向橙色的START寄存器写1即可发送起始信号
- 发送设备地址和方向和普通的数据没什么区别,写入发送数据寄存器即可,通过移位寄存器就可以完成发送
- 等待ACK可以查询上面的状态寄存器
- 发送数据的流程和发送地址的时候是一样的包括等待ack
- 停止位写STOP寄存器里面写1即可
等待总线空闲
先准备实现一个函数功能


发送起始位

发送地址

为什么要使用
0xfe

清空ADDR比较特殊,选读SR1后读SR2,这是规定
发送数据


发送停止位

完成过程
//
// I2Cx:发送的I2C端口
// Addr:地址
// pData:即将发送的数据
// Size:发送的数据大小
//
int My_I2C_SendBytes(I2CType *I2Cx, uint8_t Addr, uint8_t *pData, uint16_t Size){
// 等待总线空闲
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) == SET);
// 发送起始位
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; // 寻址失败
}
}
// 清除ADDR寄存器
I2C_ReadRegister(I2Cx, I2C_Register_SR1);
I2C_ReadRegister(I2Cx, I2C_Register_SR2);
// 发送数据
for(uint16_t i = 0; i < Size; ++i){
while(1){
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF) == SET){ // 上一个数据被拒绝接收
I2C_GenerateSTOP(I2Cx, ENABLE);
return -2;
}
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_TXE) == SET){ // 发送数据寄存器为空
break;
}
}
I2C_SendData(I2Cx, pData[i]); // 发送数据
}
while(1){
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF) == SET){ // 上一个数据被拒绝接收
I2C_GenerateSTOP(I2Cx, ENABLE);
return -2;
}
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == SET){ // 数据发送完成
break;
}
}
// 发送停止位
I2C_GenerateSTOP(I2Cx, ENABLE);
return 0; // 成功
}


浙公网安备 33010602011771号