MC9S12XDP512下IIC模块的应用总结

IIC应用笔记

IIC总线相关知识:

1.起始信号: 时钟线保持高电平时,数据线上出现由高变低的信号。

2.停止信号:时钟线保持高电平时,数据线上出现由低变高的信号。

3.数据传输:时钟线为高电平时,数据线上的逻辑状态必须保持一致。时钟线为低电平时,允许数据线上的电平发生变化(即传输)

4.起始信号和停止信号都由主控制器产生,应答信号在每个数据传输后的第9个时钟周期由接收器产生,低电平有效。当主控制器为接收方时,接收到最后一个字节时,不应发送应答信号。

5. 写过程:启动IIC→发送从机地址→发送要写单元地址→发送写数据(一个或者连续写) →发送停止信号,关闭IIC

6.读过程:主机发送开始信号,启动IIC→发送从机地址→产生连续启动,发送要读单元地址→接收数据,发送应答信号→接收最后一个数据,不发送应答信号→发送停机信号

芯片相关知识:

1.  FM3135(RTC模块)

1.  支持最高1MHZIIC总线时钟频率。

2.     RTC模块读取时间流程:向地址0x00处先写0x01(即置位R)→地址移动到0x02→读取时间数据→向地址0x00处写0x00(即复位R)

3.     RTC模块修改时间流程:向地址0x00处写0x02(即置位W) →写时钟寄存器→向地址0x00处写0x00

2.  MC9S12XDP512IIC模块:

1.IBCR:5位,主/模式选择位,该位从0变成1时,产生起始信号;该位从1变成0时,产生一个停止信号(只有当IBIF=1时,停止信号才能产生).

2.IBDR:在发送模式下,当一个数据被写到IBDR时,数据传输就开始了。

     在接收模式下,读该寄存器将机动下一字节的接收。注意:接收第一字节之前,空读该寄存器以启动接收。在读最后一个字节之前,要将寄存器设置成不发送应答信号。当下一次中断(最后一个字节之后的一个数据)来临时,不能再读IBDR,应直接写IBCR的第5位产生停止信号。

   3. 主机做接收方时,需要将主机设置成连续启动.

     4. 发送中断来临时,还需等待从机应答信号到来才能发送下一个字节。

