打印
[技术问题解答]

KL15关于IIC的问题(已解决)

[复制链接]
5073|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wxb18k|  楼主 | 2014-9-2 14:44 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
沙发
wxb18k|  楼主 | 2014-9-2 14:51 | 只看该作者
我用的是FRDM-K25Z_demo例程,但是一直无法调通AT24c256的使用,AT24C256与1MHz I2C总线兼容,以下是我的主要配置(PTE18和19为SCL和SDA):
/*********************************************************************************************************
** 全局变量
*********************************************************************************************************/
const INT16U GusSCLDivider[64] = {
    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};

/*
* 用于进行I2C通讯的全局变量   
*/
volatile INT8U     I2C_sla;                                             /* I2C器件从地址                */
volatile INT32U    I2C_suba;                                            /* I2C器件内子地址              */
volatile INT8U     I2C_suba_num;                                        /* I2C子地址长度                */
volatile INT8U     *I2C_buf;                                            /* 数据缓冲区指针               */
volatile INT32U    I2C_num;                                             /* 要读取/写入的数据个数        */
volatile INT8U     I2C_end;                                             /* I2C总线结束标志              */
volatile INT8U     I2C_restart;                                         /* I2C总线结重复起始标?         */

static   INT8U     I2C_irq_status;                                      /* I2C中断读写操作控制          */
                                                                        /* 1--读模式                    */
                                                                        /* 0--写模式                    */
volatile INT8U     I2C_sla_dir;         /*  从机控制
                                         *  1--读取操作
                                         *  0--写操作
                                         */



/*********************************************************************************************************
** Function name:           i2c0Init
** Descriptions:            I2C初始化
** input parameters:        none
** output parameters:       none
** Returned value:          none
** Created by:              Li Xiang
** Created Date:            2012-12-14
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
*********************************************************************************************************/
void i2c0Init(void)
{
    INT32U ulBaudRate = 0;
    INT32U i = 0;
    INT32U j = 0;
#if 1
    PORT_ENABLE_CLK(MKL_PORTE);
    IO_FUN_SEL(MKL_PORTE,18,4);                                         /* SCL初始化                    */
    IO_FUN_SEL(MKL_PORTE,19,4);                                         /* SDA初始化                    */
#endif
#if 0
    PORT_ENABLE_CLK(MKL_PORTB);
    IO_FUN_SEL(MKL_PORTB,0,2);                                          /* SCL初始化                    */
    IO_FUN_SEL(MKL_PORTB,1,2);                                          /* SDA初始化                    */
#endif   
#if 0
    PORT_ENABLE_CLK(MKL_PORTB);
    IO_FUN_SEL(MKL_PORTB,2,2);                                          /* SCL初始化                    */
    IO_FUN_SEL(MKL_PORTB,3,2);                                          /* SDA初始化                    */
#endif   
#if 0
    PORT_ENABLE_CLK(MKL_PORTC);
    IO_FUN_SEL(MKL_PORTC,8,2);                                          /* SCL初始化                    */
    IO_FUN_SEL(MKL_PORTC,9,2);                                          /* SDA初始化                    */
#endif   
    i2c0ClkEnable();                                                    /* 打开I2C0时钟                 */

#if (I2C0_MODE == I2C_MASTER)
    ulBaudRate = SystemBusClock / (I2C0_BAUD_RATE << I2C0_MUL);         /* 计算SCL divider              */
    for(j = 0; j < I2C0_BT_ERROR; j++) {
        for(i = 0; i < 64; i++) {
            if(((ulBaudRate - GusSCLDivider[i]) <= j) || ((GusSCLDivider[i] - ulBaudRate) <= j) ){
                break;
            }   
        }
        if (i != 64) {
            break;
        }   
    }

    if (j == I2C0_BT_ERROR) {
        printf("I2C0 BT SET ERROR\r\n");        
        while(1);
    }  
    I2C0_F = (I2C0_MUL << 6) | i;                                       /* 配置波特率                   */
     I2C0_C1 |=  (1 << 5);                                            /* 选择主机模式                 */

#endif
#if (I2C0_MODE == I2C_SLAVER)
    I2C0_C1 |=  (1 << 7)|                                               /* 响应地址                     */
                (I2C0_SLAVER_ADDRESS_MODE << 6)|                        /* 从机地址类型定义             */
                (I2C0_SLAVER_ADR_MATCH << 3)|                           /* 地址匹配设置                 */                 
                ((I2C0_SLAVER_ADR >> 8) & 7UL);                         /* 高位地址设置                 */
    I2C0_A1 = I2C0_SLAVER_ADR;                                          /* 从机地址定义                 */
    I2C0_RA = I2C0_RANGE_SLAVER_ADR;

//     I2C0_C1 &=  ~(1 << 5);                                           /* 选择从机模式                 */

#endif

//     I2C0_C1 |=  (1 << 5);                                            /* 发送起始位与停止位           */               
//     I2C0_C1 &=  ~(1 << 5);                                           /* 初始化总线                   */                                          

    I2C0_S |= (1 << 1)|                                                 /* 清除标志                     */
              (1 << 4);
    I2C0_FLT    |= 1 << 6;         

    I2C0_C1 |=  (1 << 7)|                                               /* 使能I2C0                     */
                (1 << 6);                                               /* 使能IRQ                      */
    I2C0_FLT  |= 1 << 5;                                                /* 使能停止中断                 */

    NVIC_EnableIRQ(I2C0_IRQn);
    NVIC_SetPriority(I2C0_IRQn,3);                                      /* 用户自己定义                 */        

}

