TI中文支持网
TI专业的中文技术问题咨询交流网站

MSP430G2755,做USCI_I2C从机,在按键退出低功耗时会出现I2C-SDA一直被拉低

2755做硬件I2C从机。正常情况下休眠在LPM3,I2C可以正常通讯。按按键退出LPM3,有时会出现SDA一直被拉低,只能重新初始化USCI。

现贴出按键中断配置,和USCI从机配置。请高手帮忙分析一下,感激不尽。

#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
__bic_SR_register_on_exit(LPM3_bits); //退出中断的同时退出低功耗 只能用于中断 if(P2IFG&BIT2)//如果P2.2的中断标志位为1 延时消抖
{
delay_ms(10);
if(P2IFG&BIT2)//如果P2.2延时后的中断标志位还是1 证明确实有按键按下
{
if(!(P2IN&BIT2))//再次检测P2.2的输入状态
{ if(key_flag1==1)
{
key_flag2=1;
}
key_flag1=1;//第一次按键按下标志位
}
P2IFG&=~BIT2;
}
}
}

I2C部分,

void TI_USCI_I2C_slaveinit(void (*SCallback)(),void (*TCallback)(unsigned char volatile *value),void (*RCallback)(unsigned char value),void (*StCallback)(),unsigned char slave_address){
P3SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMODE_3 + UCSYNC; // I2C Slave, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 10; // Set prescaler 1M/10~100KHZ
UCB0BR1 = 0;
UCB0I2COA = slave_address; // set own (slave) address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
// IE2 |= UCB0TXIE + UCB0RXIE; // Enable TX RX interrupt
// UCB0I2CIE |= UCSTTIE+UCSTPIE; // Enable STT STP interrupt
TI_start_callback = SCallback;
TI_stop_callback = StCallback;
TI_receive_callback = RCallback;
TI_transmit_callback = TCallback;
}
void USCI_I2C_Enable(void)
{
IE2 |= (UCB0TXIE + UCB0RXIE); // Enable TX RX interrupt
UCB0I2CIE |= (UCSTTIE+UCSTPIE); // Enable STT STP interrupt}
void USCI_I2C_DisEnable(void)
{
IE2 &=~(UCB0TXIE + UCB0RXIE); // DisEnable TX RX interrupt
UCB0I2CIE &=~(UCSTTIE+UCSTPIE); // DisEnable STT STP interrupt}
unsigned char TI_USCI_I2C_notready(void)
{
return (UCB0STAT & UCBBUSY);
}
// USCI_B0 Data ISR
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (IFG2 & UCB0TXIFG)
{
TI_transmit_callback(&UCB0TXBUF);
}
else
{
TI_receive_callback(UCB0RXBUF);
}

}

// USCI_B0 State ISR
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
if(UCB0STAT&UCSTTIFG)
{
UCB0STAT &= ~UCSTTIFG; // Clear start condition int flag
rxnum=0;//接收到开始信号清零
} if(UCB0STAT&UCSTPIFG)
{
UCB0STAT&=~UCSTPIFG;
TI_stop_callback();
}
}

void start_cb(){
for(unsigned char index=0;index<sizeof(I2C_RXData);index++)
{
I2C_RXData[index]=0;
}
}
void stop_cb(){
I2C_flag=0;
}
void transmit_cb(unsigned char volatile *byte){
*byte = I2C_Block_TXData[I2C_flag];
I2C_flag++;
}

void receive_cb(unsigned char receive){
unsigned char temp[37]={0},rxtemp=0;
temp[0]=0x16;
temp[2]=0x17;
rxtemp=receive;
I2C_RXData[rxnum]= rxtemp;
rxnum++;

}

Butterfly:

参考430ware 下面 msp430g2x55_uscib0_i2c_08.c例程,中断方式发送

//******************************************************************************#include <msp430.h>

unsigned char *PTxData; // Pointer to TX dataunsigned char TXByteCtr;const unsigned char TxData[] = // Table of data to transmit{ 0x11, 0x22, 0x33, 0x44, 0x55};

int main(void){ WDTCTL = WDTPW | WDTHOLD; // Stop WDT P3SEL |= 0x06; // 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 = 0x48; // Slave Address is 048h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation IE2 |= UCB0TXIE; // Enable TX interrupt

while (1) { PTxData = (unsigned char *)TxData; // TX array start address TXByteCtr = sizeof TxData; // Load TX byte counter while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent UCB0CTL1 |= UCTR | UCTXSTT; // I2C TX, start condition __bis_SR_register(CPUOFF | GIE); // Enter LPM0 w/ interrupts // Remain in LPM0 until all data // is TX'd }}

//——————————————————————————// The USCIAB0TX_ISR is structured such that it can be used to transmit any// number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData// points to the next byte to transmit.//——————————————————————————#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)#pragma vector = USCIAB0TX_VECTOR__interrupt void USCIAB0TX_ISR(void)#elif defined(__GNUC__)void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)#else#error Compiler not supported!#endif{ if (TXByteCtr) // Check TX byte counter { UCB0TXBUF = *PTxData++; // Load TX buffer TXByteCtr–; // Decrement TX byte counter } else { UCB0CTL1 |= UCTXSTP; // I2C stop condition IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 }}

yue feng1:

回复 Butterfly:

hi,butterfly

这个code,我试过。我的逻辑是不论MSP430有无进入休眠都能收发数据。所以就不能在while中接收与发送。只能用接收和发送中断,在接收中断中根据接收的不同COMMAND,填充不同的数据到发送缓存,再由发送中断完成发送。

现在接收和发送都正常,但是在按按键时会有很大概率造成SDA被拉低,我把低功耗去掉后还是存在。所以问题点还是定位在I2C配置与中断处理上。

还有一个问题要跟您请教一下:LPM3下SCLK不是OFF了吗但实际中可以收发。

灰小子:

回复 yue feng1:

LPM3下SMCLK会被关闭。但如果SMCLK正在被使用,一般msp430是不会真正进入低功耗状态的。

你可以观察一下电流变化,看是否真正进入了低功耗状态

赞(0)
未经允许不得转载:TI中文支持网 » MSP430G2755,做USCI_I2C从机,在按键退出低功耗时会出现I2C-SDA一直被拉低
分享到: 更多 (0)