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.
之前发帖子时发错了论坛分区了,经提醒后只能重新再这里发一下帖子,问题详细描述请移步步:e2echina.ti.com/.../523061
平台描述:
DSP28335,外部晶振30M,配置系统时钟150M,使能I2C时钟,I2Cmodule时钟为10M,配置通信波特率400K,采用硬件I2C通信方式,I2C的SCL和SDA硬件上拉4.7k,
外设为SHT30温湿度传感器模块,供电3.3V,,和DSP的I2C引脚直连,SHT30模块的ADDR引脚连接到VDD上,其设备地址为0x45
编译器版本CCS6.1,Win10
现状描述:
DSP通过I2C总线和外设SHT30进行通信,获取温度和湿度的数据。采用进行查询,判断状态为的方式进行,参考
http://bbs.eeworld.com.cn/thread-535531-1-1.html这个网站上的程序,虽然在写数据时在打印消息上没有看到有出错,但是通过示波器看波形却是不正常的,本来一发送一个字节就要有8个时钟脉冲,实际只有1~2个。且程序在写完后,接着的读取操作中卡住了。且卡住时,此时的SCL输出变为低电平了。
(上图为整个操作的波形)
(上图为前两次写的波形)
(上图为第二次写和第一次读的波形)
还有一个问题,关于DSP的I2C读取操作的。对于那些在读取数据前,不需要先发送指定的地址,直接读取就可以的的外设,怎么做?目前我网上看到的都是需要先发送一个地址之类的。如上面提到的SHT30、TDF8541等外设都不需要发送指定地址才能读的。但是如果不先写,好像就不能用ARDY判断当前是否可读了?
目前在google,查找TI等论坛后没有找到相关的解决方法,发帖求解各位TI工程师和论坛工程师。
源码如下:
1. 配置主时钟为150M:(外部晶振30M)
InitPll(DSP28_PLLCR,DSP28_DIVSEL);//#define DSP28_PLLCR 10,#define DSP28_DIVSEL 2
2. 使能I2C时钟:
SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 1; // I2C
3. 配置I2C的引脚:
InitI2CGpio() { EALLOW; // // Enable internal pull-up for the selected pins // Pull-ups can be enabled or disabled disabled by the user. // This will enable the pullups for the specified pins. // Comment out other unwanted lines. // GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0; // Enable pull-up for GPIO32 (SDAA) GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0; // Enable pull-up for GPIO33 (SCLA) // // Set qualification for selected pins to asynch only // This will select asynch (no qualification) for the selected pins. // Comment out other unwanted lines. // GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3; // Asynch input GPIO32 (SDAA) GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3; // Asynch input GPIO33 (SCLA) // // Configure SCI pins using GPIO regs // This specifies which of the possible GPIO pins will be I2C functional // pins. Comment out other unwanted lines. // GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1; // Configure GPIO32 to SDAA GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1; // Configure GPIO33 to SCLA EDIS; }
4. I2C初始化
void I2CA_Init(Uint16 iSlaveAddress,CommunicateSpeed_Enum eCommunicateSpeed) { //IRS must be 0 while you configure/reconfigure the i2c module I2caRegs.I2CMDR.bit.IRS = 0; // Initialize I2C I2caRegs.I2CSAR = iSlaveAddress; // Slave address // Configure I2C Module Clock #if (CPU_FRQ_150MHZ) // Default - For 150MHz SYSCLKOUT I2caRegs.I2CPSC.all = 13; // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz) #endif #if (CPU_FRQ_100MHZ) // For 100 MHz SYSCLKOUT I2caRegs.I2CPSC.all = 9; // Prescaler - need 7-12 Mhz on module clk (100/10 = 10MHz) #endif // Configure Communicate Speed if ( CommunicateSpeed_100K == eCommunicateSpeed ) { I2caRegs.I2CCLKL = 60; // NOTE: must be non zero I2caRegs.I2CCLKH = 30; // NOTE: must be non zero } else if ( CommunicateSpeed_400K == eCommunicateSpeed ) { I2caRegs.I2CCLKL = 10; // NOTE: must be non zero I2caRegs.I2CCLKH = 5; // NOTE: must be non zero } else { printf("Current I2C Communicate Speed Not Support"); } // Configure Interrupt Source Enable I2caRegs.I2CIER.all = 0x00; // Disable interrupts I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset // Stop I2C when suspended //I2caRegs.I2CMDR.bit.IRS = 1; // Take I2C out of reset // Stop I2C when suspended I2caRegs.I2CFFTX.all = 0x0000; // Disable FIFO mode and TXFIFO I2caRegs.I2CFFRX.all = 0x0000; // Disable RXFIFO, clear RXFFINT, return; }
5. I2C写参数
Uint16 WriteData(Uint16 iSlaveAddress,Uint16 *pTxData,Uint16 iTxDataLen) { Uint16 i; // Wait until the STP bit is cleared from any previous master communication. // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. while(I2caRegs.I2CMDR.bit.STP == 1); // Check if bus busy while(I2caRegs.I2CSTR.bit.BB == 1); while(0 == I2caRegs.I2CSTR.bit.XRDY); I2caRegs.I2CSAR = iSlaveAddress; // Slave address; I2caRegs.I2CCNT = iTxDataLen; I2caRegs.I2CDXR = pTxData[0]; I2caRegs.I2CMDR.all = 0x6E20; for (i=0; i<iTxDataLen-1; i++) { printf("\r\n w1 here,I2CMDR:0x%04x,I2CSTR:0x%04x,I2CCNT:0x%04x,I2CDXR:0x%04x",I2caRegs.I2CMDR.all,I2caRegs.I2CSTR.all,I2caRegs.I2CCNT,I2caRegs.I2CDXR); while(0 == I2caRegs.I2CSTR.bit.XRDY); I2caRegs.I2CDXR = pTxData[i+1]; if (I2caRegs.I2CSTR.bit.NACK == 1) { printf("\r\n w busy here1"); return I2C_BUS_BUSY_ERROR; } } return I2C_SUCCESS; }
6. I2C读函数
Uint16 ReadData(Uint16 iSlaveAddress,Uint16 *pTxData,Uint16 iTxDataLen,Uint16 *pRxData,Uint16 iRxDataLen) { Uint16 i,Temp; // Wait until the STP bit is cleared from any previous master communication. // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. while(I2caRegs.I2CMDR.bit.STP == 1); // Check if bus busy while(I2caRegs.I2CSTR.bit.BB == 1); I2caRegs.I2CSAR = iSlaveAddress; // Slave address;; if ( (0 != iTxDataLen) && (NULL != pTxData) ) //判断是否需要在读取前先发送数据 { while(0 == I2caRegs.I2CSTR.bit.XRDY); I2caRegs.I2CCNT = iTxDataLen; I2caRegs.I2CDXR = pTxData[0]; I2caRegs.I2CMDR.all = 0x2620; if (I2caRegs.I2CSTR.bit.NACK == 1) { return I2C_BUS_BUSY_ERROR; } for (i=0; i<iTxDataLen-1; i++) { while(0 == I2caRegs.I2CSTR.bit.XRDY); I2caRegs.I2CDXR = pTxData[i+1]; if (I2caRegs.I2CSTR.bit.NACK == 1) { return I2C_BUS_BUSY_ERROR; } } DELAY_US(50); } printf("\r\n r here1,I2CMDR:0x%04x,I2CSTR:0x%04x",I2caRegs.I2CMDR.all,I2caRegs.I2CSTR.all); while(0 == I2caRegs.I2CSTR.bit.XRDY); //判断这个是否合适?? // Wait Register-access-ready //while(I2caRegs.I2CSTR.bit.ARDY == 0); //如果不需要先写入的读取,用这个判断也不合适?? I2caRegs.I2CCNT = iRxDataLen; I2caRegs.I2CMDR.all = 0x2C20; if (I2caRegs.I2CSTR.bit.NACK == 1) { return I2C_BUS_BUSY_ERROR; } for(i=0; i<iRxDataLen; i++) { printf("\r\n r here2,I2CMDR:0x%04x,I2CSTR:0x%04x",I2caRegs.I2CMDR.all,I2caRegs.I2CSTR.all); while(0 == I2caRegs.I2CSTR.bit.RRDY); //卡在这里 Temp = I2caRegs.I2CDRR; if (I2caRegs.I2CSTR.bit.NACK == 1) { return I2C_BUS_BUSY_ERROR; } *pRxData = Temp; pRxData++; } return I2C_SUCCESS; }
在while(0 == I2caRegs.I2CSTR.bit.RRDY);卡住,程序停止运行了。在其上一句调试信号为 r here2,I2CMDR:0x0c20,I2CSTR:0x3438
看sprg03b手册上说,在RSFULL=1或XMST=0时会将SCL拉低,但是在卡住的调试上看,这两个条件都不满足,但是SCL却输出低了。(将SCL断开和外设的连接,测试DSP侧的SCL信号,为低)