/*********************************************************************************************************
** Function name:           i2c0SendByte
** Descriptions:            I2C0发送单字节函数
** input parameters:        sla:从机地址 dat:数据缓冲区指针
** output parameters:       none
** Returned value:          none
** Created by:              Li Xiang
** Created Date:            2012-12-14
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
*********************************************************************************************************/
INT8U i2c0SendByte(INT8U sla, INT8U *dat)
{
    I2C_sla         = sla;                                              /* 写操作的器件地址             */
    I2C_buf         = dat;                                              /* 待发送的数据缓冲区指针       */
    I2C_num         = 1;                                                /* 发送1字节数据                */
    I2C_suba_num    = 0;                                                /* 无子地址                     */
    I2C_sla_dir     = 0;                                                /* 写操作                       */
    I2C_irq_status  = 0;                                                /* 写模式                       */
    I2C_end         = 0;   

    I2C0_C1 |=  (1 << 5);                                               /* 发送起始位,主模式           */               
    I2C0_D   = I2C_sla & 0xFE;                                          /* 将写地址写入数据寄存器       */
    I2C0_C1 |=  (1 << 4);                                               /* 发送模式                     */               

    return( Wait_I2c_End(20));
}

/*********************************************************************************************************
** Function name:           i2c0WriteNByte
** Descriptions:            I2C0发送多字节函数
** input parameters:        sla:从机地址 suba_type: 子地址类型
**                          suba:子地址 s:数据缓冲区指针 num:数据长度
** output parameters:       none
** Returned value:          none
** Created by:              Li Xiang
** Created Date:            2012-12-14
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
*********************************************************************************************************/
INT8U i2c0WriteNByte(INT8U sla, INT8U suba_type, INT32U suba, INT8U *s, INT32U num)
{
    I2C_sla         = sla;                                              /* 写操作的器件地址             */
    I2C_suba        = suba;                                             /* 子地址类型                   */
    I2C_num         = num;                                              /* 发送n字节数据                */
    I2C_suba_num    = suba_type;                                        /* 子地址类型                   */

    I2C_buf         = s;                                                /* 待发送的数据缓冲区指针       */
    I2C_sla_dir     = 0;                                                /* 写操作                       */
    I2C_irq_status  = 0;                                                /* 写模式                       */
    I2C_end         = 0;   
    I2C_restart     = 0;

    I2C0_C1 |=  (1 << 5);                                               /* 发送起始位,主模式           */  
    I2C0_C1 |=  (1 << 4);                                               /* 发送模式                     */      
    I2C0_D   = I2C_sla & 0xFE;                                          /* 将写地址写入数据寄存器       */

    return( Wait_I2c_End(20));
}

