iic
最近在写DS3231时钟芯片的驱动,这个芯片使用IIC进行通讯,以前没有用过IIC模块,照着教材和示例程序写程序后发现各种问题。没办法,还是官方数据手册靠谱,遂把相应部分又翻译了一遍。果然发现示例程序纯粹就是个玩具,一点用都没有。。。
第15章 集成电路总线(IICV3)
译者注:译者博客(http://blog.csdn.net/lin_strong),转载请保留这条。此为 MC9S12XEP100RMV1芯片手册的第15章内容,仅供学习交流使用,请勿用于商业用途。
介绍
集成IC总线(IIC)是一个双线双向串行总线,它提供设备间简单高效的数据交换。由于只需要两条线,IIC总线大大简化了设备间的连接,另外,它还不需要地址译码器。
这个总线很适合需要在大量设备间进行短距离断续通讯的情景。它具有很高的扩展性,能够灵活地在总线上添加设备进行系统功能扩展。
该接口被设计为在最大总线负载和定时下以最高100 kbps运行。设备能够运行在更高的波特率上,最高为 总线时钟/20。最大通讯距离和可以连接的设备数受限于总线电容,电容值最大400pF。
特性
IIC模块有以下关键特性:
- 兼容I2C总线标准
- 支持多主机
- 可软件配置的256种串行时钟频率
- 软件可控的应答位
- 中断驱动的多数据字节传送
- 仲裁丢失时触发中断,同时自动从主机切换为从机。
- 主叫地址识别中断
- 可以生成/探测 启动信号和停止信号
- 可以生成重复启动信号
- 可以生成与探测应答位
- 可以探测总线忙碌状态
- 通用呼叫地址探测
- 兼容10bit地址
运行模式
IIC模块在 普通、特殊和模拟 模式下运作方式相同。它有两个低功耗模式:等待模式和停止模式。
框图
IIC模块的框图如图1。
图 1.IIC模块框图
外部信号引脚描述
IICV3模块有两个外部引脚。
IIC_SCL — 串行时钟线 引脚
这是模块的双向串行时钟线(SCL),兼容IIC总线规范。
IIC_SDA — 串行数据线 引脚
这是模块的双向串行数据线(SDA),兼容IIC总线规范。
地址映射与寄存器定义
这部分提供了IIC模块的所有地址和寄存器的详细描述。
寄存器描述
这部分以地址顺序描述寄存器。每个描述都有一个标准的寄存器框图以及对应的数字。寄存器位以及字段功能的细节描述跟在寄存器图之后,按照位顺序。
图 2.IIC寄存器总结
IIC地址寄存器(IBAD)
图 3.IIC总线地址寄存器(IBAD)
任何时刻都可读写。
如果当前为从机,当主叫地址与寄存器中的值匹配时,IIC模块会自动答复。注意,这个地址并不是当自己为主机时,在发送地址时会被发送的那个。
表 2. IBAD字段描述
字段 | 描述 |
---|---|
7:1 ADR[7:1] |
从机地址 — Bit 1到7包含IIC总线模块使用的从机地址。当总线上地址匹配时IIC默认为从机模式。 |
0 保留 |
保留 — IBAD的Bit 0 预留作未来使用。读取时总是0。 |
IIC分频寄存器(IBFD)
图 4.IIC总线分频寄存器
任何时刻都可读写。
表 3. IBFD字段描述
字段 | 描述 |
---|---|
7:0 IBC[7:0] |
I 总线时钟率 — 这个字段用于预分频时钟以配置比特率。位时钟生成器实现为3个子部分: 预分频器 — IBC7:6、预分频移位寄存器 — IBC5:3用于选择预分频器、IBC2-0 选择移位寄存器的tap点。不同IBC配置所对应的tap和预分频值如表4所示。 |
表 4. I-总线 tap和预分频值
表 5. 预分频器编码
表 6.乘数因子
从SCL下降沿到第一个tap(Tap[1])的时钟数由表5中的scl2tap决定,之后所有的tap点由 2IBC5-3分离,如表5中的tap2tap。SCL Tap被用于生成SCL周期,SDA Tap用于确定从SCL下降沿到SDA变化的延迟,及SDA保持时间(hold time)。
IBC7-6 决定乘数因子 MUL。MUL的值如表6所示。
图 5.SCL分频器和SDA保持
用于生成分频值的公式为:
SDA保持延时时间等于cpu时钟周期乘以表7中所示的SDA保持值。用于生成SDA保持值的公式为:
用于生成启动条件(start condition)和停止条件(start condition)的SCL保持值的公式为:
- 注意:
- 在更高的内部总线时钟频率下,主机的sql分频周期可能会延长。当内部总线周期等于一个pad延时时就会发生。SCL输入被用于多主机下的时钟仲裁。因此每次SCL边沿被内部驱动后,在达到pad电平前会额外计算一个总线周期,以支持下一次反转。这在MUL=1并且IBC[7:0] = 0x00到0x0F时会起作用,见表7。
表 7.IIC分频与保持值
IIC控制寄存器(IBCR)
任何时刻都可读写。
表 8. IBCR字段描述
字段 | 描述 |
---|---|
7 IBEN |
I-总线 使能 — 这个字段控制IIC总线模块的软重置。 0 模块被重置并禁用。这是上电重置后的状态。此时,接口保持重置状态,但可以访问寄存器。 1 IIC总线模块被使能。这个位必须在使用其他IBCR位之前置位。 如果IIC总线模块在直接传输的过程中被使能,会发生如下事情:从机模式会忽略当前总线上的传输并在探测到下一个启动信号时开始运行。主机模式不会意识到总线正忙,因此如果这时发起启动的话,当前的总线可能会发生冲突并出错。这最终会导致当前的主线主机与IIC总线模块之一丢失仲裁,然后总线就会恢复正常。 |
6 IBIE |
I-总线 中断使能 0 禁用来自IIC总线模块的中断。注意,挂起的标志位还是需要手动清零的。 1 使能来自IIC总线模块的中断。IIC总线的发生中断的同时,状态寄存器中的IBIF也会一起置位。 |
5 MS/SL |
主机/从机模式选择位 — 重置后,这个位为0。当这个位从0变为1时,会在总线上产生一个启动信号,然后就选择了主机模式。当这个位从1变为0时,会生成一个停止信号,然后运行模式就从从机变为主机。停止信号只有在IBIF置位时才会生成。当主机丢失仲裁时,MS/SL会在不生成停止信号的情况下清零。 0 从机模式 1 主机模式 |
4 Tx/Rx |
发送/接收模式选择位 — 这个位选择主机与从机传输的方向。当作为从机被呼叫时,这个位应该由软件根据状态寄存器中的SRW位进行设置。在主机模式下,这个位应该根据传输需求进行设置。因此,在寻址周期,这个位应该总是1。 0 接收 1 发送 |
3 TXAK |
应答位发送使能 — 这个位指定了主机/从机接收器在数据应答周期时驱动到SDA上的值。只要模块启用了,不管TXAK是什么值,IIC模块总会应答匹配的呼叫地址。注意,写到这个bit的值只在IIC总线为接收器时才有用(即Tx/Rx=0时)。 0 在接收到一个字节数据后的第9个时钟位,会发送一个应答信号。 1 不会发送应答信号(即,应答位 = 1) |
2 RSTA |
重复启动 — 如果模式是当前的总线主机,向这个位写入1会在总线上生成一个重复启动信号。这个位读出来总是0。如果在错误的时刻试图重复启动,比如总线是由其他主机占用,会导致丢失仲裁。 1 生成重复启动信号 |
1 RESERVED |
保留 — IBCR的Bit 1预留用作以后使用。这个位读出来总是0。 |
0 IBSWai |
I-总线 接口在暂停模式下停止 0 IIC总线模块时钟正常运行。 1 在等待模式下停止IIC总线模块的时钟生成。 |
当执行CPU WAI指令时会进入等待模式。如果这时IBSWAI位为1,IIC模块的所有内部时钟会停止,当前的进行中的传输将停止。如果CPU由非来自IIC模块的信号源唤醒,时钟将会重启,如果正在传输的话,IIC将恢复之前的状态继续进行传输。当内部时钟停止时,IIC模块不可能唤醒CPU。
如果当执行WAI指令时IBSWAI位为0,IIC内部时钟和接口会保持活跃,继续完成当前的操作。甚至可以配置IIC模块使其通过当前操作产生的中断来唤醒CPU。详见IBSR中的IBIF位与IBCR中的IBIR位。
IIC状态寄存器(IBSR)
图 7.IIC总线状态寄存器(IBSR)
除了bit 1(IBIF)和bit 4(IBAL)可用软件清零外,状态寄存器的其他位都是只读的。
字段 | 描述 |
---|---|
7 TCF |
数据传输位 — 当一个数据字节正在传输时,这个位为0。它会由一个数据字节传输的第9个时钟的下降沿置位。注意,这个位只在一次数据传输的过程中或者刚刚结束的瞬间有效。 0 传输中 1 传输完成 |
6 IAAS |
被作为从机呼叫 — 当自己的地址(I-总线地址寄存器)与主叫地址匹配,或者当GCEN为1时收到了通用主叫地址,这个位会被置位。如果IBIE为1,置位时会触发中断。然后CPU需要检测SRW位并相应地设置Tx/Rx。写I-总线控制寄存器会清零这个位。 0 未被寻址 1 被呼叫为从机 |
5 IBB |
总线忙 0 这个位指示总线的状态。当探测到启动信号,IBB被置位。如果探测到停止信号,IBB被清零,同时总线进入空闲状态。 1 总线正忙 |
4 IBAL |
仲裁丢失 — 仲裁丢失位(IBAL)会在仲裁失败时由硬件置位。仲裁会在以下情况丢失: 1. 当主机在寻址或者数据传输周期中想驱动SDA为1却采样到0。 2. 当主机在数据接收周期的应答位时想驱动SDA为1却采样到0。 3.当总线正忙时试图发出启动信号。 4.在从机模式下试图重复启动。 5.当主机检测到非主动发出的停止信号。 这个位必须由软件清零,通过写1来清零。写入0没有任何作用。 |
3 RESERVED |
保留 — IBSR的Bit 3预留用作以后使用。这个位读出来总是0。 |
2 SRW |
从机 读/写 — 当IAAS为1时,这个位指示由主机发送来的主叫地址中的R/W命令位的值 只有当处于从机模式时收到了匹配的主叫地址并且没有发起其他传输时这个位才有效。 通过检查这个位,CPU可以根据主机的命令选择从机的传输/接收模式。 0 从机接收,主机向从机发送数据 1 从机传输,主机从主机读取数据 |
1 IBIF |
I-总线 中断 — IBIF位会在发生以下情况时置位: 1. 仲裁丢失(IBAL位置位) 2.数据传输完成(TCF位置位) 3. 被作为从机寻址(IAAS位置位) 如果IBIE位被置位,会引发一次处理器中断请求。这个位必须由软件清零,写入1清零。写入0没有用。 |
0 RXAK |
接收应答 — 一次总线周期的应答位的SDA值。如果接收应答位(RXAK)为0,表明在总线上传输完8位数据后收到了应答信号。如果RXAK为1,说明在第9个时钟没有应答信号。 0 接收到应答 1 没有接收到应答 |
IIC数据I/O寄存器(IBDR)
图 8. IIC总线数据I/O寄存器(IBDR)
在主机传输模式下,向IBDR写入数据会发起一次数据传输。最高位会先传输。在主机接收模式下,读这个寄存器会启动下一次数据接收。从机模式下,在探测到主机的呼叫后,就可以使用同样的功能。注意,IBCR的Tx/Rx位必须正确地反映主/从模式下想要的传输方向。比如,如果IIC被配置为主机传输,但其实想要的是主机接收,那读取IBDR并不会启动接收。
当IIC被配置为主机接收或者从机接收时,读取IBDR读取IBDR将返回上一个接收到的字节。IBDR并不会反映在IIC总线上传输的每一个字节,软件也无法通过回读IBDR来验证刚写入的字节。
在主机传输模式下,断言MS/SL后,首个写入IBDR的字节用于传输地址,其应该包含主叫地址(在D7:D1上)以及R/W位(在D0上,1为读)。
IIC控制寄存器2(IBCR2)
图 9. IIC控制寄存器2(IBCR2)
这个寄存器包含在通用呼叫以及10bit地址中使用的变量。
任何时刻都可读写。
字段 | 描述 |
---|---|
7 GCEN |
通用呼叫使能 0 禁用通用呼叫。模块不会接受任何通用呼叫数据和寻址。 1 使能通用呼叫。它表明模块可以接收地址和任何数据。 |
6 ADTYPE |
地址类型 — 这个位选择地址长度。这变量必须在IIC进入从机模式前被正确地配置。 0 7位地址 1 0位地址 |
5,4,3 RESERVED |
保留 — IBCR2的Bit 5,4,3预留用作以后使用。这个位读出来总是0。 |
2:0 ADR[10:8] |
从机地址[10:8] — 如果地址类型被断言(ADTYPE=1),这3个位代表了10位地址的高3位。 |
功能描述
这个部分提供了IICV3完整的功能描述。
I-总线 协议
IIC总线系统使用一条串行数据线(SDA)和一套串行时钟线来传输数据。所有连接到上面的设备必须有开漏输出。两条线上都接有外部上拉电阻,采用”与”逻辑。这些电阻的值依赖于系统。
通常,一个标准的通信包含四个部分:启动信号、从机地址传输、数据传输 和 停止信号,如图10所示。后面的部分会简短地描述它们。
图 10.IIC总线传输信号
启动信号
当总线空闲,即没有主机正占用总线(SCL和SDA线都处于逻辑高位)时,主机可以通过发送一个启动信号来发起通信。如图11所示,启动信号定义为,当SCL为高时SDA上从高变到低。这个信号指示一次新的数据传输的开始(每次数据传输都可以包含数个数据字节)并让所有从机脱离空闲状态。
图 11.起始和停止条件
从机地址传输
主机在启动信号后的首个数据传输为从机地址传输。这是个7位的主叫地址以及一个1位R/W位。R/W位告知从机想要的数据传输方向。
1 = 读传输,从机传输数据给主机
0 = 写传输,主机传输数据给从机
如果主叫地址是10位的,另一个字节跟在首个字节后传输。只有与主机传输的主叫地址匹配的从机会进行答复,通过发回一个应答位。这通过在第9个时钟拉低SDA来实现(见图10)。
系统中不能有地址相同的从机。如果IIC模块是主机,它绝对不能传输与自己的从机地址相同的地址。IIC模块不能同时作为主机和从机。然而,如果在地址周期间丢失了仲裁,IIC模块将切换到从机模式并正确地运行,即使它正被另一个主机呼叫。
数据传输
只要成功地寻址到了从机,就可以以R/W位指定的方向进行连续的字节传输。
所有在地址传输之后传输都被认为是数据传输,即使它们携带了从机设备的子地址信息。
每次数据字节的传输都是8位长度的。数据线只可以在SCL为低位时变化,在SCL为高位时数据线必须保持稳定,如图10。每个数据位都对应SCL上一个时钟脉冲,先传输MSB。每个数据字节后面都跟着一个应答位,应答位由接收设备通过在第9个时钟拉低SDA来应答。所以一次完整的数据字节传输需要9个时钟脉冲。
如果从机接收器不应答主机,从机必须释放SDA线使其保持在高位。然后主机可以生成一个停止信号以抛弃数据传输或者一个启动信号(重新启动)以开始新的一次呼号。
如果主机接收器在一个字节传输后不应答从机发送器的话,就是对从机说“这是最后一个字节”,所以从机应该释放SDA线以便主机能够产生停止信号或者启动信号。注意,为了正确地释放总线,在主机不应答之后,从机必须立即切换到接收器,然后必须虚读一次IBDR。
停止信号
主机可以通过生成停止信号以释放总线来终止通信。但是,主机也可以直接生成启动信号并跟着一个主叫命令而不用先生成停止信号。这叫做重复启动。停止信号定义为当SCL在逻辑1时,SDA上从低到高的转换(见图11)。
即使从机已经进行了应答,主机仍然可以生成停止信号,这样从机必须释放总线。
重复启动信号
如图10中所示,重复启动信号就是不先生成停止信号来终止通信就直接生成启动信号。这被主机用来在不释放总线的情况下与另一个从机通信或者与同个从机以不同的模式(发/收模式)通信。
仲裁过程
集成IC总线是一个真正的多主机总线,它允许连接多个主机。如果两个或者多个主机同时试图控制总线,时钟同步过程会确定总线时钟,低位(注:即逻辑低电平)时间等于主机间最长的时钟低位时间,而高位时间等于最短的那个。进行竞争的主机的优先级由数据仲裁过程确定,当一个主机发送逻辑1时另一个主机却在发送逻辑0,它会丢失仲裁。丢失仲裁的主机会立即切换到从机接收模式并停止驱动SDA输出。这种情况下,主机到从机的模式切换不会生成停止信号。同时硬件会置位状态位以通知丢失了仲裁。
时钟同步
因为在SCL线上是”与”逻辑,SCL线上高到低的变化会影响到所有连接到总线上的设备。一旦设备时钟变为低位,设备开始计数低位时间,它会维持SCL线的低位直到到了时钟高位状态。但是,这个设备时钟从低到高的转变可能不会改变SCL线的状态,因为可能另一个设备的时钟还在低位。因此,同步时钟SCL由拥有最长低位时间的设备保持在低位。有较短低位时间的设备在这段时间进入高等待状态(见图12)。当所有相关设备都计数完成低位时间,同步时钟SCL线被释放并被拉高。然后所有设备就一起开始计数高位时间。首个计数完成的设备会再次拉低SCL线。
图 12.IIC总线时钟同步
握手
时钟同步机制可以被用作数据传输中的握手。从机设备可以在一个字节传输(9个bit)后维持SCL为低。这种情况下,它能停止总线时钟并强迫主机时钟为等待状态,直到从机释放SCL线。
时钟延展
时钟延展机制可以被从机用于降低传输的比特率。在主机驱动SCL为低位后,从机可以驱动SCL为低足够长的时间,然后释放它。如果从机的SCL低位周期比主机SCL低位周期长,就会导致SCL总线信号低位周期的延展。
10bit 地址
如果首个地址字节的头5个bit为0b11110,则表明这是个10bit地址。下面的规则应用于首个地址字节。
表 11.首个字节中的位的定义。
从机地址 | R/W位 | 描述 |
---|---|---|
0000000 | 0 | 通用呼叫地址 |
0000010 | x | 为不同总线格式预留 |
0000011 | x | 为未来预留 |
11111XX | x | 为未来预留 |
11110XX | x | 10bit 从机寻址 |
地址类型由ADTYPE定义。当ADTYPE为0,使用7bit地址。反之,则使用10bit地址。通常来说,有两类10bit地址。见图14和15。
图14. 一个主发送器以10bit地址寻址一个从接收器
图15. 一个主接收器以10bit地址寻址一个从发送器
在图15中,前两个字节与图14的相似。在重复启动(Sr)之后,首个从机地址再次被发送,但是R/W位为1,意识是从机要作为发送器。
通用呼叫地址
为了使用通用呼叫地址进行广播,设备必须先生成通用呼叫地址(0x00),然后在接收到确认位后,必须传输数据。
在通信中,作为从机设备,如果GCEN为1,则会应答广播并接收数据直到禁用了GCEN或者主机释放了总线或者启动了新的传输。在广播中,从机总是作为接收器。在通用呼叫中,IAAS同样用于指示地址匹配。
为了区分地址匹配是匹配的正常地址还是通用地址,在接收到地址字节之后应该读取IBDR。如果数据为0x00,说明匹配的是通用呼叫地址。通用呼叫地址的意义总是在第一个数据字节中指定,必须由软件进行处理,IIC硬件并不会解密和处理首个数据字节。
当一次数据字节传输完成,可以从IBDR中读取收到的数据。用户可以通过使能或禁用GCEN来控制这个过程。
运行模式下的运行
这是运行的基本模式。
等待模式下的运行
IIC在等待模式下的运行方式是可配置的。取决于内部寄存器位的配置,IIC模块可以在CPU在等待模式时正常运行或者可以停止IIC时钟生成使IIC模块进入一个能量保存状态。然后,进行中的任何发送或接收都会在进入等待模式那一刻停止。
停止模式下的运行
为了节能,IIC模块在停止模式下是不活跃的。STOP指令不会影响IIC寄存器的状态。
重置
每一个位在重置后的状态都列在了“地址映射与寄存器定义”中,里头详述了寄存器和他们的位字段。
中断
IICV3只使用一个中断向量。
表 12.中断总结
中断 | 偏移 | 向量 | 优先级 | 中断源 | 描述 |
---|---|---|---|---|---|
IIC中断 | - | - | - | IBSR寄存器中的IBAL、TCP、IAAS位 | 当IBAL、TCP、IAAS任一个置位时会触发中断,分别是由于仲裁丢失、传输完成和地址匹配导致。 |
IIC内部有三种类型的中断。中断服务例程可以通过读取状态寄存器来确定中断类型。
IIC中断可以由以下条件生成:
1. 仲裁丢失(IBAL置位)
2. 字节传输完成(TCF置位)
3. 地址匹配(IAAS置位)
IIC中断通过置位IIC控制寄存器中的IBIE位来启用。必须在中断服务例程中向IBF位写0来清零它(译者注:没看懂,但原文就这么写的)。
应用信息
IIC编程示例
初始化序列
重置会使得IIC的控制寄存器变为默认状态。在接口可以用于传输串行数据前,需要先按照如下执行一个初始化过程:
- 修改分频寄存器(IBFD)并选择需要的分频系数以从系统时钟获得SCL频率。
- 修改IBCR2的ADTYPE以确定地址长度,7bit或者10bit。
- 修改IIC地址寄存器以定义自己的从机地址。如果使用的是10bit地址,还要修改IBCR2寄存器以定义地址的高位。
- 置位IIC控制寄存器(IBCR)的IBEN位以使能IIC接口系统。
- 修改IIC控制寄存器(IBCR)以选择主机/从机模式、传送/接收模式以及是否使能中断。
- 如果支持通用呼叫,应该断言IBCR2中的GCEN位。
生成启动信号
在初始化过程完成后,可以通过选择“主机发送”模式来发送串行数据。如果设备连在一个多主机总线系统上,必须要检查IIC总线忙位(IBB)的状态以查看是否串行总线空闲。
如果总线空闲(IBB = 0),就可以发送启动信号和首个字节(从机地址)。写入数据寄存器的数据包含从机主叫地址,最低位则用于告知从机自己想要的数据传输方向。
总线空闲时间(即在停止条件到下一个启动条件之间的时间)是生成启动信号的硬件决定的。取决于系统时钟的相对频率和SCL周期,在写入主叫地址到IBDR后可能需要等到IIC忙碌,才能继续后续的指令。后面的例子就是说的这个。
下面是生成启动信号并传输首个字节(从机地址)的示例程序:
CHFLAG BRSET IBSR,#$20,* ;等待IBB标志位清零
TXSTART BSET IBCR,#$30 ;设置主机传输模式;即生成启动信号
IBFREE BRCLR IBSR,#$20,* ;等待IBB位置位
MOVB calling,IBDR ;传输主叫地址,D0=R/W
IBFREE BRCLR IBSR,#$20,* ;等待IBB位置位
数据传输后的软件响应
传输或接收一个字节会使数据传输位(TCF)置位,它表明一个数据传输完成了。IIC总线中断位(IBIF)也会置位;如果在初始化时通过置位IBIE使能了中断功能,这时就会产生一个中断。软件在中断例程的一开始必须清零IBIF位。在接收模式下读取数据I/O寄存器(IBDR)或在发送模式下写入IBDR,会清零TCF位。
如果没有使用中断功能,软件可以通过监视IBIF位来驱动IIC模块。注意,轮询的应该是IBIF位而不是TCF位,因为在仲裁丢失时它们的运行方式是不一样的。
注意,当中断在地址周期末尾发生时,主机总是会在传输模式,即地址总是被发送的。如果想要的是主机接收模式,在往IBDR中写入从机地址时设置好R/W位,然后在这里反转Tx/Rx位。
在从机模式的地址周期时(IAAS=1),读取状态寄存器的SRW位来确定随后的传输方向并相应地编程Tx/Rx位。对于从机模式的数据周期(IAAS=0),SRW位无效,应该读取控制寄存器的Tx/Rx位以确定当前的传输方向。
下例是中断例程中“主机发送器”的软件响应示例:
ISR BCLR IBSR,#$02 ;清零IBIF标志位
BRCLR IBCR,#$20,SLAVE ;如果是从机模式则跳转
BRCLR IBCR,#$10,RECEIVE ;如果是接收模式则跳转
BRSET IBSR,#$01,END ;如果没有应答,则结束传输
TRANSMIT MOVB DATABUF,IBDR ;传输下一个数据字节
生成停止信号
一次数据传输由“主机”设备产生一个停止信号来结束。主机发送器可以简单地在所有数据传输完成后产生一个停止信号。下面是一个怎么使主机发送器生成停止信号的示例。
MASTX TST TXCNT ;获得发送计数器的值
BEQ END ;如果没有更多数据的话就跳到END
BRSET IBSR,#$01,END ;如果没有应答的话就跳到END
MOVB DATABUF,IBDR ;发送数据的下一个字节
DEC TXCNT ;递减TXCNT
BRA EMASTX ;退出
END BCLR IBCR,#$20 ;生成一个停止信号
EMASTX RTI ;从中断返回
如果一个主机接收器想要结束数据传输,它必须不应答最后一个数据字节以告知从机发送器,这可以通过在读取倒数第二个数据字节前设置传输应答位(TXAK)来实现。在读取最后一个数据字节前,必须先生成停止信号。下例展示了主机接收器怎么生成停止信号。
MASR DEC RXCNT ;递减RXCNT
BEQ ENMASR ;如果是要读取的最后一个字节,跳转到ENMASR
MOVB RXCNT,D1 ;检查是不是倒数第二个
DEC D1 ;
BNE NXMAR ;如果既不是最后一个也不是倒数第二个,跳转到NXMAR
LAMAR BSET IBCR,#$08 ;这是倒数第二个,禁用传输应答
BRA NXMAR
ENMASR BCLR IBCR,#$20 ;这是最后一个字节,生成停止信号
NXMAR MOVB IBDR,RXBUF ;读取数据并存储
RTI
生成重复启动信号
在数据传输的末尾,如果主机想要继续与总线通信,它可以产生另一个启动信号,然后发送另一个从机地址而不用先产生停止信号。程序示例如下:
RESTART BSET IBCR,#$04 ;另一个启动(重启)
MOVB CALLING,IBDR ;传输主叫地址;D0=R/W
从机模式
在从机中断服务例程中,应该检查模块的被寻址为从机位(IAAS)以确定是否自己受到呼叫。如果IAAS置位,软件应该根据R/W命令位(SRW)设置传输/接收模式选择位(IBCR的Tx/Rx位)。写入IBCR会自动清零IAAS。注意,在中断中,IAAS会读为1的时刻只有在发生了地址匹配的地址周期的结尾,在随后数据传输导致的中断中,IAAS为0。现在,可以通过写IBDR(从机发送模式),或虚读一次IBDR(从机接收模式)以发起数据传输。从机将在两次数据传输间驱动SCL为低位,当在想要的模式下访问了IBDR,SCL被释放。
在从机发送器例程中,必须在发送下一个数据字节前检查接收应答位(RXAK)。RXAK为1表示来自主机接收器的”数据结束”信号,这之后,必须由软件切换发送模式为接收模式。然后进行一次虚读以释放SCL线,这样主机就可以产生停止信号。
仲裁丢失
如果多个主机同时想要竞争总线,只有一个主机获胜,其他会丢失仲裁。丢失仲裁的设备立刻由硬件切换为从机接收模式。在丢失仲裁期间,他们会停止到SDA线的数据输出,但是SCL会继续生成直到字节的结尾。在这次传输的第九个时钟的下降沿会发生中断,这时IBAL=1,MS/SL=0。如果一个主机试图在总线正被另一个主机竞争时启动传输,硬件会禁止传输;将MS/SL位从1切换为0,这时不会生成停止信号;生成中断给CPU并置位IBAL以表明竞争总线失败。考虑到这种情况,从机服务例程应该先测试IBAL,如果IBAL位置位了,软件应该清零它。
图 16.典型的IIC中断服务例程流程图