I2C传输协议- Master-Transmitter/Receiver Protocol

本文详细介绍了I2C总线协议中的Master-Transmitter和Master-Receiver两种模式下的7bit与10bit地址传输协议。阐述了传输过程中START、STOP、RESTART信号的作用,以及数据传输中ACK/NACK信号的产生方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

在I2C虚拟项目中,只对DUT的master模式进行了验证,由于涉及不同模式/不同地址格式的读写传输,很容易混淆,故将master模式下的不同地址下的传输协议进行梳理。


1.基本概念

在描述传输协议之前,我们需要先知道transmitter和receiver,master和slave两组概念的区别。
Transmitter:指向总线发送数据的设备,它可以是向总线发起数据传输(称之为 master-transmitter),也可以是对master发送数据到总线后的响应(slave-transmitter);
Receiver:指从总线接收数据的设备,它可以是根据自身请求从总线上接收数据(master-receiver)或者是响应其他master的请求去接收数据(slave-receiver);
Master:指发起传输(START命令)、产生时钟信号和终止传输(STOP命令)的组件;
Slave:指被master寻址的设备。
比如DW_APB_I2C(DUT)想通过I2C总线发送一组数据并通过寻址找到设备A,A给出了ACK信号表明可以接收,那么这里DUT就是master transmitter,A就是slave receiver;比如DUT想要通过I2C总线读取一组数据,并传输了对应地址,B设备给出了ACK信号,这里DUT就是master-receiver,B设备就是slave-transmitter。

2.Master-Transmitter Protocol(写操作)

8bit字节格式传输,数据传输的字节数量没有限制。在master发送完地址位和读写位后或者发送完数据位后,slave receiver必须要回复ACK信号(SDA信号线拉低);当没有回复ACK信号时,那么master就会发出STOP信号中止传输,slave拉高SDA信号线(但不意味着最后一个字节必须是NACK。如果前一个信号是ACK,那为了产生STOP条件就需要拉高SDA,如果前一个是NACK,那么SDA继续保存为高)
特例:在Ultra-Fast 模式下,slave receiver会对来自master的地址字节和数据字节发送NACK。

2.1 7 bit地址

在这里插入图片描述
在7 bit地址传输中,START信号,STOP信号,地址字节和数据都由master发送到总线上,salve发送ACK信号,最后一个字节可以是NACK信号

2.2 10 bit地址

在这里插入图片描述
与7 bit地址传输格式类似,只不过需要两个字节传输地址,master产生START信号和STOP信号,地址字节和读写位以及数据,其中第一个地址字节的 前5位1111 0就是10 bit salve addressing的标志,低二位是10位地址的高二位,再加一个读写位构成一个byte,第二个地址字节是10位地址的低8位,slave发送ACK信号,最后一个字节可以是NACK信号。

3.Master-Receiver(读操作)

也是字节格式传输,与Master-Transmitter不同之处在于,数据接收的ACK/NACK信号是由master发出的,而不是slave。这与第一节所介绍的概念也一致,master总是控制着START、STOP信号以及地址字节的产生,那么第一个ACK信号就必定是slave发送的,表明其成功被寻址到。另外,最后一个字节必须回应NACK信号,使得slave释放SDA信号线,进而master才能拉高SDA信号产生STOP信号。

3.1 7 bit地址

在这里插入图片描述
在7 bit地址传输中,master产生START信号、STOP信号,地址字节的发送以及数据ACK/NACK信号的产生;slave则负责地址字节的ACK信号产生和数据的发送。

3.2 10 bit地址

在这里插入图片描述
10位地址的读操作稍微复杂一点,且需要注意的是,第一个地址字节的读写位并不是1(读),而是0(写),当按照写操作的传输格式发送完两个地址字节并且均有slave回应ACK后,master不想产生STOP信号释放总线,就会产生RESTART信号,接着再次发送第一个地址字节,并将读写位变为1(读),开启正常的读传输。slave发送地址字节的ACK信号和DATA发送。