代码:

 // ========================================================== // IIC启动函数 // 通信速率,总线频率的128分频,363KHZ // 0:读时钟,1:修改时钟 // ========================================================== void IIC_Function(byte cmd) { if(cmd == 0) // 读时钟 { while((Status.Bits.Time_Write == 1)||(Status.Bits.Time_Read == 1)); // 等待修改时钟命令完成 Status.Bits.Time_Read = 1; // 置位读时钟标志 } else { while((Status.Bits.Time_Read == 1)||(Status.Bits.Time_Write == 1)); Status.Bits.Time_Write = 1; // 置位写时钟标志 } IIC_Start(); } // ========================================================== // IIC初始化函数 // 通信速率:总线时钟40分频,1MHZ // ========================================================== void IIC_Init(void) { IIC0_IBSR_IBAL = 1; // 清零仲裁丢失位 // initial iic IIC0_IBFD = 0X07; // 设置时钟为总线时钟频率40分频,1MHZ IIC0_IBCR |=0xC0; // 使能IIC,IIC总线中断使能 } // ========================================================== // IIC Start Function // 注意:1. 启动IIC后,由中断函数控制IIC的读取与写入 // 2. 此函数只供IIC_Function()函数调用 // ========================================================== void IIC_Start(void) { while(IIC0_IBSR_IBB); // 等待总线空闲 IIC0_IBCR |= 0X30; // 主模式,选择发送,产生起始信号 while(IIC0_IBSR_IBB==0); // 等待总线忙 IIC0_IBDR = IIC_WADDR; // 写IBDR,启动发送 } // ============================================== // IIC中断函数 // ============================================== interrupt void IIC_Int(void) { static char tcount = 0, rcount = 0; // 发送,接收计数器 // 修改时钟 if(Status.Bits.Time_Write == 1) { // IIC 发送 if(IIC0_IBCR_TX_RX == 1) { if((tcount == 0) || (tcount == 11)) { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; // 清除标志位 IIC0_IBDR = 0x00; // 写地址 tcount++; } // 发送控制字: 0x02,W=1,置位写 else if((tcount == 1)|| (tcount == 12)) { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; // 清除标志位 if(tcount == 1) IIC0_IBDR = 0x02; // W = 1 else IIC0_IBDR = 0X00; // W = 0 tcount++; } else if(tcount == 2) { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; // 清除标志位 IIC0_IBDR = 0x00; // enable oscillator tcount++; } else if(tcount == 10) // 最后一个字节 { IIC0_IBCR &= 0XDF; // 1-0,产生STOP信号,进入从模式 IIC0_IBSR_IBIF = 1; // 清除标志位 while(IIC0_IBSR_IBB); // 等待总线空闲 IIC0_IBCR |= 0X30; // 主模式,选择发送,产生起始信号 while(IIC0_IBSR_IBB==0); // 等待总线忙 IIC0_IBDR = IIC_WADDR; // 写IBDR,启动发送 tcount++; } else if(tcount == 13) // 结束 { IIC0_IBCR &= 0XDF; // 1-0,产生STOP信号,进入从模式 IIC0_IBSR_IBIF = 1; // 清除标志位 // 复位 tcount = 0; Status.Bits.Time_Write = 0; } else { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; // 清除标志位 IIC0_IBDR = TimeStr_W[tcount-3]; // 写,数据发送开始 tcount++; } } } // 读取时钟 else { // 发送环节: IIC地址在读取时钟函数中发送,此处还需发送的有:地址,IIC写地址 if(IIC0_IBCR_TX_RX == 1) // 1: 发送 { tcount++; switch(tcount) { // 发送要读的单元地址 case 1: { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; IIC0_IBDR = 0X00; // 地址为0x00 break; } case 2: // 置位读标志 { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; IIC0_IBDR = 0X01; // R = 1 break; } case 3: { IIC0_IBCR &= 0XDF; // 1-0,产生STOP信号,进入从模式 IIC0_IBSR_IBIF = 1; // 清除标志位 // 从新启动IIC while(IIC0_IBSR_IBB); // 等待总线空闲 IIC0_IBCR |= 0X30; // 主模式,选择发送,产生起始信号 while(IIC0_IBSR_IBB==0); // 等待总线忙 IIC0_IBDR = IIC_WADDR; // 写IBDR,启动发送 break; } case 4: { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; IIC0_IBDR = 0X00; // 地址为0x00 break; } case 5: { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; IIC0_IBDR = 0X00; // R = 0 break; } // 此语句无实际意义,仅用此语句将指针跳到0x02处 case 6: { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; // 清除标志位 IIC0_IBDR = 0x00; // enable oscillator break; } // 发送IIC读地址 case 7: { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBCR_RSTA = 1; // 产生连续启动 IIC0_IBSR_IBIF = 1; // 清除中断标志 IIC0_IBDR = IIC_RADDR; // 发送从机读地址 break; } // 读地址发送完毕 case 8: { while(IIC0_IBSR_RXAK == 1); // 等待应答信号 IIC0_IBSR_IBIF = 1; IIC0_IBCR_TX_RX = 0; // 接收 IIC0_IBCR_TXAK = 0; // 接收完后发送应答 IIC0_IBDR; // 空读启动接收 tcount = 0; break; } } } // 发送环节结束 // 接收数据环节 else { // 接收到最后一个字节 if(rcount == 7) { IIC0_IBCR &= 0XDF; // 1-0,产生STOP信号 IIC0_IBSR_IBIF = 1; // 清中断标志 rcount = 0; // 复位rount Status.Bits.Time_Read = 0; } // 接收第5+1个字节不产生应答信号 else if(rcount == 6) { IIC0_IBSR_IBIF = 1; // 清标志位 IIC0_IBCR_TXAK = 1; // 接收完下一个字节后不发送应答信号 TimeStr[rcount] = IIC0_IBDR; // 接收,并启动下一个字节接收 rcount++; } // 非最后及倒数第一个字节 else { IIC0_IBSR_IBIF = 1; TimeStr[rcount] = IIC0_IBDR; // 接收,并启动下一次接收 rcount++; } } } }   

后记:此程序IIC总线时钟速率为1MHZ,采用XGATE处理IIC中断,之间会有等待 过程,最长等待为发送停机信号及重新启动IIC部分。

你可能感兴趣的:(function,cmd,byte)