TI中文支持网
TI专业的中文技术问题搜集分享网站

MSP430 硬件I2C 中断法始终调不通,求助!!!

CC430F5x单片机硬件I2C通过中断的方式对AT24C02进行读写,始终调不通,程序如下,请各位帮忙看看

#include "msp430.h"

typedef unsigned char uint8;

uint8 test_buf1[8] = {'H','E','L','L','O','Y','O','U'};
uint8 test_buf2[8] = {0,0,0,0,0,0,0,0};
uint8 test_byte1 = 0x0c;
uint8 test_byte2 = 0x00;

//UCB0---I2C
uint8 I2C_Tx_Size = 0; 	//left data to be sent
uint8 I2C_Rx_Size = 0; 	//left data to be received
uint8 *I2C_Tx_Buffer; 	//pointer of data to be sent
uint8 *I2C_Rx_Buffer; 	//pointer of data to be received
uint8 I2C_State = 0; 	//flag of I2C tranmit or receive state
uint8 I2C_Read_Data_Address = 0;
uint8 I2C_Write_Data_Address = 0;
uint8 UCB0_Rx_Or_Tx = 0; // 0--Receive only; 1--Transmit only; 2--Receive and transmit
uint8 Flag_ACK=1;
uint8 Flag_I2C_Address_Transmitted=0;

#define EEPROM_SCL			BIT2	//P1.2
#define EEPROM_SDA			BIT3	//P1.3
#define ADG841_IN1			BIT7	//P3.7
#define LEDBIT1	//P3.1
#define I2C_SLAVE_ADDR0x50

//Delay
#define 	CPU_F((double)26000000)	//XT2CLK--26MHz
#define 	delay_us(x)__delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define 	delay_ms(x)__delay_cycles((long)(CPU_F*(double)x/1000.0))

void UCB0_Interrupt_Sel(uint8);


void CLK_Init()
{
	UCSCTL6 &= ~(XT2OFF+XT1OFF);// Enable XT2--26MHz XT1--32.768kHz

	UCSCTL4 = SELA_0 + SELS_5 + SELM_5;

	UCSCTL5 = DIVM_0 | DIVS_0 | DIVA_0;
/*
	do
	{UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);// Clear XT2,DCO fault flagsSFRIFG1 &= ~OFIFG;// Clear fault flags
	}while (SFRIFG1&OFIFG);	// Test oscillator fault flag
*/
	UCSCTL4 = SELA_0 + SELS_5 + SELM_5;
}
void GPIO_Init()
{
	P3DIR |= LED + ADG841_IN1;

	P5SEL |= BIT0 + BIT1; //Port select XT1
}

void LED_ON()
{
	P3OUT |= LED;
}

void LED_OFF()
{
	P3OUT &= ~LED;
}

void UCB0_I2C_Init()
{
	P1SEL |= EEPROM_SCL + EEPROM_SDA;
	/* Disable USCI */
	UCB0CTL1 |= UCSWRST;

	//UCB0CTL0 &= ~UCSLA10;////
	UCB0CTL0 = UCMST | UCMODE_3 | UCSYNC; //I2C, Mater mode, Synchronous mode

	UCB0CTL1 = UCSSEL_2 | UCSWRST;

	/* I2C Slave Address Register */
	UCB0I2CSA = I2C_SLAVE_ADDR;

	/* Bit Rate Control Register 0 */
	UCB0BR0 = 4;//  26MHz/260=100KHz
	UCB0BR1 = 1;
	/* Enable USCI */
	UCB0CTL1 &= ~UCSWRST;

	P3OUT |= ADG841_IN1;
}

