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:
还有文档。