赞
踩
I2C、I2C或IIC通信提供了一种可以与若干设备之间进行通信的方法。
在总线最大负载下,该接口可被设计为100 kbit/s的传输速率。
该接口处理信息波特率最大可达系统时钟的二十分之一,以此减少总线负载。
最大总线电容为400pf限制了设备的最大通信长度和可连接从设备数。
I2C模块具有以下特点:
• 兼容IIC-bus规格
• Multimaster操作
• 软件可编程为64种不同的串行时钟频率之一
• Software-selectable确认位
• 中断驱动的逐字节数据传输
• 主从切换下自动仲裁
• 呼叫地址识别中断
• 启动和停止信号的产生和检测
• 重复启动信号的产生和检测
• 确认位产生和检测
• bus忙检测
• General调用识别
• 10位地址扩展
• 可编程故障输入筛选
• 低功率模式唤醒slave地址匹配
• 多从地址支持
• DMA支持
具体初始化代码如下:
重点:
1.MULT = 2 对应 mul = 4
2.ICR = 0x17 ICR为Clock rate时钟频率
从I2C Divider and Hold Values可得:
ICR SCL Divider SDA Hold Value SCL Hold (Start) Value SCL Hold (Stop) Value
17 128 21 58 65
则 I2C baud rate = bus speed (Hz)/(mul × SCL divider) 即 135MHz/(4 × 128) = 263.6718kHz
void I2C_Init(I2Cn I2CNum) { if(I2CNum == I2CNUM0) { SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; //开启 I2C0时钟 PORTA_PCR12 = PORT_PCR_MUX(8);// 配置 I2C0功能的 GPIO 接 PORTA_PCR12 = PORTA_PCR12|(1<<5);//设置为开漏模式 PORTA_PCR11 = PORT_PCR_MUX(8); PORTA_PCR11 = PORTA_PCR11|(1<<5);//设置为开漏模式 } I2C_F_REG(I2Cx[I2CNum]) = I2C_F_MULT(2) | I2C_F_ICR(0x17) ; //频率 / 波特率 frequency I2C_C1_REG(I2Cx[I2CNum]) = I2C_C1_IICEN_MASK;//使能 IIC0模块 // //无论I2C接口被配置成主机模式还是从机模式,收到一串数据后自动发送应答信号 // I2C_C1_REG(I2Cx[I2CNum]) &= ~I2C_C1_TXAK_MASK; //使能I2C0自动应答信号 }
IIC开始信号产生
void DrvI2CStart (I2Cn I2CNum)
{
I2C_C1_REG(I2Cx[I2CNum]) |= I2C_C1_TX_MASK + I2C_C1_MST_MASK;
}
再次产生开始信号
void DrvI2CReStart(I2Cn I2CNum)
{
I2C_C1_REG(I2Cx[I2CNum]) |= I2C_C1_RSTA_MASK ;
}
停止信号
void DrvI2CStop (I2Cn I2CNum)
{
I2C_C1_REG(I2Cx[I2CNum]) &= ~(I2C_C1_MST_MASK + I2C_C1_TX_MASK);//暂停信号
}
写一个字节
void DrvI2CWriteByte (I2Cn I2CNum, U8 Byte)
{
I2C_D_REG(I2Cx[I2CNum]) = Byte;
}
读一个字节
U8 DrvI2CReadByte(I2Cn I2CNum)
{
U8 Temp;
Temp = I2C_D_REG(I2Cx[I2CNum]);
return Temp;
}
启动IIC传输
void I2C_StartTransmission (I2Cn I2CNum, U8 SlaveID, IIC_MASTER_RW_MODE Mode)
{
SlaveID = ( SlaveID << 1 ) | Mode ; //确定写地址和读地址
DrvI2CStart(I2CNum);//send start signal
DrvI2CWriteByte(I2CNum, SlaveID);//send ID with W/R bit
}
I2C设置等待应答信号,开启则等待,关闭则不等待
void DrvI2CWaitAck(I2Cn I2CNum, IIC_ACK_MODE ModeType) { U16 Timeout; if(ModeType == I2C_ACK_ON) { while(!(I2C_S_REG(I2Cx[I2CNum]) & I2C_S_IICIF_MASK)) { if(Timeout>60000) //超时判断 { break; } else { Timeout++; } } I2C_S_REG(I2Cx[I2CNum]) |= I2C_S_IICIF_MASK; } else { I2C_C1_REG(I2Cx[I2CNum]) |= I2C_C1_TXAK_MASK; //关闭I2C的ACK } }
I2C主机读写模式配置
void DrvI2CSetMasterWRMode(I2Cn I2CNum, IIC_MASTER_RW_MODE ModeType)
{
if(ModeType == I2C_MASTER_READ)
{
I2C_C1_REG(I2Cx[I2CNum]) &= (~I2C_C1_TX_MASK);
}
else
{
I2C_C1_REG(I2Cx[I2CNum]) |= ( I2C_C1_TX_MASK);
}
}
延时
void DrvTimeDelay(U32 Timeout)
{
U32 Cnt;
for(Cnt = 0; Cnt < Timeout; Cnt++)
{
}
}
读取IIC设备指定地址寄存器的数据
U8 I2C_ReadAddr(I2Cn I2CNum, U8 SlaveID, U8 Addr) { U8 result; I2C_StartTransmission (I2CNum, SlaveID, I2C_MASTER_WRITE);//Send Slave Address DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CWriteByte(I2CNum, Addr);//Write Register Address DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CReStart(I2CNum);//Do a repeated start DrvI2CWriteByte(I2CNum, ( SlaveID << 1) | I2C_MASTER_READ );//Send Slave Address DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CSetMasterWRMode(I2CNum, I2C_MASTER_READ);//Put in Rx Mode DrvI2CWaitAck(I2CNum, I2C_ACK_OFF);//Turn off ACK since this is second to last byte being read result = DrvI2CReadByte(I2CNum);//Dummy read 虚假读取 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CStop(I2CNum);//Send stop since about to read last byte result = I2C_D_REG(I2Cx[I2CNum]);//Read byte return result; }
写IIC设备指定地址寄存器的数据
void I2C_WriteAddr(I2Cn I2CNum, U8 SlaveID, U8 Addr, U8 Data) { I2C_StartTransmission(I2CNum, SlaveID, I2C_MASTER_WRITE); //启动传输 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CWriteByte(I2CNum, Addr); //写地址 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CWriteByte(I2CNum, Data); //写数据 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CStop(I2CNum); DrvTimeDelay(5000); //延时太短的话,可能写出错 }
写IIC设备指定地址寄存器的数据 16位
void I2C_WriteAddr16(I2Cn I2CNum, U8 SlaveID, U8 Addr, U16 Data) { I2C_StartTransmission(I2CNum, SlaveID, I2C_MASTER_WRITE); //启动传输 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CWriteByte(I2CNum, Addr); //写地址 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CWriteByte(I2CNum, (U8)(Data>>8)); //写数据 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CWriteByte(I2CNum, (U8)Data); //写数据 DrvI2CWaitAck(I2CNum, I2C_ACK_ON); DrvI2CStop(I2CNum); DrvTimeDelay(5000); //延时太短的话,可能写出错 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。