/*********************************************************************************************************
** Function name:           i2c0ReadNByte
** Descriptions:            I2C0接收多字节函数
** input parameters:        sla:从机地址 suba_type: 子地址类型
**                          suba:子地址 s:接收数据缓冲区指针 num:数据长度
** output parameters:       none
** Returned value:          none
** Created by:              Li Xiang
** Created Date:            2012-12-14
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
*********************************************************************************************************/
INT8U i2c0ReadNByte(INT8U sla, INT8U suba_type, INT32U suba, INT8U *s, INT32U num)
{
    I2C_sla         = sla;                                              /* 写操作的器件地址             */
    I2C_suba        = suba;                                             /* 子地址类型                   */
    I2C_num         = num;                                              /* 发送n字节数据                */
    I2C_suba_num    = suba_type;                                        /* 子地址类型                   */

    I2C_buf         = s;                                                /* 接收数据缓冲区指针           */
    I2C_sla_dir     = 1;                                                /* 写操作                       */
    I2C_irq_status  = 0;                                                /* 写模式                       */
    I2C_end         = 0;   
    I2C_restart     = 0;

    I2C0_C1 |=  (1 << 5);                                               /* 发送起始位,主模式           */               
    I2C0_C1 |=  (1 << 4);                                               /* 发送模式                     */
    I2C0_D   = I2C_sla & 0xFE;                                          /* 将写地址写入数据寄存器       */   
    Wait_I2c_Restart(20);
    I2C0_D   = (I2C_sla & 0xFE) + 1;                                    /* 将读地址写入数据寄存器       */

    return( Wait_I2c_End(20));
}


使用特权

评论回复
板凳
wxb18k|  楼主 | 2014-9-2 14:53 | 只看该作者
总觉得这个历程的读写函数怪怪的,是我的配置有问题还是读写函数或者是初始化错了啊?

使用特权

评论回复
地板
FSL_TICS_Robin| | 2014-9-2 14:59 | 只看该作者
楼主你好
请问你参考的是哪里的I2c函数呢?

使用特权

评论回复
5
FSL_TICS_Robin| | 2014-9-2 15:05 | 只看该作者
另外要注意你的KL25芯片mask号对应勘误表,可以从 KL2x: Kinetis KL2x USB MCU 文档页面下载。
KINETIS_L_1N97F和KINETIS_L_2N97F里都有一条与I2C有关的提示

使用特权

评论回复
6
wxb18k|  楼主 | 2014-9-2 15:06 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-2 14:59
楼主你好
请问你参考的是哪里的I2c函数呢?

i2c0WriteNByte和i2c0ReadNByte

使用特权

评论回复
7
wxb18k|  楼主 | 2014-9-2 15:11 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-2 14:59
楼主你好
请问你参考的是哪里的I2c函数呢?

这两个函数我觉得好奇怪,有好几个输入参数都没用到……

使用特权

评论回复
8
FSL_TICS_Robin| | 2014-9-2 15:36 | 只看该作者
你用的是周立功提供的FRDM-K25Z_demo例程包是吧?
请问你用单字节发送的函数能成功通信不?

使用特权

评论回复
9
wxb18k|  楼主 | 2014-9-3 10:27 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-2 15:36
你用的是周立功提供的FRDM-K25Z_demo例程包是吧?
请问你用单字节发送的函数能成功通信不? ...

不行啊,感觉怪怪的,你们有没有IIC的例程啊?

使用特权

评论回复
10
FSL_TICS_Robin| | 2014-9-3 10:32 | 只看该作者
wxb18k 发表于 2014-9-3 10:27
不行啊,感觉怪怪的,你们有没有IIC的例程啊?

飞思卡尔官网有提供IIC例程呢
手把手学会官方例程<十三>:KL25 加速度传感器PE例程
【经验分享】KL25 I2C结合加速度传感器代码(CW工程)

【经验分享】KL25 I2C结合加速度传感器代码(IAR工程)


使用特权

评论回复
11
wxb18k|  楼主 | 2014-9-3 10:55 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-3 10:32
飞思卡尔官网有提供IIC例程呢
手把手学会官方例程:KL25 加速度传感器PE例程
【经验分享】KL25 I2C结合加 ...

有keil工程的吗?

使用特权

评论回复
12
FSL_TICS_Robin| | 2014-9-3 11:00 | 只看该作者
wxb18k 发表于 2014-9-3 10:55
有keil工程的吗?