uint8 I2C_Write_Page(uint8 Data_Address, uint8 *pBuffer, uint8 size)
{
	if(size==0)
		return 0;
	if(UCB0STAT & UCBUSY) 	//If I2C is busy
		return 0;

	Flag_I2C_Address_Transmitted=0;

	I2C_Write_Data_Address=Data_Address;
	I2C_Tx_Buffer=pBuffer;
	//I2C_Tx_Size=size-1;
	I2C_Tx_Size=size;

	//_EINT();
	UCB0IFG &= ~UCTXIFG;
	UCB0_Rx_Or_Tx = 1; 					//transmit interrupt only
	UCB0_Interrupt_Sel(UCB0_Rx_Or_Tx);
	_EINT();

	while( UCB0CTL1& UCTXSTP );
	UCB0CTL1 |= UCTR+UCTXSTT;//write mode, send start bit

	__bis_SR_register(LPM0_bits);// Enter LPM0

	return 1;
}

uint8 I2C_Read_Page(uint8 Read_Data_Address, uint8 *pbuffer, uint8 size)
{
	_DINT();
	if(size==0)
		return 0;
	if(UCB0STAT & UCBUSY)	//If I2C is busy
		return 0;

	I2C_Read_Data_Address=Read_Data_Address; // set addressFlag_I2C_Address_Transmitted=0;I2C_Tx_Size=0;
/*
	UCB0_Rx_Or_Tx = 1;		//enable transmit interrupt bit only_EINT();
	UCB0_Interrupt_Sel(UCB0_Rx_Or_Tx);
 */

	while( UCB0CTL1& UCTXSTP );
	UCB0CTL1 |= UCTR;		//write mode
	UCB0CTL1 |= UCTXSTT;//send start bit
	//UCB0TXBUF = E2PROM_WRITE_CMD;

	if(Flag_I2C_Address_Transmitted==0)
	{
		Flag_I2C_Address_Transmitted=1;
		UCB0TXBUF = I2C_Read_Data_Address;//write data address
	}

	I2C_Rx_Buffer = pbuffer;
	//I2C_Rx_Size = size-1; 	//Number of data to be received
	I2C_Rx_Size = size;

	UCB0IFG &= ~UCRXIFG;
	UCB0_Rx_Or_Tx=0;
	UCB0_Interrupt_Sel(UCB0_Rx_Or_Tx);
	_EINT();
	while( UCB0CTL1& UCTXSTP );
	//delay_ms(5);
	UCB0CTL1 &= ~UCTR;//read mode
	//UCB0IFG &= ~UCRXIFG;// clear interrupt flag

	UCB0CTL1 |= UCTXSTT;//send start bit

	__bis_SR_register(LPM0_bits);// Enter LPM0, enable interrupts

	return 0;
}

void UCB0_Interrupt_Sel(uint8 onOff)
{

	if(onOff == 0) 		//Only receive interrupt enabled
	{
		UCB0IE &=~UCTXIE;// Disable USCI_B0 TX interrupt
		UCB0IE |= UCRXIE;// Enable USCI_B0 RX interrupt
	}
	else if(onOff==1)	//Only transmit interrupt enabled
	{
		UCB0IE &=~UCRXIE;// Disable USCI_B0 RX interrupt
		UCB0IE |= UCTXIE;// Enable USCI_B0 TX interrupt
	}
	else//Both receive and transmit interrupt enabled
	{
		UCB0IE |= UCTXIE;// Enable USCI_B0 TX interrupt
		UCB0IE |= UCRXIE;// Enable USCI_B0 RX interrupt
	}
}