总结

无论是读操作还是写操作,在非DATA传输阶段,master始终负责发送START(RESTART)、STOP、和地址字节,slave始终只负责发送ACK信号表明被寻址到;
变化的是DATA传输阶段写操作时DATA是由master发送,所以由slave发送ACK/NACK信号,读操作时DATA由slave发送,ACK/NACK信号由master产生;
写操作下由于是master发送数据,所以它控制着SDA信号线,slave最后一个确认位不影响其对SDA线的控制,它可以在这期间使得SDA信号线为高;读操作下由于是slave发送数据,slave控制着SDA信号线,如果最后一个确认位发送ACK(拉低SDA信号线),那么紧接着产生STOP信号需要拉高SDA信号线的条件没有指令可以操作完成,所以只能在确认位通过产生NACK来拉高SDA信号线

### MC32F7361 I2C Communication Code Example For the MC32F7361 microcontroller, implementing an I2C communication interface involves configuring and initializing the hardware peripherals properly to ensure reliable data transmission between master and slave devices. Below is a detailed example of how this can be achieved. #### Initialization Function The initialization function sets up the necessary parameters for I2C operation including clock speed, address mode, etc. ```c void I2C_Init(void) { // Enable GPIO and I2C peripheral clocks RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2Cx, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOx, ENABLE); // Configure SCL and SDA pins as alternate function open-drain outputs GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_PIN_SDA | GPIO_PIN_SCL; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOx, &GPIO_InitStruct); // Initialize I2C structure with desired settings I2C_InitTypeDef I2C_InitStruct; I2C_InitStruct.I2C_ClockSpeed = 100000; // Standard Mode 100kHz I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_OwnAddress1 = OWN_ADDRESS; I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Init(I2Cx, &I2C_InitStruct); // Enable I2C Peripheral I2C_Cmd(I2Cx, ENABLE); } ``` #### Write Data Function This function sends data over the I2C bus from the master device to the slave device specified by its address. ```c uint8_t I2C_WriteData(uint8_t* pData, uint16_t length, uint8_t slaveAddr) { if (!length || !pData) return ERROR; // Generate START condition I2C_GenerateSTART(I2Cx, ENABLE); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Send Slave Address for write I2C_Send7bitAddress(I2Cx, slaveAddr, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // Transmit bytes one at a time until all are sent for(int i=0;i<length;i++) { I2C_SendData(I2Cx, *(pData+i)); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); } // Generate STOP Condition after sending last byte I2C_GenerateSTOP(I2Cx, ENABLE); return SUCCESS; } ``` #### Read Data Function To read data back from a connected sensor or another module via I2C protocol. ```c uint8_t I2C_ReadData(uint8_t* pBuffer, uint16_t length, uint8_t slaveAddr) { if (!length || !pBuffer) return ERROR; // Start condition generation followed by addressing the target node I2C_GenerateSTART(I2Cx, ENABLE); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2Cx, slaveAddr, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // Switch direction to receive mode before issuing repeated start I2C_RepeatedStart(I2Cx); I2C_Send7bitAddress(I2Cx, slaveAddr, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // Receive multiple bytes into buffer depending on requested count for(int i=0 ;i<(int)(length-1);i++) { *pBuffer++ = I2C_ReceiveData(I2Cx); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); } // Last byte should not acknowledge receipt so that sender knows end has been reached I2C_AcknowledgeConfig(I2Cx, DISABLE); *pBuffer = I2C_ReceiveData(I2Cx); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); // Re-enable acknowledgment and generate stop signal upon completion I2C_AcknowledgeConfig(I2Cx, ENABLE); I2C_GenerateSTOP(I2Cx, ENABLE); return SUCCESS; } ``` These functions provide basic building blocks for establishing robust two-way communications using the I2C standard on the MC32F7361 platform[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ann_xia66

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值