请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号: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
我们已经调试了很长一段时间、在检查代码时没有发现任何问题。 请帮助工程师进行分析。
非常感谢!