void I2C_Write_Byte(uint8 data_addr, uint8 data_value)
{
	while(UCB0STAT & UCBUSY); 	//If I2C is busy

	Flag_I2C_Address_Transmitted=0;

	I2C_Write_Data_Address=data_addr;
	I2C_Tx_Buffer=&data_value;//UCB0IFG &= ~UCTXIFG;
	UCB0_Rx_Or_Tx = 1; 					//transmit interrupt only

	while( UCB0CTL1& UCTXSTP );
	UCB0CTL1 |= UCTR+UCTXSTT;//write mode, send start bit

	UCB0_Interrupt_Sel(UCB0_Rx_Or_Tx);
	_EINT();
	__bis_SR_register(LPM0_bits);// Enter LPM0
}
void I2C_Read_Byte(uint8 data_addr, uint8 * data_value)
{//_DINT();
	I2C_State=1;
	while(UCB0STAT & UCBUSY);	//If I2C is busy

	I2C_Read_Data_Address=data_addr; // set address
	Flag_I2C_Address_Transmitted=0;
	I2C_Rx_Buffer = data_value;

	while( UCB0CTL1& UCTXSTP );
	UCB0CTL1 |= UCTR;		//write mode
	UCB0CTL1 |= UCTXSTT;//send start bit

	UCB0IE |= UCTXIE;

	UCB0_Rx_Or_Tx=0;
	UCB0_Interrupt_Sel(UCB0_Rx_Or_Tx);
/*
	if(Flag_I2C_Address_Transmitted==0)
	{
		Flag_I2C_Address_Transmitted=1;
		UCB0TXBUF = I2C_Read_Data_Address;//write data address
	}
*/
	UCB0IFG &= ~UCTXIFG;

	_EINT();
	while( UCB0CTL1& UCTXSTP );

	UCB0CTL1 &= ~UCTR;//read mode

	UCB0CTL1 |= UCTXSTT;//send start bit

	__bis_SR_register(LPM0_bits);// Enter LPM0, enable interrupts

}

#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
	//_DINT();
	switch(__even_in_range(UCB0IV,12))
	{
		case 0: 				// no interrupt
			break;
		case 2:					// ALIFG
			break;
		case 4:					// NACKIFG
			break;
		case 6:					// STTIFG
			break;
		case 8:					// STPIFG
			break;
		case 10:				// RXIFG

			UCB0CTL1 |= UCTXSTP;// Generate I2C stop condition

			*I2C_Rx_Buffer = UCB0RXBUF;// Move final RX data to PRxData
			__bic_SR_register_on_exit(LPM0_bits);// Exit active CPU
			break;
		case 12:				// TXIFG

			if(Flag_I2C_Address_Transmitted==0)
			{
				UCB0TXBUF = I2C_Write_Data_Address;//write data address
				Flag_I2C_Address_Transmitted=1;
				/*
				while(!(UCB0IFG & UCTXIFG))
				{
					UCB0IE &= ~UCTXIE;
					UCB0IFG &= ~UCTXIFG;
				}
				*/
			}
			if(I2C_State==0)
			{
				UCB0TXBUF = *I2C_Tx_Buffer;// Load TX buffer
				/*
				while(!(UCB0IFG & UCTXIFG))// wait UCTXIFG=1
				{
					UCB0IE &= ~UCTXIE;
					UCB0IFG &= ~UCTXIFG;
				}
				*/
				UCB0IE &= ~UCTXIE;
				UCB0CTL1 |= UCTXSTP;// I2C stop condition
				__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
			}
			// Clear USCI_B0 TX int flag

			break;
		default:
			break;
	}
}

void main()
{
	uint8 I2C_SUCCESS_FLAG=0;
	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer

	CLK_Init();
	GPIO_Init();

	LED_ON();
	UCB0_I2C_Init();

	delay_ms(20);

	I2C_Write_Byte(0x00,test_byte1);

	I2C_Read_Byte(0x00,&test_byte2);
	
	if(test_byte1==test_byte2)
		I2C_SUCCESS_FLAG=1;
}

等待法已经调试成功了,说明AT24C02没有问题,求助各位帮忙看看这个程序有什么问题,谢谢!

灰小子:

一般这种都是时序问题,建议用逻辑分析仪看看时序,没有好办法

Jason Guo:

没法一行行看代码。提供官方读写EEPROM 例程吧,希望能帮到。

Jason Guo:

回复 Jason Guo:

还有文档。

赞(0)
未经允许不得转载:TI中文支持网 » MSP430 硬件I2C 中断法始终调不通,求助!!!
分享到: 更多 (0)