STM32学习-17-[I2C]写数据

I2C模块的内部结构框图

image

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

数据发送过程的简介

image

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

等待总线空闲

先准备实现一个函数功能
image

image

发送起始位

image

发送地址

image

为什么要使用0xfe
image

image

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

发送数据

image

image

发送停止位

image

完成过程

//
// 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;	// 成功
}
posted @ 2026-08-31 22:08  灵垚克府  阅读(12)  评论(0)    收藏  举报