/*
 * LPLD_I2C_Init
 * I2C通用初始化函数
 * 
 * 参数:
 *    i2cx--选择I2C模块号
 *      |__I2C0           --I2C0号模块
 *      |__I2C1           --I2C1号模块
 *    port--通道端口位选择
 *      |__0              --I2C0(PTB2-I2C0_SCL PTB3-I2C0_SDA)
 *      |                 --I2C1(PTE0-I2C1_SDA PTE1-I2C1_SCL)
 *      |__1              --I2C0(PTD8-I2C0_SCL PTD9-I2C0_SDA)
 *      |                 --I2C1(PTC10-I2C1_SCL PTC11-I2C1_SDA)
 *    scl_frq--选择IIC SCL频率
 *      |__I2C_SCL_50KHZ  --50khz
 *      |__I2C_SCL_100KHZ --100khz
 *      |__I2C_SCL_150KHZ --150khz
 *      |__I2C_SCL_200KHZ --200khz
 *      |__I2C_SCL_250KHZ --250khz
 *      |__I2C_SCL_300KHZ --300khz
 * 输出:
 *    0--配置错误
 *    1--配置成功
 */
uint8 LPLD_I2C_Init(I2Cx i2cx, uint8 port, uint8 scl_frq)
{
  uint8 ps; 
  
  //参数检查
  ASSERT( i2cx <= I2C1);                            //判断I2Cx模块号
  ASSERT( scl_frq <= I2C_SCL_300KHZ);               //判断SCL频率
  ASSERT( port <= 1);                               //判断端口选择
  
  //总线频率50mhz
  //scl_frq=50mhz/(mul * scl div)
  if(scl_frq == I2C_SCL_50KHZ)
  {
    ps=0x33;
  }
  else if(scl_frq == I2C_SCL_100KHZ)
  {
    ps=0x2B;
  }
  else if(scl_frq == I2C_SCL_150KHZ)
  {
    ps=0x28;
  }
  else if(scl_frq == I2C_SCL_200KHZ)
  {
    ps=0x23;
  }
  else if(scl_frq == I2C_SCL_250KHZ)
  {
    ps=0x21;
  }
  else if(scl_frq == I2C_SCL_300KHZ)
  {
    ps=0x20;
  }
  else
    return 0;

  if(i2cx==I2C0)
  {
    if(!port)
    {
      /* configure GPIO for I2C0 function */
      PORTB_PCR2 = PORT_PCR_MUX(2);
      PORTB_PCR3 = PORT_PCR_MUX(2);   
    }
    else if(port==1)
    {
      /* configure GPIO for I2C0 function */
      PORTD_PCR8 = PORT_PCR_MUX(2);
      PORTD_PCR9 = PORT_PCR_MUX(2);   
    }
    else
      return 0;
    
    SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; //开启I2C0时钟
  }
  else if(i2cx==I2C1)
  {
    if(!port)
    {
      /* configure GPIO for I2C0 function */
      PORTE_PCR0 = PORT_PCR_MUX(6);
      PORTE_PCR1 = PORT_PCR_MUX(6);   
    }
    else if(port==1)
    {
      /* configure GPIO for I2C0 function */
      PORTC_PCR10 = PORT_PCR_MUX(2);
      PORTC_PCR11 = PORT_PCR_MUX(2);   
    }
    else
      return 0;
    
    SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK; //开启IIC1时钟
  }
  else
    return 0;
  
  I2C_F_REG(I2Cx_Ptr[i2cx]) = ps;
  I2C_C1_REG(I2Cx_Ptr[i2cx]) = I2C_C1_IICEN_MASK;      //使能I2Cx
  
  return 1;
}
示例#2
0
/*!
 *  @brief      I2C初始化,设置波特率
 *  @param      I2Cn_e      I2C模块(I2C0、I2C1)
 *  @param      baud        期待的波特率
 *  @return                 实际的波特率
 *  @since      v5.0
 *  Sample usage:       i2c_init(I2C0,400*1000);     // 初始化I2C0,期待的波特率为400k
 */
