I2C 事件中断有哪些

I2C 事件中断是指 I2C 硬件在发生特定事件时触发的中断。不同的 I2C 事件会影响通信过程,这些事件可以在 I2C 状态寄存器中监测。通常,这些事件与 I2C 总线的状态变化有关,例如生成 START、接收 ACK、完成数据传输等。以下是常见的 I2C 事件中断:

1. START 生成事件 (SB - Start Bit)

  • 触发时机: 当主机生成 START 信号时(即调用 I2C_GenerateSTART(ENABLE))。
  • 状态寄存器标志: SBSR1 状态寄存器中)。
  • 作用: 进入中断后,主机可以开始发送从设备地址。

2. ADDR 事件 (Address Sent/Matched)

  • 触发时机:
    • 主机发送从设备地址后,收到从机的应答信号(ACK)时。
    • 从机检测到主机发送了它的地址。
  • 状态寄存器标志: ADDRSR1 状态寄存器中)。
  • 作用: 主机或从机确定通信对象,接下来准备发送或接收数据。

3. STOP 生成事件 (STOPF - Stop Detection)

  • 触发时机: 主机在通信完成后发送 STOP 信号,或者从机检测到主机发送了 STOP 信号。
  • 状态寄存器标志: STOPFSR1 状态寄存器中)。
  • 作用: 通信结束,主机或从机处理停止信号,并清除标志位。

4. 传输缓冲区空 (TxE - Data Register Empty)

  • 触发时机: 当数据寄存器中的数据已经成功发送,并且硬件准备好接受新数据时。
  • 状态寄存器标志: TxESR1 状态寄存器中)。
  • 作用: 主机或从机可以继续发送下一个字节的数据。

5. 接收缓冲区非空 (RxNE - Data Register Not Empty)

  • 触发时机: 当一个字节的数据接收完成并存储在数据寄存器中时。
  • 状态寄存器标志: RxNESR1 状态寄存器中)。
  • 作用: 从寄存器中读取接收到的数据,继续通信。

6. 字节传输完成事件 (BTF - Byte Transfer Finished)

  • 触发时机:
    • 当主机发送或接收了一个字节的数据,并且该字节传输完成时。
    • 如果发送的是最后一个字节,主机会根据 BTF 标志来决定是否发送 STOP 信号。
  • 状态寄存器标志: BTFSR1 状态寄存器中)。
  • 作用: 表示当前字节传输已经完成,可以开始处理下一个字节。

7. 应答失败事件 (AF - Acknowledge Failure)

  • 触发时机: 主机在发送数据或地址后,未收到从机的应答(NACK)时。
  • 状态寄存器标志: AFSR1 状态寄存器中)。
  • 作用: 主机未收到应答信号,通信可能失败,主机需要处理错误。

8. 总线错误事件 (Bus Error - BER)

  • 触发时机: 当 I2C 总线在非预期的时间内检测到开始或停止条件时,会出现总线错误。
  • 状态寄存器标志: BERSR1 状态寄存器中)。
  • 作用: 通信出现严重错误,主机或从机需要停止通信并重新初始化总线。

9. 仲裁丢失事件 (ARLO - Arbitration Lost)

  • 触发时机: 在多主机的 I2C 通信中,如果一个主机在发送数据时发现其仲裁失败,意味着它失去了控制总线的权利。
  • 状态寄存器标志: ARLOSR1 状态寄存器中)。
  • 作用: 通信中断,主机需要重新尝试获取总线控制权。

10. 超时事件 (Timeout - TIMEOUT)

  • 触发时机: 当通信超时或出现长时间未响应的情况时。
  • 状态寄存器标志: TIMEOUTSR1 状态寄存器中)。
  • 作用: 通信超时,可能需要重新初始化或停止通信。

11. PEC 错误事件 (Packet Error Checking Error - PECERR)

  • 触发时机: 当启用 PEC(数据包错误检查)模式时,如果校验的 PEC 值不匹配,则会触发该事件。
  • 状态寄存器标志: PECERRSR1 状态寄存器中)。
  • 作用: 表示数据包错误,主机或从机需要重新传输数据。

if (event & (RB_I2C_BTF | RB_I2C_TxE)) 判断是否进入中断


小结:

