专家,你好!I2C接口调试不通过,想请教一下,是怎么回事,我用示波器测试输出的SCL口,好像也是有信号的。但是程序调用出错,C6747_I2C_write()返回值正常应该是0,怎么老是返回-1。感觉好像就没有将数据发送出去一样,好像是寄存器配置有问题,但仔细看了遍,也没发现是什么问题呀,这个代码也是你推荐的那个开发板的代码。请你多多帮忙,谢谢!
#define I2C_BASE 0x01C22000 // 0x01E28000 #define I2C_OAR *( volatile Uint32* )( I2C_BASE + 0x00 )
#define I2C_ICIMR *( volatile Uint32* )( I2C_BASE + 0x04 )
#define I2C_ICSTR *( volatile Uint32* )( I2C_BASE + 0x08 )
#define I2C_ICCLKL *( volatile Uint32* )( I2C_BASE + 0x0C )
#define I2C_ICCLKH *( volatile Uint32* )( I2C_BASE + 0x10 )
#define I2C_ICCNT *( volatile Uint32* )( I2C_BASE + 0x14 )
#define I2C_ICDRR *( volatile Uint32* )( I2C_BASE + 0x18 )
#define I2C_ICSAR *( volatile Uint32* )( I2C_BASE + 0x1C )
#define I2C_ICDXR *( volatile Uint32* )( I2C_BASE + 0x20 )
#define I2C_ICMDR *( volatile Uint32* )( I2C_BASE + 0x24 )
#define I2C_ICIVR *( volatile Uint32* )( I2C_BASE + 0x28 )
#define I2C_ICEMDR *( volatile Uint32* )( I2C_BASE + 0x2C )
#define I2C_ICPSC *( volatile Uint32* )( I2C_BASE + 0x30 )
#define I2C_ICPID1 *( volatile Uint32* )( I2C_BASE + 0x34 )
#define I2C_ICPID2 *( volatile Uint32* )( I2C_BASE + 0x38 )
#define ICMDR_STP 0x0800
#define ICSTR_ICXRDY 0x0010
Int32 i2c_timeout = 0x10000;
//外部晶体是无源24MHz,
PINMUX8 = 0x00022022; // I2C0 I2C1
Int16 C6747_I2C_init( )
{
I2C_ICMDR = 0; // Reset I2C
I2C_ICPSC = 1; // Prescale to get I2C internal 3
I2C_ICCLKL = 13; // Config clk LOW I2C_ICCLKH = 5; // Config clk HIGH I2C_ICMDR |= ICMDR_IRS; // Release I2C from reset
return 0;
}
Int16 C6747_I2C_write( Uint16 i2c_addr, Uint8* data, Uint16 len )
{
Int32 timeout, i;
I2C_ICCNT = len; // Set length
I2C_ICSAR = i2c_addr; // Set I2C slave address
I2C_ICMDR = 0x6E20; // Set for Master Write
C6747_wait( 10 ); // Short delay
for ( i = 0 ; i < len ; i++ )
{
I2C_ICDXR = data[i]; // Write
timeout = i2c_timeout;
do
{
if ( timeout– < 0 )
{
C6747_I2C_reset( );
return -1;
}
} while ( ( I2C_ICSTR & ICSTR_ICXRDY ) == 0 );// Wait for Tx Ready
}
I2C_ICMDR |= ICMDR_STP; // Generate STOP
return 0;
}
noaming:
你好,可以单步调试一下程序,在
for ( i = 0 ; i < len ; i++ ) { I2C_ICDXR = data[i]; // Write
timeout = i2c_timeout; do { if ( timeout– < 0 ) { C6747_I2C_reset( ); return -1; } } while ( ( I2C_ICSTR & ICSTR_ICXRDY ) == 0 );// Wait for Tx Ready }
运行这段程序的时候,自己观察一下下面的寄存器
I2C_ICSTR & ICSTR_ICXRDY
的值是多少,仔细排查问题
Jiang YanJun:
回复 noaming:
专家,你好。我也看了 I2C_ICSTR 寄存器了, 程序运行到这里I2C_ICDXR = data[i],寄存器 I2C_ICSTR =0X400,当程序运行到这里 while ( ( I2C_ICSTR & ICSTR_ICXRDY ) == 0 );// Wait for Tx Ready,寄存器 I2C_ICSTR =0X1400.用示波器看了,可以看到只发送了10位数据 ,看了一下手册正好是I2c器件从地址,时钟配置也很正常,还请专家帮忙指导一下,谢谢了。
noaming:
回复 Jiang YanJun:
I2C_ICSTR =0X1400说明I2C总线忙,BB置1
Bus is busy. When the STT bit in ICMDR is set to 1, a restart condition is generated. BB is set by one ofthe following events:• The I2C has received or transmitted a START bit on the bus.• I2Cx_SCL is in a low state and the IRS bit in ICMDR is 0.
上面两种情形是BB置1的原因。根据你的说明,应该是发送最后一个字符出现的问题,你可以单步运行到这里查看一下上面两种,是哪一种情形。
Jiang YanJun:
回复 noaming:
Titan 你好。俺又仔细看了一遍,I2C_ICSTR =0X1406.IRS位在寄存器ICMDR中已经置位了,根据你的提示
应该是The I2C has received or transmitted a START bit on the bus.可是需要怎么设置呢,我搞了一天也没搞出来。
真的是无语了。。。。。。。寄存器设置如下: I2C_ICMDR = 0; // Reset I2C I2C_ICMDR = ICMDR_TRX // set for Transmitter mode | ICMDR_MST; // Set for Master Write
I2C_ICSAR = i2c_addr; // Set I2C slave address I2C_ICPSC = 9; // Prescale to get 7.5MHz I2C internal I2C_ICCLKL = 15; // Config clk LOW for 100kHz I2C_ICCLKH = 40; // Config clk HIGH for 100kHz I2C_ICSTR = I2C_ICSTR; while (!(I2C_ICIVR == 0)); I2C_ICMDR |= ICMDR_IRS; // Release I2C from reset
while (!(( I2C_ICSTR & ICSTR_BB ) == 0 )); I2C_ICMDR |= ICMDR_STT; //以上都是按TI手册中Configuring the I2C 步骤来的,已经核对了,没有问题 //下面两行是我自己加上的,加上了,也没有效果。 I2C_ICMDR |= ICMDR_STB; I2C_ICMDR |= ICMDR_RM;