This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

关于使用6713的I2C,SCLK被锁定的问题,请帮忙各位帮忙解答

Other Parts Discussed in Thread: CCSTUDIO

使用I2C通信,设置的用自发自收模式,应该是循环发送,结果发完一次后,SCLK就被锁定了,详细状况可见附图(逻辑分析仪抓取的),以下是代码

void I2C0_Init()
{
puts("HI,I2C Init!");

//进入复位 IRS = 0
I2C0_MDR &= ~0x20;

//配置寄存器
//系统时钟 预分频器 225MHz / (21 + 1) = 10.25 MHz
I2C0_PSC = (0x15);

//I2C 时钟分频器 10.25 / (50) = 200KHz
I2C0_CLKL = (0x0013); //19+6 = 25
I2C0_CLKH = (0x0013); //19+6 = 25

//退出复位
I2C0_MDR |= (0x20); //IRS = 1

//5-配置主机地址
I2C0_OAR = 0x05;

//中断设置 -- 接收产生中断
// I2C0_IER = (1 << 3);
}

int I2C_WriteData(char addr, char *array, int count)
{
// int i;
char *p;
p = array;

//先前是否发送完成 检查SST位是否为1
if((I2C0_MDR & (0x01<<11)) == 1)
{
puts("previous not finished!");
return 0;
}

//从机地址
I2C0_SAR = addr;

I2C0_STR |= (1<<12);

//检查总线是否空闲 1:表示忙
if((I2C0_STR & (1<<12)))
{
return 0;
}

//计数器
I2C0_CNT = 2;

//发送开启
//进入复位 IRS = 0
I2C0_MDR |= 0x6E60;

//发送数据
while(I2C0_STR & (0x01<<1)); //ASK
while(!(I2C0_STR & (0x1<<4))); //ICXRDY
I2C0_DXR = *p++;

while(I2C0_STR & (0x01<<1));
while(!(I2C0_STR & (0x1<<4)));
I2C0_DXR = *p++;

//I2C0_MDR |= (0x1<<11);

return p-array;
}

主函数

void main()
{
// int i;
char data[2] = {5, 2};

I2C0_Init();

while(1)
{
I2C_WriteData(0x0F, data, 2);
}
}

  • 关于停止位消失的问题,已经解决,应该是发送完最后一个字节,要延迟一会,才能产生,因为停止位有时序要求。

    但是,后面的数组还是没出来,SCLK继续被锁定

    修改的代码:

    //发送数据
    while(I2C0_STR & (0x01<<1)); //ASK
    while(!(I2C0_STR & (0x1<<4))); //ICXRDY
    I2C0_DXR = *p++;

    while(I2C0_STR & (0x01<<1));
    while(!(I2C0_STR & (0x1<<4)));
    I2C0_DXR = *p++;

    for(i=0; i<3200; i++);    //增加的

    修改后:

  • 试试附件DSK6713 I2C DLB例程, 看能不能在你板子上运行.

  • Zhang,

        示例工程文件不能直接打开,我重新建立工程,出现如下错误

    undefined first referenced
    symbol in file
    --------- ----------------
    _I2C_start C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\i2c_define.obj
    _I2C_rrdy C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\i2c_define.obj
    _I2C_xrdy C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\i2c_define.obj
    _I2C_readByte C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\i2c_define.obj
    _I2C_bb C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\i2c_define.obj
    _I2C_writeByte C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\i2c_define.obj
    _I2C_open C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj
    _PLL_deassert C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj
    _PLL_enable C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj
    _PLL_bypass C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj
    _PLL_reset C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj
    _I2C_sendStop C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj
    _I2C_configArgs C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj
    _I2C_close C:\\CCStudio_v3.1\\MyProjects\\i2c\\Debug\\main.obj

    我把头文件的放到C:\CCStudio_v3.1\C6000\cgtools\include  下还是不行,请问如何解决,多谢!

  • Zhang,

       不好意思,忘记加csl6713.lib了,示例文件能够运行,我研究下代码

  • 嗯, 例程能运行可以排除硬件问题了, 你对比一下代码, 有问题欢迎继续探讨

  • 终于搞出来了,总结起来有如下几点,也不知道对不对:

    1.两次发送之间的间隔要保证,因为起始位和停止位都有最短的脉冲宽度要求

    2.每次发送完之后也有类似的要求

    3.每次发送前,要把机器进入复位,把上次的状态清掉

    4.如果是循环发送,要把接收寄存器的内容读走

     更改后的程序如下

    #include <stdio.h>
    #include "i2c.h"

    void I2C0_Init()
    {
    puts("HI,I2C Init!");

    //进入复位 IRS = 0
    I2C0_MDR &= ~0x20;

    //配置寄存器
    //系统时钟 预分频器 225MHz / (21 + 1) = 10.25 MHz
    I2C0_PSC = (0x15);

    //I2C 时钟分频器 10.25 / (50) = 200KHz
    I2C0_CLKL = (0x0013); //19+6 = 25
    I2C0_CLKH = (0x0013); //19+6 = 25

    //退出复位 IRS = 1
    I2C0_MDR |= (0x20);

    //配置主机地址
    I2C0_OAR = 0x05;

    //中断设置 -- 接收产生中断
    // I2C0_IER = (1 << 3);
    }

    void I2C_EdmaInit(void)
    {

    }

    int I2C_WriteData(char addr, char *array, int count)
    {
    int i;
    char *p,*in_p;
    static char input[2];

    p = array;
    in_p = input;

    //保证起始位及停止位的时序
    for(i=0; i<3200; i++);

    //进入复位,目的是清空I2CO_STR的标志位,不然有些标志位会一直占住I2C模块
    I2C0_MDR &= ~0x20;

    //先前是否发送完成 检查SST位是否为1
    if((I2C0_MDR & (0x01<<11)) == 1)
    {
    puts("previous not finished!");
    return 0;
    }

    //从机地址
    I2C0_SAR = addr;

    I2C0_STR |= (1<<12);

    //检查总线是否空闲 1:表示忙
    while((I2C0_STR & (1<<12)));

    //计数器
    I2C0_CNT = 2;

    //发送开启
    //进入复位 IRS = 0
    I2C0_MDR |= 0x6E60;

    //发送数据
    while(I2C0_STR & (0x01<<1)); //ASK
    while(!(I2C0_STR & (0x1<<4))); //ICXRDY
    I2C0_DXR = *p++;

    //获取得到的数据
    while(I2C0_STR & (0x01<<11))
    {
    *in_p++ = I2C0_DRR;
    }

    //发送数据
    while(I2C0_STR & (0x01<<1));
    while(!(I2C0_STR & (0x1<<4)));
    I2C0_DXR = *p++;

    //获取得到的数据
    while(I2C0_STR & (0x01<<11))
    {
    *in_p++ = I2C0_DRR;
    }

    //停止位时序,去掉的话没有停止位
    for(i=0; i<3000; i++);

    //获取得到的数据
    while(I2C0_STR & (0x01<<11))
    {
    *in_p++ = I2C0_DRR;
    }

    return p-array;
    }

    char I2C_ReadDirRegister(int DirId, int reg)
    {
    return 0;
    }

    void i2c0_int()
    {
    puts("received!");
    }