基于Kinetis系列微控制器K60芯片的I2C接口函数程序说明1

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); //延时太短的话,可能写出错
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值