IIC 使用说明 SM39R 系列 IIC 使用说明 1 适用产品: 1.1 SM39R02A2/ SM39R04A2 1.2 SM39R2051G1/ SM39R4051G1 1.3 SM39R08A2/ SM39R12A2/ SM39R16A2 2 IIC 使用概述: 2.1 使用硬件 SCL (clock)及 SDA (data)管脚,须接上拉电阻,建议 2K~10KΩ。 2.2 速度:SCL 最高可达 400Kbps(由软件设定 SFR IICBR[2:0])。 2.3 IIC 和 ICE 内部使用同一电路,所以使用 IIC 功能和 ICE 仿真不可同时使用。 2.4 IIC 可选择 master 或 slave 两种模式,提供中断(RXIF, TXIF, MPIF)及两组控制地址(IICA1, IICA2) 使用。 2.5 Master 硬件可自动产生 IIC 的启动(START)、重新启动(Re-START)及停止(STOP)信号,自动侦 测 bus busy(BB flag)及 arbitration(LAIF)。 2.6 Slave 硬件可侦测 IIC 的 START(Match)、Re-START(Match)及 STOP(MPIF)信号。 2.7 Slave 最多可接 127 devices,线材电容量最高限制为 400pF。 3 IIC 相关的特殊缓存器 Special Function Register (SFR) Mnemonic Description Direct Bit 7 AUX IICCTL Auxiliary register IIC control register 91h F9h BRGS IICEN IICS IIC status register F8h - IICA1 IICA2 IICRWD IICEBT IIC Address 1 register IIC Address 2 register IIC Read/Write register IIC Enaable Bus Transaction Bit 6 Bit 5 Bit 4 IIC function P2SPI P2UR MSS MAS AB_EN MPIF LAIF RXIF FAh IICA1[7:1] FBh IICA2[7:1] FCh FDh Bit 3 Bit 2 P2IIC BF_EN - TXIF Bit 1 Bit 0 DPS IICBR[2:0] RW or RXAK TXAK BB MATCH1 or RW1 MATCH2 or RW2 IICRWD[7:0] FU_EN - - - RESET 00H 04H 00H A0H 60H 00H - - - Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 1 Ver A 2011/09 00H IIC 使用说明 Mnemonic: AUX 7 6 5 BRGS P2SPI 4 P2UR 3 P2IIC 2 - 1 - Address: 91h 0 Reset DPS 00H P2IIC: P2IIC = 0 – IIC function on P1. P2IIC = 1 – IIC function on P2. P2IIC 0 1 SCL P1.2 P2.6 SDA P1.3 P2.7 IIC 脚位直接由软件指定至 P1 或 P2,可避免和其它特殊功能脚位重复,提高硬件规划的兼容性。有此 功能的 MCU 如下表: P4IIC(IIC function pin assignment) MCU device SM39R16A2/ SM39R12A2/ SM39R08A2 ○ SM39R4051/ SM39R2051 X SM39R04G1/ SM39R02G1 X ○:表示该型号可以使用 P2IIC 功能 X:表示该型号不可使用 P2IIC 功能 Mnemonic: IICCTL 7 6 5 IICEN MSS MAS 4 AB_EN 3 2 BF_EN 1 IICBR[2:0] Address: F9h 0 Reset 04h IICEN: IC 致能位(Enable IIC module) IICEN = 1,IIC 致能。 IICEN = 0,IIC 禁能。 MSS: 主从模式选择位 Master or slave mode select: MSS = 1,设定为 master mode。 MSS = 0,设定为 slave mode。 *当使用 IIC 设定其它 IIC SFR 时,程序必须先致能此位。 MAS: 控制地址位 Master address select (master mode only): MAS = 0 ,选择控制地址(control byte)由 SFR IICA1 送出。 MAS = 1 ,选择控制地址(control byte)由 SFR IICA2 送出。 AB_EN: 仲裁检查致能位 Arbitration lost enable bit. (Master mode only) AB_EN = 1,致能仲裁检查。 AB_EN = 0,禁能仲裁检查,master不理会主控权丢失情况。 仲裁检查:在multi-master架构,master由硬件送出SDA为”1”,却侦测到为”0”时,即发生仲裁丢失, 失去对IIC bus的主控权(表示IIC bus上已有其它master正在通讯),LAIF将被设置为”1”。 当系统为多主从(multi-master)应用时,必须致能AB_EN,并检查LAIF位。 当系统为单主从(single-master)应用时,可禁能AB_EN。 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 2 Ver A 2011/09 IIC 使用说明 BF_EN: 总线忙碌侦测致能位 Bus busy enable bit. (Master mode only) BF_EN = 1,致能,若BF=1,master会无法送出启动条件(Start condition),直到BF=0。 BF_EN = 0,禁能,master硬件不理会BF=0或1。 致能BF_EN时: 1. 当Master硬件侦测到启动条件(Start condition),或BUS上的SCL=0、或SDA=0时,即为 bus busy状态,BB会由硬件设为”1”。 2. 当Master硬件侦测到停止条件(Stop condition)后,BB由硬件清除为”0”。此位也可由软件清 除。 当系统为多主从(multi-master)应用时,必须致能BF_EN,并检查BB(bus busy)位。 当系统为单主从(single-master)应用时,可禁能BF_EN。 IICBR[2:0]: IIC 鲍率选择元位 Baud rate selection (master mode only): 系统频率(Fosc)依据 MCU 外部晶振(或内部晶振)而定,默认值为 Fosc/512 。 IICBR[2:0] 000 001 010 011 100 101 110 111 Mnemonic: IICS 7 6 MPIF 5 LAIF Baud rate Fosc/32 Fosc/64 Fosc/128 Fosc/256 Fosc/512 Fosc/1024 Fosc/2048 Fosc/4096 4 RXIF 3 TXIF 2 RXAK 1 TxAK Address: F8H 0 Reset RW or BB 00H MPIF: 停止中断旗标 Stop Interrupt Flag: 1. master: 送出或侦测(multi-master)到stop condition时,MPIF会由HW设置为1,会 产生中断,但与RxIF及TxIF无关。MPIF必须由软件清除,或离开中断时由HW清除。 2. slave: 收到stop condition时,MPIF会由HW设置为1,但不产生中断,MPIF必须由 软件清除。 LAIF: 仲裁检查旗标 Lost Arbitration bit. (Master mode only) LAIF = 1,失去总线主控权 lost bus arbitration。 LAIF = 0,总线闲置 bus ready。 当系统为多主从(multi-master)应用时,请致能该侦测位(AB_EN)。 当系统为单主从(single-master)应用时,可禁能该侦测位(AB_EN)。 AB_EN = 1,致能仲裁检查。 AB_EN = 0,禁能仲裁检查,master不理会主控权丢失情况。 仲裁检查:在multi-master架构,master由硬件送出SDA为”1”,却侦测到为”0”时,即发生 仲裁丢失,失去对IIC bus的主控权(表示IIC bus上已有其它master正在通讯),LAIF将被设 置为”1”。 当系统为多主从(multi-master)应用时,必须致能AB_EN,并检查LAIF位。 当系统为单主从(single-master)应用时,可禁能AB_EN。 RxIF: 数据接收中断旗标 Data receive interrupt flag 以下事件发生时 RxIF 会由硬件设为”1”,并发生中断: 1. master mode: IICRWD 加载数据完成时。 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 3 Ver A 2011/09 IIC 使用说明 2. slave mode: IICRWD 加载数据完成时。 3. slave mode: Match (即 salve 收到 start condition 及 device ID)时。 RxIF必须由软件清除。 TxIF: 数据传送中断旗标 Data transmit interrupt flag 以下事件发生时 TxIF 会由硬件设为”1”,并发生中断: 1. master mode: 送出 start condition 及 device ID 时。 2. master mode: 数据从 IICRWD 载至位移缓存器,并已由位移缓存器传送时。 3. slave mode: 数据从 IICRWD 载至位移缓存器,并已由位移缓存器传送时。 TxIF必须由软件清除。 RxAK: 接收应答位 Receive acknowledgement (read only) 此为只读位,传送端等待接收端回复应答(ACK/NACK),不可由程序编写。 1. master mode:传出数据(8-bit)后,由 slave 回复应答位(RxAK)。 2. slave mode:传出数据(8-bit)后,由 master 回复应答位(RxAK)。 TxAK: 传送应答位 Transmit acknowledgement 接收端接收前必须先设定好 TxAK(ACK or NACK),接收数据完成后,即由硬件送出 TxAK 至传送端。 RW or BB: Master Mode: 总线忙碌侦测位 Bus busy bit BB = 1,总线忙碌 bus busy。 BB = 0,总线闲置 bus ready。 致能BF_EN时: 1. 当Master硬件侦测到启动条件(Start condition),或BUS上的SCL=0、或SDA=0时, 即为bus busy状态,BB会由硬件设为”1”。 2. 当Master硬件侦测到停止条件(Stop condition)后,BB由硬件清除为”0”。此位也可由 软件清除。 当系统为多主从(multi-master)应用时,必须致能BF_EN,并检查BB(bus busy)位。 当系统为单主从(single-master)应用时,可禁能BF_EN。 Slave Mode: 读写状态位 Read or Write status bit(read only) 此位由 master 的地址 IICA1(或 IICA2) 的 8th-bit 所控制: RW = 0,master 要求 slave 的 IIC module 为接收模式(即 master write, slave read)。 RW = 1,master要求slave的IIC module为传送模式(即master read, slave write)。 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 4 Ver A 2011/09 IIC 使用说明 Fig. Acknowledgement bit in the 9th bit of a byte transmission Mnemonic: IICA1 7 6 5 4 IICA1[7:1] R/W 3 2 1 Address: FAH Reset 0 Match1 or RW1 A0H R or R/W Slave mode: IICA1[7:1]: IIC Address registers 控制地址(第一组)IICA1 共 7-bit,须由软件设定。 Match1: 当 slave 接收到 master 的启动条件(Start or Re-Start condition),及控制地址(IICA1)7-bit,由硬 件比对: = 1,当比对相同时,Match1 及 RxIF 皆由硬件设置为”1”,并产生中断。 = 0,Match1 由硬件清除为”0”,如下情况: 1. RXIF 发生但未侦测到启动条件(Start or Re-Start condition)。 2. TXIF 发生时。 Master mode: IICA1[7:1]: IIC Address registers 1. 第一组控制地址 IICA1 共 7-bit,由软件设定。 2. 当 MAS = 0,选择控制地址第一组(IICA1)。 当 MAS = 1,选择控制地址第二组(IICA2)。 3. 当 IICEBT 由软件设置为”10”时,会送出启动条件(Start or Re-Start condition)及控制地址位 (IICA1)。 RW1: master 送出的 8th-bit(R/W-bit),告知 slave 读写的状态 RW1= 1:为 master IIC module 接收模式(即 master read, slave write)。 RW1= 0:为 master IIC module 传送模式(即 master write, slave read)。 Fig. : RW bit in the 8th bit after IIC address Mnemonic: IICA2 7 6 5 Address: FBh 4 IICA2[7:1] R/W 3 2 1 0 Match2 or RW2 R or R/W Reset 60h Slave mode: IICA2[7:1]: IIC Address registers 控制地址(第二组)IICA2 共 7-bit,须由软件设定。 Match2: 当 slave 接收到 master 的启动条件(Start or Re-Start condition),及控制地址(IICA2)7-bit,由硬 件比对: = 1,当比对相同时,Match2 及 RxIF 皆由硬件设置为”1”,并产生中断。 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 5 Ver A 2011/09 IIC 使用说明 = 0,Match2 由硬件清除为”0”,如下情况: 1. RXIF 发生但未侦测到启动条件(Start or Re-Start condition)。 2. TXIF 发生时。 Master mode: IICA2[7:1]: IIC Address registers 1. 控制地址(第二组)IICA2 共 7-bit,由软件设定。 2. 当 MAS = 0,选择控制地址第一组(IICA1)。 当 MAS = 1,选择控制地址第二组(IICA2)。 3. 当 IICEBT 由软件设置为”10”时,会送出启动条件(Start or Re-Start condition)及控制地址位 (IICA2)。 RW2: master 送出的 8th-bit(R/W-bit),告知 slave 读写的状态 RW2= 1:为 master IIC module 接收模式(即 master read, slave write)。 RW2= 0:为 master IIC module 传送模式(即 master write, slave read)。 Mnemonic: IICRWD 7 6 5 4 3 IICRWD[7:0] 2 Address: FCh 0 Reset 00h 1 IICRWD[7:0]: 数据读写缓存器(8-bit) IIC read write data buffer: 1. IIC 接收时,IICRWD 为接收数据的暂存区; 当数据接收完成时 RxIF=1,再读取 IICRWD,读完后必须 release IIC bus(即 IICEBT 写入”01”)。 2. IIC 传送时,IICRWD 为传送数据的暂存区; 先将数据写入 IICRWD,再写入 IIC 传送指令(即 IICEBT 写入”01”)即可,传送完成时 TxIF=1。 Address: FDH Mnemonic: IICEBT 7 6 5 - FU_EN Master Mode FU_EN[7:6]: 4 - 3 - 2 - 1 - 0 - Reset 00H FU_EN[7:6] 00 Reserved 01 Master transmit data 传数据操作命令及流程: 1. Write data to IICRWD (by software) 2. FU_EN write 01 (by software) 3. Transmit data finish and receive RxAK when FU_EN auto-clear (by HW) 4. TxIF will set (by HW) then interrupt occur, TxIF must clear (by software) 5. Check RxAK status EX: IICRWD=TxData; // load data IICEBT=0x40; // trans. data Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 6 Ver A 2011/09 IIC 使用说明 while(IICEBT != 0x00);// waiting data trans. Finish while(TxIF=0); TxIF=0; if(RxAK) { // by user… } else { // by user… } Master receive data 收数据操作命令及流程: 1. TxAK set ACK/NACK before receive data (by software) 2. FU_EN write 01(by software) for release bus 3. Receive data finish and transmit TxAK when FU_EN auto-clear (by HW) 4. RxIF will set (by HW) then interrupt occur 5. User can read data from IICRWD (by software) 6. RxIF must clear (by software) Ex: TXAK=ACKStatus; // Feedback ACK/d_NACK to slave IICEBT=0x40; // Ready for receive while(IICEBT != 0x00);// waiting data recive finish while(RxIF=0); RxIF=0; temp=IICRWD; 10 送出启动条件(Start or Re-Start condition)及控制地址位 (IICA1/IICA2) Ex: IICEBT = 0x80; // generate a start condition while(IICEBT != 0x00); return RXAK; 11 送出停止条件(Stop condition) IIC bus module generate a stop condition on the SDA/SCL. Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 7 Ver A 2011/09 IIC 使用说明 EX: IICEBT = 0xC0; // generate a stop condition while(IICEBT != 0x00);// waiting data recive finish Notice: 在此仅作简易的程序示范,完整程序可参考”完整范例程序”的master及slave,或使用SyncMOS Codzard产生。 Slave Slave transmit data 传数据操作命令及流程(同 master): mode: 1. Write data to IICRWD (by software) 2. FU_EN write 01 (by software) 3. Transmit data finish and receive RxAK when FU_EN auto-clear (by HW) 4. TxIF will set (by HW) then interrupt occur, TxIF must clear (by software) Slave receive data 收数据操作命令及流程(不同于 master): 1. TxAK set ACK before receive data (by software) 2. Receive data finish and transmit TxAK when IICEBT auto-clear (by HW) 3. RxIF will set (by HW) then interrupt occur 4. User can read data from IICRWD (by software) 5. FU_EN write 01(by software) for release bus 6. RxIF must clear (by software) Slave receive Start or Re-Start condition 操作命令及流程: 1. TxAK set ACK before match (by software) 2. Transmit TxAK when device ID match 3. RxIF will set (by HW) then interrupt occur 4. User can read data from IICRWD (by software) 5. FU_EN write 01(by software) for release bus 6. RxIF must clear (by software) void IIC_interrupt() interrupt d_IIC_Vector { unsigned char buf; //slave rx=========================================================== if(RXIF) { //======================================================= if ((IICA1 & 0x01) || (IICA2 & 0x01)) // match { Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 8 Ver A 2011/09 IIC 使用说明 if (n_RW == d_Write) IICEBT = d_CMD_RW; // don't release if read phase // IIC bus release if write phase } //======================================================= else { buf = IICRWD; // save addr offset IICEBT = 0x40; // IIC bus release } //======================================================= RXIF = 0; } //slave tx=========================================================== if (TXIF) { TXIF = 0; // Clear interrupt flag } //=================================================================== } Notice: 1. Slave只须设定FU_EN[7:6] =[ 0 1] (当作Release BUS的功能 ),其它值不可设定。 2. 如果没release,IIC SCL会被lock住(=0)。 3. 在此仅作简易的程序示范,完整程序可参考”完整范例程序”的master及slave,或使用SyncMOS Codzard产生。 4 IIC 中断 4.1 向量表(Interrupt vectors table) Interrupt Vector Address 0003h Interrupt Number *(use Keil C Tool) 0 TF0 – Timer 0 interrupt 000Bh 1 IE1 – External interrupt 1 0013h 2 TF1 – Timer 1 interrupt 001Bh 3 RI0/TI0 – Serial channel 0 interrupt TF2/EXF2 – Timer 2 interrupt (SM39R16A2/ SM39R12A2/ SM39R08A2 only) PWMIF – PWM interrupt (SM39R16A2/ SM39R12A2/ SM39R08A2 only) SPIIF – SPI interrupt 0023h 4 002Bh 5 0043h 8 004Bh 9 ADCIF – A/D converter interrupt 0053h 10 KBIIF – keyboard Interface interrupt 005Bh 11 LVIIF – Low Voltage Interrupt 0063h 12 IICIF – IIC interrupt 006Bh 13 Interrupt Request Flags IE0 – External interrupt 0 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 9 Ver A 2011/09 IIC 使用说明 RI1/TI1 – Serial channel 1 interrupt Comparator interrupt (SM39R16A2/ SM39R12A2/ SM39R08A2 only) 0083h 16 0093h 18 *See Keil C about C51 User’s Guide about Interrupt Function description 4.2 中断相关缓存器(Interrupt SFR) Mnemonic IEN0 IEN1 IEN2 IRCON IRCON2 IP0 IP1 Description Interrupt Enable 0 register Interrupt Enable 1 register Interrupt Enable 2 register Interrupt request register Interrupt request register 2 Interrupt priority level 0 Interrupt priority level 1 Direct Bit 7 Bit 6 A8H EA - B8H EXEN2 9AH Bit 5 Interrupt Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 RESET ET2 ES ET1 EX1 ET0 EX0 00H - IEIIC IELVI IEKBI IEADC IESPI IEPWM 00H - - - - - ECmpI - - 00H C0H EXF2 TF2 IICIF LVIIF KBIIF ADCIF SPIIF PWMIF 00H 97H - - - - - CmpIF - - 00H A9H - - IP0.5 IP0.4 IP0.3 IP0.2 IP0.1 IP0.0 00H B9H - - IP1.5 IP1.4 IP1.3 IP1.2 IP1.1 IP1.0 00H IIC 中断应用可参考以下设定: (1) IIC 中断致能设定: IEN0 |= 0x80; //Enable interrupt All IEN1 |= 0x20; //Enable interrupt IIC (2) IIC 中断程序表示: void ISR_IIC (void) interrupt 13 { if(TXIF) { TXIF = 0;//Clear interrupt flag } if(RXIF) { RXIF = 0;//Clear interrupt flag } if(MPIF) { MPIF = 0;//Clear interrupt flag } } Ps. IIC 中断发生,必须清除 IICS 的 TXIF 或 RXIF 或 MPIF,而非 IRCON 的 IICIF! 5 以下使用两颗 MCU,分别做为 master 及 slave,以最普遍使用的 EEPROM 24Cxx 做为通讯 protocal 来说明 IIC 应用: 5.1 MCU IIC flag 状态图(IIC Page Write): Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 10 Ver A 2011/09 IIC 使用说明 Master: • M1. FU_EN写入10,Master送出Start、Device ID及RW讯号。 • M2. 送出完成时,FU_EN由硬件清为零,TxIF由硬件设置为1, 并产生中断,TxIF由软件清除。时也需判断RxAK的状态。 • M3. Data写入IICRWD后, FU_EN写入01,即会将Data送出。 • M4. Data送出后,FU_EN由硬件清为零,TxIF由软件设置为1, 并产生中断。 • M5. FU_EN写入11,送出Stop讯号,后MPIF由硬件设为1, 并产生中断。 Slave: • S1. S1. 当slave硬件侦测到Start condition及device ID, Match bit由硬件设为1。 • S2. 收到Device ID(及RW)时,硬件会传出TxAK;RxIF会 由硬件设为1,并触发中断,软件必须写FU_EN=01,用来 release bus。 • S3. 收到Data时,硬件会传出TxAK;RxIF会由硬件设为1, 并触发中断,软件必须写FU_EN=01,用来release bus。 • S4. 在收到Stop condition后,MPIF由硬件设为1,MPIF须 由软件清除为0。 5.2 MCU IIC flag 状态图(IIC Random Read): Master: Slave: • • M1&M3. FU_EN写入10h,Master送出Start(or S1. 当slave硬件侦测到Start condition及device ID,Match Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 11 Ver A 2011/09 IIC 使用说明 Re-Start)、Device ID及RW讯号。收到ACK后FU_EN由硬 • 件清除,并触发TxIF。 • • bit由硬件设为1。 RxIF会由硬件设为1,并触发中断,软件必须写FU_EN=01, 出Data。收到ACK后FU_EN由硬件清除,并触发TxIF。 用来release bus。 M4. RX:FU_EN写入01h后,SCL开始送出CLK,并将Data • 收进IICRWD,收到ACK后FU_EN由硬件清除,并触发 M5. Stop:FU_EN写入11h后,送出Stop,收到ACK后 S4. 每次Data完成送出后,FU_EN由硬件清除为0,TxIF由 硬件设置为1,并触发中断,TxIF须由软件清除为0。 • FU_EN由硬件清除,并触发MSIF及中断。 S3. 每次Data写入IICRWD后,FU_EN写入01,即会将Data 送出。 • RxIF及中断。 • S2. 收到Device ID(及RW)或Data,硬件会接着传出TxAK; M2. TX:将Data写入IICRWD后,FU_EN写入01h,即送 S5. 当收到N-ACK时,Slave即停止Data回传。在收到Stop condition,MPIF由硬件设为1,MPIF须由软件清除为0。 5.3 MCU IIC 完整范例程序(master): Description MCU master w/r EEPROM(24cxx): Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 12 Ver A 2011/09 IIC 使用说明 Main program //======================================================================== // // S Y N C M O S T E C H N O L O G Y // //======================================================================== #include "SM39R16A2.h" #include "IIC.h" //=============================== //IIC DEFINITIONs //=============================== #define d_DEVICE_ID1 0x60 #define d_DEVICE_ID2 0xA0 // user modify // user modify #define d_IIC_ADR_CA1 #define d_IIC_ADR_CA2 #define d_IIC_ADR_SEL // user modify, Device ID select 0x00 0x20 d_IIC_ADR_CA1 #define #define #define #define #define #define #define #define #define d_BR32 d_BR64 d_BR128 d_BR256 d_BR512 d_BR1024 d_BR2048 d_BR4096 d_IIC_BR 0x00 0x01 0x02 0x03 0x04 #define #define #define #define #define #define #define #define d_MASTER d_SLAVE d_MODE_SEL d_IIC_EN d_NACK d_ACK d_WRITE d_READ 0x40 #define #define #define #define #define #define d_BB_DIS d_BB_EN d_BUS_BUSY d_AR_DIS d_AR_EN d_ARBITRATION 0x00 #define #define #define d_CMD_RW d_CMD_Start d_CMD_Stop 0x05 0x06 0x07 d_BR32 0x00 d_MASTER // user modify //691.2->588 // use master mode 0x80 1 0 0 1 0x08 d_BB_EN 0x00 0x10 d_AR_EN 0x40 0x80 0xC0 //=============================================================== //OWNED SUBROUTINES //=============================================================== void IIC_interrupt(void) interrupt d_IIC_Vector { if(TXIF) { TXIF = 0; // Clear interrupt flag } if(RXIF) { RXIF = 0; // Clear interrupt flag } if(MPIF) Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 13 Ver A 2011/09 IIC 使用说明 { MPIF=0; // Clear interrupt flag } } void IIC_Init_master(void) { IICA1 = d_DEVICE_ID1; IICA2 = d_DEVICE_ID2; IICS = 0x00; // Clear IIC all status IEN0 |= 0x80; // Enable interrupt All IEN1 |= 0x20; // Enable interrupt IIC IICCTL = d_IIC_EN | d_MODE_SEL | d_ARBITRATION | d_BUS_BUSY | d_IIC_ADR_SEL | d_IIC_BR; } void IIC_Disable(void) { IICCTL = 0x00; IEN1 &= 0xDF; IICS = 0x00; } // Disable IIC all function // Disable interrupt IIC // Clear IIC all status //=============================================================== //This function will send out the Start or Re-Start pulse and CONTROL byte. //=============================================================== bit IIC_SendStart(unsigned char ControlByte) { IICA2 = ControlByte; // MAS = 1 IICA1 = ControlByte; // MAS = 0 IICEBT = d_CMD_Start; while(IICEBT != 0x00) { ; } return RXAK; // generate a start condition } //=============================================================== //This function will send out the Stop pulse //=============================================================== void IIC_SendStop(void) { IICEBT = d_CMD_Stop; // generate a stop condition while(IICEBT != 0x00) // waiting data recive finish { ; } } //=============================================================== //This function will wait and receive one byte, then feedback ACK or NACK. //=============================================================== unsigned char IIC_ReceiveByte(bit ACKStatus) { unsigned char temp; TXAK = ACKStatus; // Feedback ACK/d_NACK to slave IICEBT = d_CMD_RW; // Ready for receive while(IICEBT != 0x00) { ; // waiting data recive finish Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 14 Ver A 2011/09 IIC 使用说明 } temp = IICRWD; //Delay(100); return(temp); // finetune by user } void IIC_TransmitByte(unsigned char TxData) { IICRWD = TxData; // load data IICEBT = d_CMD_RW; // trans. data while(IICEBT != 0x00) // waiting data trans. finish { ; } //Delay(100); // finetune by user } void IIC_Page_Write( char Crtl_byte, unsigned char Addr, char LEN) { unsigned char counter=0; IIC_SendStart(Crtl_byte | d_WRITE); // -- Send CONTROL byte -- if(RXAK==d_ACK) { IIC_TransmitByte( Addr ); // -- Send ADDRESS -- for (counter=0; counter<LEN; counter++) { if(RXAK==d_ACK) { IIC_TransmitByte(Addr + counter); } else { ; } // -- Write N bytes -- // -- Transmit one byte -- // error process } } else { ; } IIC_SendStop(); // error process // -- Send STOP -- MStart= 0 } void IIC_Random_Read( char Crtl_byte, unsigned char Addr, char LEN) { unsigned char Temp[16]; unsigned char counter=0; IIC_SendStart(Crtl_byte | d_WRITE); if(RXAK==d_ACK) { IIC_TransmitByte(Addr); if(RXAK==d_ACK) { IIC_SendStart(Crtl_byte | d_READ); for(counter=0; counter<LEN; counter++) { // -- Send CONTROL byte -- // -- Send ADDRESS -- // -- Send CONTROL byte -// -- Read N byte -- Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 15 Ver A 2011/09 IIC 使用说明 if(RXAK==d_ACK) { if(counter<(LEN-1)) { Temp[counter] = IIC_ReceiveByte(d_ACK); // Receive one byte } else { Temp[counter] = IIC_ReceiveByte(d_NACK);// Receive last byte } } else { ; // error process } } } else { ; // error process } } else { ; } IIC_SendStop(); // error process // -- Send STOP -- MStart= 0 } void Check_Arbitration(void) // multi-master use { // arbitration lost, set by H/W // clear by S/W while(LAIF) { LAIF = 0; } } void Check_Busy(void) // multi-master use { // Bus busy, BB set by H/W // Bus ready, BB clear by H/W or S/W while(BB) { ; } } void Delay(unsigned int NTime) { unsigned int i, j; for(i=0; i<NTime; i++) { for(j=0; j<100; j++) { ; } } } #define waitslave 10 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 16 Ver A 2011/09 IIC 使用说明 void main() { IIC_Init_master(); Check_Arbitration(); Check_Busy(); // multi-master use // multi-master use while(1) { IIC_Page_Write(d_DEVICE_ID1, Delay(waitslave); IIC_Random_Read(d_DEVICE_ID1, Delay(waitslave); IIC_Page_Write(d_DEVICE_ID1, Delay(waitslave); IIC_Random_Read(d_DEVICE_ID1, Delay(waitslave); IIC_Random_Read(d_DEVICE_ID1, Delay(waitslave); } 0x00, 3); // finetune by user 0x00, 3); // finetune by user 0x03, 3); // finetune by user 0x03, 3); // finetune by user 0x00, 6); } 5.4 MCU IIC 完整范例程序(slave): Description Main program MCU be slave as IIC-EEPROM: //======================================================================== // // S Y N C M O S T E C H N O L O G Y // //======================================================================== // Test condition: // Slave MCU Crystal 4~25MHz, pull-up 2.2KR // Master SCL=100KHz and 400KHz test ok //======================================================================== #include "SM39R16A2.h" #include "IIC.h" //===================================================================== #define d_DEVICE_ID1 0xA0 // user modify #define d_DEVICE_ID2 0x60 // user modify #define d_ACK #define d_NACK #define d_Write #define d_Read #define d_null #define d_CMD_RW #define d_SAVE_ADDR #define d_SAVE_DATA 0 1 0 1 0 0x40 1 2 //===================================================================== bit bACK_last = d_NACK; unsigned char n_Next_Step = d_null; unsigned char n_RW = d_null; unsigned char n_Addr = d_null; unsigned char n_DAT[16]; //===================================================================== void IIC_interrupt() interrupt d_IIC_Vector { //slave rx=========================================================== Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 17 Ver A 2011/09 IIC 使用说明 if(RXIF) { //======================================================= if ((IICA1 & 0x01) || (IICA2 & 0x01)) // match { n_Next_Step = d_SAVE_ADDR; // set next step n_RW = RW; // save RW status if (n_RW == d_Write) // don't release if read phase IICEBT = d_CMD_RW; // IIC bus release if write phase } //======================================================= else if (n_Next_Step == d_SAVE_ADDR) { n_Next_Step = d_SAVE_DATA; // set next step n_Addr = IICRWD; // save addr offset IICEBT = d_CMD_RW; // IIC bus release } //======================================================= else if (n_Next_Step == d_SAVE_DATA) { n_Next_Step = d_SAVE_DATA; // set next step n_DAT[n_Addr++] = IICRWD; // save data IICEBT = d_CMD_RW; // IIC bus release } //======================================================= RXIF = 0; } //slave tx=========================================================== if (TXIF) { TXIF = 0; // Clear interrupt flag } //=================================================================== } void IIC_init_slave() { IFCON |= 0x80; IICS = 0x00; IRCON = 0x00; IICEBT = d_CMD_RW; IICA1 = d_DEVICE_ID1; IICA2 = d_DEVICE_ID2; IEN1 |= 0x20; IEN0 |= 0x80; IICCTL = 0x80; } // MCU 1T // init IICS // init IRCON // IIC bus ready // Control Byte 1 // Control Byte 2 // Enable interrupt IIC // Enable interrupt All // Enable IIC module, slave mode, use IICA1 void IIC(void) { //slave tx=========================================================== if(n_RW==d_Read) { //slave tx get stop==================================== if(MPIF) // get Stop condition { n_RW = d_null; // break while(n_RW==d_Read) MPIF = 0; } Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 18 Ver A 2011/09 IIC 使用说明 //======================================================== else { //slave tx finish================================ if((RXAK == d_NACK)&&(bACK_last==d_ACK))// End if RXAK recive NACK { bACK_last = d_NACK; } //slave tx on going============================== else if(MPIF==0) { bACK_last = d_ACK; IICRWD = n_DAT[n_Addr++]; IICEBT = d_CMD_RW; // IIC bus ready while(IICEBT==d_CMD_RW) { ; } //IICEBT will auto clear by HW } //=============================================== } } //slave rx=========================================================== else if(n_RW==d_Write) { //slave rx finish==================================== if(MPIF) // get Stop condition { //slave rx get stop==================================== //slave finish recive data, here user process data, example n_DAT[]..... TXAK = d_NACK; //TX NACK if slave busy MPIF = 0; // clear MPIF if finish process TXAK = d_ACK; } } //=================================================================== } void main(void) { IIC_init_slave(); while(1) { IIC(); }//while(1) }//end of main 6 不同工作电压的 IIC 通讯应用: 图示 说明 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 19 Ver A 2011/09 IIC 使用说明 MCU Vcc Target Vcc Pull -up Target Vcc Pull -up SCL MCU SM39R Target IC SDA HW: 1. Bus 必须接上拉(pull-up)电阻,电阻值须视实际应用 调整。 2. 必要时调降 MCU Vcc 可降低 MCU VIH/VIL,但仍 须符合 MCU 工作电压 2.7~5.5V 规范。 3. 建议 Target Vcc> MCU Vcc*60%。 (Spec. ideal MCU Vcc=3.3V:VIH=1.9V,VIL=0.7V) (Spec. ideal MCU Vcc=5V:VIH=2.7V,VIL=1V) SW: 1. 先设置 SM39R 的 GPIO 设置为 open drain。 2. enable IIC function。 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0236 20 Ver A 2011/09