请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:MSP430G2253 主题中讨论的其他器件:DLPC3478
您好、工程师:
我使用 MSP430G2553IPW20。 将其 P1.6和 P1.7连接到 DLPC 3478、IO 配置为模拟 I2C、发送的指令为36 9E 00 00。 测试表明将会发生数据包丢失、这将每几十到几百次发生一次。
下图显示了正常通信期间的时间序列:
下图显示了丢失照片的顺序:
过去使用 P1.4和 P1.5IO 对 I2C 进行仿真。 经过许多测试、都没有数据包丢失问题。 由于电路设计最近已更改、IO 已更改、代码刚刚交换了 IO 配置、因此发现了此问题。
您能帮助我分析一下出现了什么问题吗?
与 I2C 相关的硬件如下所示:
I2C 相关代码如下所示:
/***************************************************************************** ** ** TEXAS INSTRUMENTS PROPRIETARY INFORMATION ** ** (c) Copyright, Texas Instruments Incorporated, 2009 ** All Rights Reserved. ** ** Property of Texas Instruments Incorporated. Restricted Rights - ** Use, duplication, or disclosure is subject to restrictions set ** forth in TI's program license agreement and associated documentation. ******************************************************************************/ /************************************************************* * THIS PROGRAM IS PROVIDED "AS IS." TI MAKES NO WARRANTIES OR * REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, * INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR * COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE. * TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET * POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY * INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR * YOUR USE OF THE PROGRAM. * * IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL, * CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY * THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED * OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT * OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM. * EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF * REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS * OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF * USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S * AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF * YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS * (U.S.$500). * * Unless otherwise stated, the Program is written and copyrighted * by Texas Instruments is distributed as "freeware." You may, * only under TI's copyright in the Program, use and modify the * Program without any charge or restriction. You may * distribute to third parties, provided that you transfer a * copy of this license to the third party and the third party * agrees to these terms by its first use of the Program. In * jurisdictions in which use is not deemed acceptance of these * terms, no license is granted and no use is permitted. You * must reproduce the copyright notice and any other legend of * ownership on each copy or partial copy of the Program. * * You acknowledge and agree that the Program contains * copyrighted material, trade secrets and other TI proprietary * information and is protected by copyright laws, * international copyright treaties, and trade secret laws, as * well as other intellectual property laws. You agree that in * no event will you alter, remove or destroy any copyright * notice included in the Program. TI reserves all rights not * specifically granted under this license. Except as * specifically provided herein, nothing in this agreement * shall be construed as conferring upon you, by implication, * estoppel, or otherwise, any license or other right under any * TI patents, copyrights or trade secrets. *************************************************************/ #ifndef __i2c_master #define __i2c_master #ifdef __cplusplus extern "C" { #endif // defines #define I2C_NO_ACK 0 //***********functions 软件i2C**********************************/ uint08 I2C_PolledMasterWrite(uint08 device_addr, uint08* write_data, uint08 num_bytes); uint08 I2C_PolledMasterRead(uint08 device_addr, uint08* read_data, uint08 num_bytes); void I2C_Master_Init (void); void I2C_Master_Start(void); uint08 I2C_Master_Stop(void); uint08 I2C_MasterTransmitByte(uint08 data); uint08 I2C_MasterReceiveByte(void); //***********functions 软件i2C**********************************/ /* void i2c_hw_init(void);//不支持P14&P15 void set_devaddr(uint08 dev_addr); int i2c_hw_write(uint08 dev_addr, int32 inlen, unsigned char *pdata); int i2c_hw_read(uint08 dev_addr, int32 inlen, unsigned char *pdata); int i2c_dpp_write(uint08 dev_addr, unsigned char cmd , int outlen, unsigned char *pdata); int i2c_dpp_read(uint08 dev_addr, unsigned char cmd , int inlen, unsigned char *pdata); int i2c_sil9293_write(uint08 dev_addr, unsigned char cmd , int outlen, unsigned char *pdata); int i2c_sil9293_read(uint08 dev_addr, unsigned char cmd , int inlen, unsigned char *pdata); */ #ifdef __cplusplus /* matches __cplusplus construct above */ } #endif #endif // #ifndef __i2c_master
/***************************************************************************** ** ** TEXAS INSTRUMENTS PROPRIETARY INFORMATION ** ** (c) Copyright, Texas Instruments Incorporated, 2009 ** All Rights Reserved. ** ** Property of Texas Instruments Incorporated. Restricted Rights - ** Use, duplication, or disclosure is subject to restrictions set ** forth in TI's program license agreement and associated documentation. ******************************************************************************/ /************************************************************* * THIS PROGRAM IS PROVIDED "AS IS." TI MAKES NO WARRANTIES OR * REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, * INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR * COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE. * TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET * POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY * INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR * YOUR USE OF THE PROGRAM. * * IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL, * CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY * THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED * OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT * OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM. * EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF * REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS * OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF * USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S * AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF * YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS * (U.S.$500). * * Unless otherwise stated, the Program is written and copyrighted * by Texas Instruments is distributed as "freeware." You may, * only under TI's copyright in the Program, use and modify the * Program without any charge or restriction. You may * distribute to third parties, provided that you transfer a * copy of this license to the third party and the third party * agrees to these terms by its first use of the Program. In * jurisdictions in which use is not deemed acceptance of these * terms, no license is granted and no use is permitted. You * must reproduce the copyright notice and any other legend of * ownership on each copy or partial copy of the Program. * * You acknowledge and agree that the Program contains * copyrighted material, trade secrets and other TI proprietary * information and is protected by copyright laws, * international copyright treaties, and trade secret laws, as * well as other intellectual property laws. You agree that in * no event will you alter, remove or destroy any copyright * notice included in the Program. TI reserves all rights not * specifically granted under this license. Except as * specifically provided herein, nothing in this agreement * shall be construed as conferring upon you, by implication, * estoppel, or otherwise, any license or other right under any * TI patents, copyrights or trade secrets. *************************************************************/ #include "common.h" #include "i2c_master.h" //#include "msp430f2132.h" #include "msp430G2553.h" #include "HWGPIO.h" #include "delay.h" #define SDA_HI I2C_SetSDA_High() #define SDA_LO I2C_SetSDA_Low() #define SDA_IN I2C_GetSDA_Input() #define SCL_HI I2C_SetSCL_High() #define SCL_LO I2C_SetSCL_Low() #define SCL_IN I2C_GetSCL_Input() void I2C_SetSDA_High (void); void I2C_SetSDA_Low (void); BOOL I2C_GetSDA_Input (void); void I2C_SetSCL_High (void); void I2C_SetSCL_Low (void); BOOL I2C_GetSCL_Input (void); // local functions //uint08 i2c_master_check_nak_timeout(uint08 timeout, uint08 check_nak); //void i2c_master_cleanup(void); void i2c_delay_us(int n) { int i; for(i = 0; i < n; i++) { // __no_operation(); // __no_operation();//ALL=15 __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); __no_operation(); // __no_operation(); // __no_operation();//ALL=15 } } //////////////////////////////////////////////////////////////////////// void I2C_Master_Start(void) // Set up start condition for I2C /** * Generates the start condition for I2C read/write * */ { volatile uint08 i; SDA_HI; __no_operation(); SCL_HI; for (i=0; i<5; i++) { __no_operation(); SDA_LO; __no_operation(); __no_operation(); SCL_LO; //after end of start condition both SDA and SCL will be low } } //////////////////////////////////////////////////////////////////////// uint08 I2C_Master_Stop(void) // Set up stop condition for I2C /** * Generates the stop condition for I2C read/write * */ { /* volatile uint08 i; unsigned short delay=2000; SCL_HI; SCL_LO; i2c_delay_us(5); SDA_HI; SDA_LO; i2c_delay_us(10); SCL_IN; while(delay--) { i2c_delay_us(50); if(~SCL_IN) { SCL_HI; //SCL_OUT; i2c_delay_us(10); SDA_HI; i2c_delay_us(40); SCL_IN; return ENABLE; } } SDA_IN; */ { volatile uint08 i; SDA_LO; i2c_delay_us(5); SCL_HI; i2c_delay_us(5); SDA_HI; i2c_delay_us(5); i=0; //ensure bus is in default condition ( freed by slave) while(!SDA_IN) // i is just a variable to control the while loop run time. { SCL_HI; i2c_delay_us(5); SCL_LO; i2c_delay_us(5); i++; if( i > 25) { break; } } SCL_HI; //After generating stop condition SCL and SDA are both high. Default condition for I2C bus. } return DISABLE; } //////////////////////////////////////////////////////////////////////// uint08 I2C_PolledMasterWrite(uint08 device_addr, uint08* write_data, uint08 num_bytes)//return 1 IIC_FAULT /** * Writes data to the specified device address * * @param device_addr - I - 7 Bit device Address * @param write_data - I - Pointer to data buffer to be written to slave * @param num_bytes - I - Number of bytes to be written * @return PASS - Completed successfully * I2C_NO_ACK - Slave NAck'ed * */ { uint08 ByteCount; uint08 *data_ptr; uint08 status=PASS; // initialize pointer to the data and start the transfer data_ptr = write_data; // Generate START condition // // Data line loow when clock is high // I2C_Master_Start(); // Before writing address ensure the bit 0 is set to zero // Bit 0 =0 means master is writing , Bit 0 =1 means master wants to read // BIT0 = 0x1 if (I2C_MasterTransmitByte(device_addr & ~0x1) == I2C_NO_ACK) { // If not Acknowledged by slave// status = I2C_NO_ACK; } else // Tranmit all the data bytes as slave has acknowledged// { for (ByteCount=0; ByteCount<num_bytes; ByteCount++) { if (I2C_MasterTransmitByte(*data_ptr)== I2C_NO_ACK) { // If not Acknowledged by slave// status = I2C_NO_ACK; break; } else data_ptr++; //delay_ms(20);//YZP I2Cdelay } } // Generate STOP Condition // Data line high, when clock is high I2C_Master_Stop(); return status; } //////////////////////////////////////////////////////////////////////// uint08 I2C_PolledMasterRead(uint08 device_addr, uint08* read_data, uint08 num_bytes) /** * Reads data from the specified device address * * @param device_addr - I - 7 Bit device Address * @param read_data - I - Pointer to buffer to hold received data from slave * @param num_bytes - I - Number of bytes to be read * @return PASS - Completed successfully * I2C_NO_ACK - Slave NAck'ed * */ { uint08* data_ptr; uint08 status=PASS; uint08 ByteCount; data_ptr = read_data; // Generate START condition // // Data line low when clock is high // I2C_Master_Start(); // Transmit the slave address // // Before writing address ensure the bit 0 is set to 1 // Bit 0 =0 means master is writing , Bit 0 =1 means master is reading // BIT0 = 0x1 if(I2C_MasterTransmitByte(device_addr | 0x1) == I2C_NO_ACK) { // If not Acknowledged // status = I2C_NO_ACK; } else { // Receive all the data bytes // for(ByteCount = 0; ByteCount < num_bytes; ByteCount++) { *data_ptr = I2C_MasterReceiveByte(); data_ptr++; } } // Generate STOP Condition // Data line high, when clock is high I2C_Master_Stop(); return status; } //////////////////////////////////////////////////////////////////////// uint08 I2C_MasterTransmitByte(uint08 data) /** * This routine transmits one byte of data over the given clock and data lines and * receives the ack from slave. * * @param data - I - The 8 bit data to be transmitted * @return I2C_NO_ACK - Not Acknowledgeed * PASS - Acknowledged * */ { uint08 Ack=1; uint08 i; uint08 Byte = data; // printf("_I2C_MasterTransmitByte_=0x%x\n", Byte); // Send Byte It is assumed that the start condition would have made SCL and SDA low. // SDA should change only when SCA is low. SCL_LO; for(i = 0; i < 8 ; i++) { if( Byte & 0x80) SDA_HI; else SDA_LO; __no_operation(); __no_operation(); i2c_delay_us(2); SCL_HI; Byte <<= 1; __no_operation(); //need to optimize the delay. __no_operation(); __no_operation(); __no_operation(); i2c_delay_us(5); SCL_LO; //leave SDA at the end if(i == 7) { SDA_HI; } __no_operation(); __no_operation(); i2c_delay_us(2); } //Receive Ack __no_operation(); __no_operation(); i2c_delay_us(2); SCL_HI; //__no_operation(); // delay added bcoz without this delay ack was received wrong. //__no_operation(); // need to optimize the delay. i2c_delay_us(2); // If data line is pulled low by slave- it is acknowledged if (SDA_IN) Ack = 0; //ack not received else Ack = 1; //ack received i2c_delay_us(3); SCL_LO; __no_operation(); __no_operation(); i2c_delay_us(4); SDA_LO; if (Ack == 0) printf("__W_I2C_FAULT___\n"); //After transmitting one byte of data SCL and SDA are both low. return Ack; } //////////////////////////////////////////////////////////////////////// uint08 I2C_MasterReceiveByte() /** * This routine receives one byte of data over the given clock and data lines and * sends the ack to slave. * * @return one byte of data received from slave. * */ { uint08 Data=0; uint08 i; //Make SDA as input SDA_HI; __no_operation(); __no_operation(); i2c_delay_us(2); for(i = 0; i < 8 ; i ++) { SCL_HI; __no_operation(); __no_operation(); i2c_delay_us(2); Data <<= 1; if (SDA_IN) Data |=1; else Data |=0; i2c_delay_us(2); SCL_LO; __no_operation(); __no_operation(); i2c_delay_us(5); } //After the eight bits are transferred by slave, slave will pull SDA high ( default condition for I2C bus) // Generate ack for slave. SDA_LO; __no_operation(); __no_operation(); i2c_delay_us(1); SCL_HI; __no_operation(); __no_operation(); i2c_delay_us(5); SCL_LO; i2c_delay_us(2); //After receiving one byte of data SCL and SDA are both low. return Data; } ////////////////////////////////////////////////// void I2C_Master_Init(void) //P1.4=DATA,=58KHZ 17us; /** * Initializes I2C. Makes SCL and SDA high. */ { //bit banging P1SEL &= ~(SCL | SDA); //&= ~��0�� Set GPIO function P1OUT &= ~(SDA | SCL); I2C_SetSCL_Low(); //although not required but want to make sure SCL is low when SDA goes high I2C_SetSDA_High(); __no_operation(); i2c_delay_us(5); I2C_SetSCL_High(); __no_operation(); i2c_delay_us(5); } ////////////////////////////////////////////////// /* I2C SDA and SCL Lines */ void I2C_SetSDA_High (void) { P1DIR &= ~SDA; } ////////////////////////////////////////////////// void I2C_SetSDA_Low (void) { P1DIR |= SDA; } ////////////////////////////////////////////////// BOOL I2C_GetSDA_Input (void) { return (P1IN & SDA ? 1 : 0); } ////////////////////////////////////////////////// void I2C_SetSCL_High (void) { P1DIR &= ~SCL; } ////////////////////////////////////////////////// void I2C_SetSCL_Low (void) { P1DIR |= SCL; } ////////////////////////////////////////////////// BOOL I2C_GetSCL_Input (void) { return (P1IN & SCL ? 1 : 0); } #if 0 void i2c_hw_init(void)//P1.4 and P1.5 不支持硬件 { P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0 P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0 UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST+UCMODE_3+UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2+UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz UCB0BR1 = 0; //UCB0I2CSA = 0x20; // Set slave address UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation //IE2 |= UCB0TXIE; } void set_devaddr(uint08 dev_addr) { UCB0I2CSA = dev_addr >> 1; } unsigned char iic1_buffer[16]; int i2c_hw_write(uint08 dev_addr, int32 inlen, unsigned char *pdata) { volatile int32 i; set_devaddr(dev_addr); while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent //i = UCB0STAT; UCB0CTL1 |= UCTR + UCTXSTT; //while (UCB0CTL1 & UCTXSTT); for(i = 0; i < inlen; i++) { //while(((IFG2 & UCB0TXIFG) == 0) && ((UCB0STAT & 0x08) == 0)); while(((IFG2 & UCB0TXIFG) == 0)); if(UCB0STAT & 0x08) { UCB0CTL1 |= UCTXSTP; while (UCB0CTL1 & UCTXSTP); return -1; } UCB0TXBUF = pdata[i]; } UCB0CTL1 |= UCTXSTP; while (UCB0CTL1 & UCTXSTP); return 1; } int i2c_hw_read(uint08 dev_addr, int32 inlen, unsigned char *pdata) { int32 i; set_devaddr(dev_addr); while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent UCB0CTL1 &= ~UCTR; UCB0CTL1 |= UCTXSTT; //while (UCB0CTL1 & UCTXSTT); for(i = 0; i < inlen; i++) { //while(((IFG2 & UCB0RXIFG) == 0) && ((UCB0STAT & UCNACKIFG) == 0)); while((IFG2 & UCB0RXIFG) == 0); if(UCB0STAT & UCNACKIFG) { UCB0CTL1 |= UCTXSTP; while (UCB0CTL1 & UCTXSTP); return -1; } pdata[i] = UCB0RXBUF; if(i == inlen - 1) { UCB0CTL1 |= UCTXSTP; } } while (UCB0CTL1 & UCTXSTP); return 1; } int i2c_dpp_write(uint08 dev_addr, unsigned char cmd , int outlen, unsigned char *pdata) { int i; for(i = 0; i < outlen; i++) { iic1_buffer[1+i] = pdata[i]; } iic1_buffer[0] = cmd; return i2c_hw_write(dev_addr, i, pdata); } int i2c_dpp_read(uint08 dev_addr, unsigned char cmd , int inlen, unsigned char *pdata) { unsigned char cc[2]; //cc[0] = 0x15; cc[0] = cmd; if(i2c_hw_write(dev_addr, 1, cc) < 1) return -1; return i2c_hw_read(dev_addr, inlen, pdata); } int i2c_sil9293_write(uint08 dev_addr, unsigned char cmd , int outlen, unsigned char *pdata) { int i; for(i = 0; i < outlen; i++) { iic1_buffer[1+i] = pdata[i]; } iic1_buffer[0] = cmd; return i2c_hw_write(dev_addr, i, pdata); } int i2c_sil9293_read(uint08 dev_addr, unsigned char cmd , int inlen, unsigned char *pdata) { unsigned char cc[2]; cc[0] = cmd; if(i2c_hw_write(dev_addr, 1, cc) < 1) return -1; return i2c_hw_read(dev_addr, inlen, pdata); } #endif
我们已经调试了很长一段时间、在检查代码时没有发现任何问题。 请帮助工程师进行分析。
非常感谢!