如果你有下载飞思卡尔官网提供的KL25_SC: FRDM-KL25Z and TWRKL25Z48M Sample Code Package.
那么正确安装此工程包后将在安装路径下找到如下工程,其中就包含Keil环境下的i2c程序。
E:\KL25 Sample Code\kl25_sc_rev10\klxx-sc-baremetal\build\keil\twr-kl25Demo

使用特权

评论回复
13
wxb18k|  楼主 | 2014-9-3 11:19 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-3 10:32
飞思卡尔官网有提供IIC例程呢
手把手学会官方例程:KL25 加速度传感器PE例程
【经验分享】KL25 I2C结合加 ...

我打开了其中的IAR工程,发现初始化函数有点奇怪:
void init_I2C(void)
{
  SIM_SCGC5 = SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK;


  SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; //Turn on clock to I2C` module

  /* configure GPIO for I2C0 function */
  PORTC_PCR10 = PORT_PCR_MUX(2);
  PORTC_PCR11 = PORT_PCR_MUX(2);

  I2C0_F  = 0x14;       /* set MULT and ICR */
  I2C0_C1 = I2C_C1_IICEN_MASK;       /* enable IIC */
}

  SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; 打开的是I2C0的时钟但是PTC10和11是I2C1,为什么啊

使用特权

评论回复
14
FSL_TICS_Robin| | 2014-9-3 11:32 | 只看该作者
wxb18k 发表于 2014-9-3 11:19
我打开了其中的IAR工程,发现初始化函数有点奇怪:
void init_I2C(void)
{

没找到你提到的函数呢,还请明示哪个链接下载的程序或哪个工程?

使用特权

评论回复
15
wxb18k|  楼主 | 2014-9-3 12:26 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-3 11:32
没找到你提到的函数呢,还请明示哪个链接下载的程序或哪个工程?

https://bbs.21ic.com/icview-677562-1-1.html这个工程\KL25_I2C\KL25_I2C\src\drivers\i2c

使用特权

评论回复
16
FSL_TICS_Robin| | 2014-9-3 12:42 | 只看该作者
wxb18k 发表于 2014-9-3 12:26
https://bbs.21ic.com/icview-677562-1-1.html这个工程\KL25_I2C\KL25_I2C\src\drivers\i2c

此工程没有调用这个函数,因为10楼后面两个例程都是从K60 100MHz的例程包里移植过来的,所以可能drivers里的函数可能有些问题。
如果你要看drivers,那么KL25_SC里也有针对KL25芯片的。

使用特权

评论回复
17
wxb18k|  楼主 | 2014-9-3 12:46 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-3 12:42
此工程没有调用这个函数,因为10楼后面两个例程都是从K60 100MHz的例程包里移植过来的,所以可能drivers ...

KL25_SC里的代码好乱,好复杂

使用特权

评论回复
18
wxb18k|  楼主 | 2014-9-3 13:47 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-3 12:42
此工程没有调用这个函数,因为10楼后面两个例程都是从K60 100MHz的例程包里移植过来的,所以可能drivers ...

你可以给我写一个用在AT24C256的驱动代码吗?我这边实在是没办法

使用特权

评论回复
19
FSL_TICS_Robin| | 2014-9-3 14:29 | 只看该作者
wxb18k 发表于 2014-9-3 13:47
你可以给我写一个用在AT24C256的驱动代码吗?我这边实在是没办法

IIC只有2根线,你用示波器完全可以抓取一段通信波形。
请拿抓取的波形与AT24C256的操作时序比较来查看问题到底出在哪。

建议还是先用周立功他们的例程,如果你下载安装了他们的FRDM-K25Z_demo包那么在安装路径比如F:\FRDM-K25Z_demo\I2C\Kinetis_l_Demo_I2C_Master内能找到KL25作为主机端的I2C例程。

使用特权

评论回复
20
wxb18k|  楼主 | 2014-9-3 14:47 | 只看该作者
FSL_TICS_Robin 发表于 2014-9-3 14:29
IIC只有2根线,你用示波器完全可以抓取一段通信波形。
请拿抓取的波形与AT24C256的操作时序比较来查看问 ...

看的就是这个例程,头疼啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

140

帖子

1

粉丝