以上这些事件中断通常是在 I2C 中断服务例程(ISR)中检测到的,开发者通过查询状态寄存器中的相应标志位来判断当前的总线状态,并采取相应的操作。不同的中断事件对应着 I2C 通信的不同阶段,帮助确保通信的正确性和完整性。

stm8si2c程序,调试通过 INTERRUPT_HANDLER(I2C_IRQHandler, 19) { /* In order to detect unexpected events during development, it is recommended to set a breakpoint on the following instruction. */ struct SCB_T *system=&system_process; unsigned char i,i2c_sr1,i2c_sr2,i2c_event,i2c__status=0,temp,sr1_analysis_int_resource[8],sr2_analysis_int_resource[8]; char i2c_interrupt_type=0,p;//在一次I2中断中,I2C中断中的中断标志位个数; disableInterrupts();//关总中断 i2c_sr1=I2C->SR1; p=I2C->SR3; i2c_sr2=I2C->SR2; //temp=I2C->SR3; //analysis interrupt resource in i2c->sr1 register sr1_analysis_int_resource[0]=i2c_sr1&I2C_SR1_SB; sr1_analysis_int_resource[1]=i2c_sr1&I2C_SR1_ADDR; sr1_analysis_int_resource[2]=i2c_sr1&I2C_SR1_BTF; sr1_analysis_int_resource[3]=i2c_sr1&I2C_SR1_ADD10; sr1_analysis_int_resource[4]=i2c_sr1&I2C_SR1_STOPF; // sr1_i2c__state[5]=i2c_state&((u8)I2C_SR1_BIT6); sr1_analysis_int_resource[6]=i2c_sr1&I2C_SR1_RXNE; sr1_analysis_int_resource[7]=i2c_sr1&I2C_SR1_TXE; //analysis interrupt resource in i2c->sr2 register sr2_analysis_int_resource[0]=i2c_sr2&I2C_SR2_BERR; sr2_analysis_int_resource[1]=i2c_sr2&I2C_SR2_ARLO; sr2_analysis_int_resource[2]=i2c_sr2&I2C_SR2_AF; sr2_analysis_int_resource[3]=i2c_sr2&I2C_SR2_OVR; sr2_analysis_int_resource[5]=i2c_sr2&I2C_SR2_WUFH; if(sr1_analysis_int_resource[0]==I2C_SR1_SB) {i2c__status=0x01;i2c_interrupt_type++;} if(sr1_analysis_int_resource[1]==I2C_SR1_ADDR) {i2c__status=0x02;i2c_interrupt_type++;} if(sr1_analysis_int_resource[2]==I2C_SR1_BTF) {i2c__status=0x03;i2c_interrupt_type++;} if(sr1_analysis_int_resource[3]==I2C_SR1_ADD10) {i2c__status=0x04;i2c_interrupt_type++;} if(sr1_analysis_int_resource[4]==I2C_SR1_STOPF) {i2c__status=0x05;i2c_interrupt_type++;} if(sr1_analysis_int_resource[6]==I2C_SR1_RXNE) {i2c__status=0x06;i2c_interrupt_type++;} if(sr1_analysis_int_resource[7]==I2C_SR1_TXE) {i2c__status=0x07;i2c_interrupt_type++;} if(sr2_analysis_int_resource[0]==I2C_SR2_BERR) {i2c__status=0x08;i2c_interrupt_type++;} if(sr2_analysis_int_resource[1]==I2C_SR2_ARLO) {i2c__status=0x09;i2c_interrupt_type++;} if(sr2_analysis_int_resource[2]==I2C_SR2_AF) {i2c__status=0x0a;i2c_interrupt_type++;} if(sr2_analysis_int_resource[3]==I2C_SR2_OVR) {i2c__status=0x0b;i2c_interrupt_type++;} if(sr2_analysis_int_resource[5]==I2C_SR2_WUFH) {i2c__status=0x0c;i2c_interrupt_type++;} if(i2c_interrupt_type>=2) /*there are more than one interrupt resource in the time*/ { if(i2c_interrupt_type==2) { if((sr1_analysis_int_resource[1]==I2C_SR1_ADDR)&&(sr1_analysis_int_resource[7]==I2C_SR1_TXE)) { I2C->DR=system->i2c.send_frame.data[system->i2c.send_frame.proc]; system->i2c.send_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x62; } else if((sr1_analysis_int_resource[7]==I2C_SR1_TXE)&&(sr1_analysis_int_resource[2]==I2C_SR1_BTF)) { system->i2c.send_frame.terminate=0; //set I2C transfer terminate bit; system->i2c.send_frame.mod=0; system->i2c.send_frame.write=0; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x64; } else if((sr1_analysis_int_resource[7]==I2C_SR1_TXE)&&(sr2_analysis_int_resource[2]==I2C_SR2_AF)) { I2C->CR2|=I2C_CR2_STOP; I2C->SR2&=(~I2C_SR2_AF);//clear AF bit; system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x64; } else { system->i2c.error=1; I2C_ITConfig(I2C_IT_EVT, DISABLE); system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x37; } } else { system->i2c.error=1; I2C_ITConfig(I2C_IT_EVT, DISABLE); system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x37; } } else { switch(i2c__status) { case I2C_SR1_SB_proc: //如果是发送模式 if(system->i2c.send_frame.mod==1)//说明本次中断之前是从模式,说明这是在从模式下发的起始位; { //EV5 p=I2C->SR1; I2C->DR=system->i2c.send_frame.add__L; //自动清除I2C_SR1_SB标志 system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x38; } else { if(system->i2c.rev_frame.mod==1) //说明本次中断之间是主模式,这次发的是重复起始位; { //EV6如果是接收模式 p=I2C->SR1; I2C->DR=system->i2c.rev_frame.add__L;//自动清除I2C_SR1_SB标志; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x51; } else { system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x36; } } break; case I2C_SR1_ADDR_proc: p=I2C->SR1; temp=I2C->SR3;//软件读取SR1寄存器后,对SR3寄存器的读操作将清除该位 temp&=(u8)I2C_SR3_TRA; I2C->CR2|=(u8)I2C_CR2_ACK;// 使能应答位 I2C->CR2&=(u8)(~I2C_CR2_POS);//设置接受到当字节应答 //如果是发送模式 if(system->i2c.send_frame.mod==1) { if(temp==(u8)I2C_SR3_TRA) {; } else { system->i2c.error=1; } } else { if(system->i2c.rev_frame.mod==1) { if(temp==0)//machine at a master-receive mod { system->i2c.rev_frame.proc=0; } else { system->i2c.error=1; } } else { system->i2c.error=1; } } system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x52; break; case I2C_SR1_RXNE_proc: if(system->i2c.rev_frame.proci2c.rev_frame.num-3)) { system->i2c.rev_frame.data[system->i2c.rev_frame.proc]=I2C->DR; system->i2c.rev_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x57; } else if(system->i2c.rev_frame.proc==(u8)(system->i2c.rev_frame.num-2)) { system->i2c.rev_frame.data[system->i2c.rev_frame.proc]=I2C->DR; system->i2c.rev_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x58; I2C->CR2&=(u8)(~I2C_CR2_ACK);//不返回应答 I2C->CR2|=I2C_CR2_STOP; //发停止位结束这次数据接收; } else if(system->i2c.rev_frame.proc>=(u8)(system->i2c.rev_frame.num-1)) { system->i2c.rev_frame.data[system->i2c.rev_frame.proc]=I2C->DR; system->i2c.rev_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x59; system->i2c.rev_frame.terminate=0; //set I2C transfer terminate bit; system->i2c.rev_frame.mod=0; system->i2c.rev_frame.read=0; } else { system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0xfb; } break; case I2C_SR1_TXE_proc: if(system->i2c.send_frame.proci2c.send_frame.num-1)) { I2C->DR=system->i2c.send_frame.data[system->i2c.send_frame.proc]; system->i2c.send_frame.proc++; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x61; } else if(system->i2c.send_frame.proc=(u8)(system->i2c.send_frame.num)) { I2C->CR2|=I2C_CR2_STOP; // 发停止位结束 这次数据接收; I2C_ITConfig(I2C_IT_BUF, DISABLE); system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x60; } else { system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0xfc; } break; case I2C_SR2_AF_proc: I2C->CR2|=I2C_CR2_STOP; I2C->SR2&=(~I2C_SR2_AF);//clear AF bit; system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0x63; break; default: system->i2c.error=1; system->i2c.debug.reserve[system->i2c.int_debug_count].type=0xfd; break; } } system->i2c.int_debug_count++; enableInterrupts();//开总中断 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值