uint32 i2c_init(I2Cn_e i2cn, uint32 baud)
{
    if(i2cn == I2C0)
    {
        /* 开启时钟 */
#if defined(MK60DZ10)
        SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK;           //开启 I2C0时钟
#elif defined( MK60F15)
        SIM_SCGC4 |= SIM_SCGC4_IIC0_MASK;           //开启 I2C0时钟
#endif

        /* 配置 I2C0功能的 GPIO 接口 */
        if(I2C0_SCL == PTB0)
            port_init (PTB0, ALT2 | ODO | PULLUP );
        else if(I2C0_SCL == PTB2)
            port_init (PTB2, ALT2 | ODO | PULLUP );
        else if(I2C0_SCL == PTD8)
            port_init (PTD8, ALT2 | ODO | PULLUP );
        else
            ASSERT(0);                              //上诉条件都不满足,直接断言失败了,设置管脚有误?

        if(I2C0_SDA == PTB1)
            port_init (PTB1, ALT2 | ODO | PULLUP );
        else if(I2C0_SDA == PTB3)
            port_init (PTB3, ALT2 | ODO | PULLUP );
        else if(I2C0_SDA == PTD9)
            port_init (PTD9, ALT2 | ODO | PULLUP );
        else
            ASSERT(0);                              //上诉条件都不满足,直接断言失败了,设置管脚有误?
    }
    else
    {
        /* 开启时钟 */
#if defined(MK60DZ10)
        SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK;           //开启 I2C1时钟
#elif defined(MK60F15)
        SIM_SCGC4 |= SIM_SCGC4_IIC1_MASK;           //开启 I2C1时钟
#endif
        /* 配置 I2C1功能的 GPIO 接口 */
        if(I2C1_SCL == PTE1)
            port_init (PTE1, ALT6 | ODO | PULLUP );
        else if(I2C1_SCL == PTC10)
            port_init (PTC10, ALT2 | ODO | PULLUP );
        else
            ASSERT(0);                          //上诉条件都不满足,直接断言失败了,设置管脚有误?

        if(I2C1_SDA == PTE0)
            port_init (PTE0, ALT6 | ODO | PULLUP );
        else if (I2C1_SDA == PTC11)
            port_init (PTC11, ALT2 | ODO | PULLUP );
        else
            ASSERT(0);                          //上诉条件都不满足,直接断言失败了,设置管脚有误?
    }

    /* 设置频率 */

    // I2C baud rate = bus speed (Hz)/(mul × SCL divider)  即这里 50MHz/(1 ×128)=390.625kHz
    // SDA hold time = bus period (s) × mul × SDA hold value
    // SCL start hold time = bus period (s) × mul × SCL start hold value
    // SCL stop hold time = bus period (s) × mul × SCL stop hold value

    //查表 ICR 对应的  SCL_divider ,见 《K60P144M100SF2RM.pdf》第1468页的 I2C Divider and Hold Values
    uint16 ICR_2_SCL_divider[0x40]  =
    {
        20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, 48, 56, 68,
        48, 56, 64, 72, 80, 88, 104, 128, 80, 96, 112, 128, 144, 160, 192, 240,
        160, 192, 224, 256, 288, 320, 384, 480, 320, 384, 448, 512, 576, 640, 768, 960,
        640, 768, 896, 1024, 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840
    };

    uint8 mult;
    if(bus_clk_khz <= 50000)mult = 0;         //bus 一分频
    else  if(bus_clk_khz <= 100000)mult = 1;  //bus 二分频
    else      mult = 2;                       //bus 四分频

    uint16 scldiv =  bus_clk_khz * 1000 / ( (mult + 1) * baud );  //最佳的分频系数

    //需要从 ICR_2_SCL_divider 里找到 与最佳分频系数scldiv最相近的 分频系数
    uint8 icr, n = 0x40;
    uint16 min_Dvalue = ~0, Dvalue;

    while(n)                                            //循环里逐个扫描,找出最接近的 分频系数
    {
        n--;
        Dvalue = abs(scldiv - ICR_2_SCL_divider[n]);
        if(Dvalue == 0)
        {
            icr = n;
            break;                                      //退出while循环
        }

        if(Dvalue < min_Dvalue)
        {
            icr = n;
            min_Dvalue = Dvalue;
        }
    }

    I2C_F_REG(I2CN[i2cn])  = ( 0                        // I2C Frequency Divider register (I2Cx_F)  I2C分频寄存器   I2C最大波特率为 400k
                               | I2C_F_MULT(mult)        // 乘数因子 mul = MULT + 1
                               | I2C_F_ICR(icr)          // 时钟速率 = ICR_2_SCL_divider[ICR] ,查表获得 ICR 与 SCL_divider 映射关系
                             );

    /* 使能 IIC1 */
    I2C_C1_REG(I2CN[i2cn]) = ( 0
                               | I2C_C1_IICEN_MASK       //使能I2C
                               //| I2C_C1_IICIE_MASK       //使能中断
                             );

    return (  bus_clk_khz * 1000 / ( (mult + 1) * ICR_2_SCL_divider[icr])  );
}