Part Number: MSP430F5419A
Hi experts,
I have I2C communication problem with EEPROM.
I've referred to the E2E reference And Application Note slaa208a
http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/636507/2352597?tisearch=e2e-sitesearch&keymatch=MSP430F5419A eeprom#2352597
But I still couldn't find the what is the problem of Read/Write operation.
Please find the attached file to lookup the source.
//==========================================================
// Subroutine for EEPROM 24C04
//
//==========================================================
#include <msp430.h>
#include <Project.h>
#define BYTE_READ 0xa1 // Serial eeprom Read command
#define BYTE_WRITE 0xa0 // Serial eeprom Write command
/*
#define SetSDA() pSDA = 1
#define ResSDA() pSDA = 0
#define ChkSDA() pSDA
#define SetSCL() pSCL = 1
#define ResSCL() pSCL = 0
*/
void SetSDA(void);
void ResSDA(void);
uint8_t ChkSDA(void);
void SetSCL(void);
void ResSCL(void);
void _SendStart(void);
void _SendStop(void);
uint8_t _SendData(uint8_t dat);
void _ReadData(uint8_t *dat);
uint8_t _SendAddr(uint8_t dat);
uint8_t ReadEprom(uint16_t addr, uint8_t *rdata);
uint8_t WriteEprom(uint16_t addr, uint8_t wdata);
//==========================================================
void SetSDA(void)
{
P3DIR &= EEPROM_SDA;
P3OUT |= EEPROM_SDA;
}
void ResSDA(void)
{
P3DIR &= EEPROM_SDA;
P3OUT &= ~EEPROM_SDA;
}
uint8_t ChkSDA(void)
{
uint8_t tSDA;
P3DIR &= ~EEPROM_SDA;
tSDA = (P3IN & EEPROM_SDA) >> 1;
return tSDA;
}
void SetSCL(void)
{
P3DIR &= EEPROM_CLK;
P3OUT |= EEPROM_CLK;
}
void ResSCL(void)
{
P3DIR &= EEPROM_CLK;
P3OUT &= ~EEPROM_CLK;
}
void _SendStart(void) // Start condition
{
SetSDA();
SetSCL();
ResSDA();
ResSCL();
}
void _SendStop(void) // Stop condition
{
ResSCL();
ResSDA();
SetSCL();
SetSDA();
}
uint8_t _SendData(uint8_t dat)
{
uint8_t ack;
uint8_t i;
for (i=0; i<8; i++){ // Write 8 bit
if (dat & 0x80) SetSDA();
else ResSDA();
SetSCL();
ResSCL();
dat <<= 1;
}
SetSDA(); // Check ACK
SetSCL();
if (!ChkSDA()) ack = 1;
else ack = 0;
ResSCL();
return ack;
}
void _ReadData(uint8_t *dat)
{
uint8_t i;
uint8_t rdat = 0;
SetSDA(); // Read 8 bit
for (i=0; i<8; i++){
rdat <<= 1;
SetSCL();
if (ChkSDA()) rdat |= 1;
ResSCL();
} /* endfor */
SetSCL(); // Check ACK
ResSCL();
*dat = rdat;
}
uint8_t _SendAddr(uint8_t dat) // Send address
{
_SendStart();
return (_SendData(dat)); // return ACK
}
//==========================================================
uint8_t ReadEprom(uint16_t addr, uint8_t *rdata)
{
uint8_t ack;
uint8_t bank;
uint8_t dat;
uint8_t retry = 50;
bank = (addr >> 7) & 0x0e;
addr &= 0xff;
do {
ack = _SendAddr(BYTE_WRITE | bank);
} while ( !ack && --retry );
if (ack){
_SendData(addr);
_SendStart();
_SendData(BYTE_READ | bank);
_ReadData(&dat);
}
_SendStop();
if (ack) *rdata = dat;
return(ack);
//*rdata = dat;
//return(ack);
}
uint8_t WriteEprom(uint16_t addr, uint8_t wdata)
{
uint8_t ack;
uint8_t bank;
uint8_t retry = 20;
bank = (addr >> 7) & 0x0e;
addr &= 0xff;
do {
ack = _SendAddr(BYTE_WRITE | bank);
} while ( !ack && --retry );
if (ack){
_SendData(addr);
_SendData(wdata);
}
_SendStop();
return(ack);
}
/*
//=======================================================================
// Load & Save Setup value
//=======================================================================
uint8_t LoadEprom(void)
{
uint8_t *dp, chksum = 0;
uint16_t i;
dp = (uint8_t *)&setup;
for (i=0; i<sizeof(setup); i++){
ReadEprom(i, dp);
chksum += *dp++;
}
if (chksum) return 0;
return 1;
}
//------------------------------------------------------------------------
void UpdateEprom(void)
{
uint8_t *dp, chksum = 0;
uint16_t i;
dp = (uint8_t *)&setup;
for (i=0; i<sizeof(setup)-1; i++){
WriteEprom(i, *dp);
chksum += *dp++;
}
WriteEprom(i, ~chksum + 1);
}
*/
#include <msp430.h>
#include <project.h>
// general variable
volatile uint16_t SysTick=0;
uint16_t Delay10msec=0;
uint8_t Blink_CNT;
uint8_t SEC_CNT;
uint8_t DIS_SecTimer=0;
uint8_t DIS_mSecTimer=0;
volatile uint8_t BFND_DisplayFlag=0; // system Big FND Display On/Off Flag
volatile uint8_t FlowFlag;
volatile uint8_t I2CBuffer;
volatile int PtrTransmit;
volatile uint8_t I2CBufferArray[10];
// External variable
extern volatile uint16_t Comp_3minTimer; // timer, 60 x 3 = 180sec
extern volatile uint32_t HotGas_Timer; // timer, 60 x 60 x 20 = 72000sec (20 hours)
extern volatile uint8_t Cur_CoinCNT; // M. count
extern volatile uint16_t HotGas_OnTimer;
extern volatile uint8_t VendMagicNumber;
extern volatile uint8_t Pick_SecTimer;
// External function
extern void S_FND(uint8_t Num);
extern void Init_TimerB(void); // FND Swing
extern void ADC_Start(void);
extern void COIN_Check(void);
extern void Key_SCAN(void);
extern void FRONT_Check(void);
extern void Limit_Check(void);
extern void Main_Process(void);
extern void Relay_CTRL(uint8_t Relay_CH,uint8_t OnOff);
extern void BillCounter_(uint8_t OnOff);
// function define
void SetVcoreUp(unsigned int level);
void Init_GPIO(void);
void Init_Clock(void);
void Init_UART0(void); // for debug
void Init_TimerA(void); // system tick
void Init_ADC(void); // for temp sensor
void Init_I2C(void); // for EEPROM
void I2CWriteInit(void);
void I2CReadInit(void);
void EEPROM_ByteWrite(uint16_t Address, uint8_t Data);
uint8_t EEPROM_ByteRead(uint16_t Address);
void EEPROM_AckPolling(void);
//extern uint8_t ReadEprom(uint16_t addr, uint8_t *rdata);
//extern uint8_t WriteEprom(uint16_t addr, uint8_t wdata);
void Delay_10msec(uint16_t DelayCNT);
// test define
extern volatile uint16_t temp_ADC;
extern volatile uint16_t volt;
extern volatile uint16_t volt_old;
extern volatile uint8_t temp_dir;
extern volatile int8_t Sen_Cel;
extern void Volt2Cel(uint16_t SenVolt);
extern void Display_BFND(uint16_t B_Num);
extern void Display_sFND(uint16_t s_Num);
extern void Display_PatEdge(uint8_t pat,uint8_t dir);
extern void Display_Obounce(void);
extern void Display_8Shift(void);
extern void Display_Bill(uint8_t CurBill);
extern void Display_VendQty(uint8_t VendQty);
extern void Display_Err(void);
extern void Display_Temp(void);
/**
* main.c
*/
void main(void)
{
volatile uint8_t tSTEP=0;
volatile uint8_t ptdata[1];
uint8_t seq_no=0;//,tACK;//,toggle=1;
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
// Clock initial
Init_Clock();
// port initial
Init_GPIO();
// timer initial
Init_TimerA(); // system tick
Init_TimerB(); // FND Swing
// adc initial
Init_ADC(); // for temp sensor
// Uart0 initial ; Debug
Init_UART0();
// I2C initial
Init_I2C();
printf("\r\n\r\n ******** \r\n");
__enable_interrupt();
BillCounter_(DISABLE);
EEPROM_ByteWrite(0x0001, 0x9a);
EEPROM_AckPolling(); // Wait for EEPROM write cycle
// EEPROM_ByteWrite(0x0002, 0xbc);
// EEPROM_AckPolling(); // Wait for EEPROM write cycle
//tACK=WriteEprom(0x0001, 0x9a);
//printf("\r\neeprom write test 0x001 ACK [%d]\r\n",tACK);
//tACK=WriteEprom(0x0002, 0xbc);
//printf("\r\neeprom write test 0x002 ACK [%d]\r\n",tACK);
tSTEP=0;
tSTEP = EEPROM_ByteRead(0x0001);
printf("\r\neeprom read test 0x001 [0x%x]\r\n",tSTEP);
// tSTEP=0;
// tSTEP = EEPROM_ByteRead(0x0002);
// printf("\r\neeprom read test 0x002 [0x%x]\r\n\n",tSTEP);
//tACK=ReadEprom(0x0001, ptdata);
//printf("\r\neeprom read test 0x001 [ACK : %d][0x%x]\r\n",tACK,ptdata[0]);
//tACK=ReadEprom(0x0002, ptdata);
//printf("\r\neeprom read test 0x002 [ACK : %d][0x%x]\r\n",tACK,ptdata[0]);
tSTEP=0;
while(1)
{
Main_Process();
// system tick soft timer
if(SysTick == 10) // 100msec
{
SysTick = 0;
DIS_mSecTimer++;
Blink_CNT++; // board led blink
SEC_CNT++;
if(SEC_CNT == 10)
{
SEC_CNT=0;
ADC_Start();
Comp_3minTimer++;
HotGas_Timer++;
HotGas_OnTimer++;
DIS_SecTimer++;
Pick_SecTimer++;
Display_Temp();
}
if(BFND_DisplayFlag == 1) // Big FND Display ON (IDLE State)
{
uint8_t Seq[10][3]={//{speed,pattern number,display time(sec)}
{1,1,5}, // 100msec,1led cw,5sec
{2,1,5}, // 200msec,1led cw,5sec
{1,2,5}, // 100msec,1led ccw,5sec
{2,2,5}, // 200msec,1led ccw,5sec
{1,3,5}, // 100msec,2led cw,5sec
{2,3,5}, // 200msec,2led cw,5sec
{1,4,5}, // 100msec,2led ccw,5sec
{2,4,5}, // 200msec,2led ccw,5sec
{2,5,10}, // 200msec,O bounce,10sec
{2,6,20} // 200msec,8 shift,10sec
};
if(Seq[seq_no][0] == DIS_mSecTimer)
{
DIS_mSecTimer = 0;
switch(Seq[seq_no][1])
{
case 1:
Display_PatEdge(1,1); // back ground fnd display
break;
case 2:
Display_PatEdge(1,2); // back ground fnd display
break;
case 3:
Display_PatEdge(2,1); // back ground fnd display
break;
case 4:
Display_PatEdge(2,2); // back ground fnd display
break;
case 5:
Display_Obounce();
break;
case 6:
Display_8Shift();
break;
}
if(Seq[seq_no][2] == DIS_SecTimer)
{
DIS_SecTimer = 0;
seq_no++;
if(seq_no == 10)
seq_no=0;
}
}
}
// if(BFND_DisplayFlag == 2) // Big FND Display ON (Bill State)
else if(BFND_DisplayFlag == 2) // Big FND Display ON (Bill State)
{
Display_Bill(Cur_CoinCNT); // display
}
else if(BFND_DisplayFlag == 3)
{
// display
Display_VendQty(VendMagicNumber);
}
else if(BFND_DisplayFlag == 4)
{
// error status
Display_Err();
}
}
if(Blink_CNT == 5)
{
Blink_CNT = 0;
P1OUT ^= 0x80; // board led blink
/*
toggle ^= 1;
if(toggle == 1)
{
// EEPROM_ByteWrite(0x0001, 0xaa);
// Delay_10msec(10);
EEPROM_ByteWrite(0x0002, 0x55);
Delay_10msec(10);
}
else if(toggle == 0)
{
toggle = EEPROM_ByteRead(0x0001);
printf("\r\neeprom read test 0x001 [0x%x]\r\n",toggle);
toggle = 0;
Delay_10msec(10);
toggle = EEPROM_ByteRead(0x0002);
printf("\r\neeprom read test 0x002 [0x%x]\r\n",toggle);
toggle = 0;
Delay_10msec(10);
}
*/
}
}
}
void Init_Clock(void)
{
SetVcoreUp(PMMCOREV_1);
SetVcoreUp(PMMCOREV_2); // Set VCore to 1.8MHz for 20MHz
P11DIR = BIT2 + BIT1 + BIT0; // P11.2,1,0 to output direction
P11SEL = BIT2 + BIT1 + BIT0; // P11.2 to output SMCLK, P11.1
// to output MCLK and P11.0 to
// output ACLK
P5SEL |= 0x0C; // Port select XT2
P7SEL |= 0x03; // Port select XT1
UCSCTL6 &= ~(XT1OFF + XT2OFF); // Set XT1 & XT2 On
UCSCTL6 |= XCAP_3; // nternal load cap
// Loop until XT1,XT2 & DCO stabilizes
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while(SFRIFG1&OFIFG); // Test oscillator fault flag
UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to
// expected frequency
// UCSCTL4 |= SELA_0 + SELS_5; // Select SMCLK, ACLK source and DCO source
UCSCTL4 |= SELA_0 + SELS_5 + SELM__XT2CLK; // Select SMCLK, ACLK source and DCO source
}
void Init_GPIO(void)
{
P1DIR |= BD_LED; // p1.7 output 0x80
P1OUT &= ~BD_LED; // board led on
P2DIR = 0x00; // key
P3DIR |= EEPROM_WP|EEPROM_SDA|EEPROM_CLK; // P3.0 output 0x01 i2c , uart0 use
P3OUT &= ~EEPROM_WP; // eeprom wp low
P4DIR |= (FND_DP|FND_G|FND_F|FND_E|FND_D|FND_C|FND_B|FND_A); // all output 0xff
P4OUT = 0x80;
// P5DIR = ; // uart1 use
P6DIR |= (M2_N|M2_P|M1_N|M1_P); // P6.0 ,adc 0 use // P6.7 ~ P6.4 output 0xf0
P6OUT = 0x00; // motor initial stop
P7DIR |= SPEAKER_EN; // p7.2 output 0x04
P7OUT |= SPEAKER_EN; // speaker enable high
P8DIR |= (B_DIG4|DIG1|DIG2|DIG3|DIG4);//|COIN_STOP4); // P8.7, 8.4, 8.3, 8.2, 8.1, 8.0 output 0x8f
P8OUT = 0xff;
P9DIR |= (B_DIG1|B_DIG2|B_DIG3); // P9.2, 9.1, 9.0 output 0x07 uart2 use
P9OUT = 0xff;
P10DIR |= (HOTGAS_CTRL|FAN_CTRL|COMP_CTRL|COIN_STOP5); // P10.2, 10.1, 10.0 output // P10.4 P10.3 input
P10OUT = 0x00; // relay low ; relay drive tr(npn) off
}
void Init_UART0(void) // for debug
{
P3SEL |= 0x30; // P3.4,5 = USCI_A0 TXD/RXD
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 104; // 12MHz 115200 (see User's Guide)
UCA0BR1 = 0; // 12MHz 115200
UCA0MCTL |= (UCBRS_1|UCBRF_0); // Modulation UCBRSx=1, UCBRFx=0
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA0IE &= ~(UCRXIE); // Disable USCI_A0 RX interrupt
}
void Init_ADC(void) // for temp sensor
{
ADC12CTL0 = ADC12SHT02 + ADC12ON; // Sampling time, ADC12 on
ADC12CTL1 = ADC12SHP; // Use sampling timer
ADC12IE = 0x01; // Enable interrupt
ADC12CTL0 |= ADC12ENC;
P6SEL |= 0x01; // P6.0 ADC option select
}
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
uint16_t tVolt;
switch(__even_in_range(ADC12IV,34))
{
case 0: break; // Vector 0: No interrupt
case 2: break; // Vector 2: ADC overflow
case 4: break; // Vector 4: ADC timing overflow
case 6: // Vector 6: ADC12IFG0
temp_ADC = ADC12MEM0;
// printf("ADC ; 0x%x ",temp_ADC);
tVolt = (uint16_t)(((uint32_t)temp_ADC*3300)/0xFFF);
// printf("Volt ; %d.%d%d%dV [0x%x] ",tVolt/1000,tVolt%1000/100,tVolt%1000%100/10,tVolt%1000%100%10,tVolt);
Volt2Cel(tVolt);
// printf("Temp : %dC[%s]\r\n",Sen_Cel,(temp_dir==1) ? "up" : "down");
break;
default: break;
}
}
void Init_TimerA(void) // system tick
{
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CCR0 = 14924; // 10msec
TA1CTL = TASSEL_2+ID_3+MC_2+TACLR+TAIE; // SMCLK(XT2,12MHz), contmode, clear TAR, Div 8(12/8 = 1.5Mhz)
TA1R = 0;
}
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
// P1OUT ^= 0x80; // Toggle P1.0
TA1R = 0;
SysTick++;
Delay10msec++;
COIN_Check();
Key_SCAN();
FRONT_Check();
Limit_Check();
}
void SetVcoreUp (unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if((PMMIFG & SVMLIFG))
while((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}
void Delay_10msec(uint16_t DelayCNT)
{
Delay10msec = 0;
while(Delay10msec >= DelayCNT)
{
_nop();
}
}
void Init_I2C(void)
{
// UCB0 - I2C
P3SEL |= EEPROM_CLK + EEPROM_SDA; // p3.1 , p3.2
// Recommended initialization steps of I2C module as shown in User Guide:
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCTR + UCSWRST; // Use SMCLK, keep SW reset
// UCB0BR0 = 30; // fSCL = SMCLK/30 = ~400kHz
UCB0BR0 = 120; // fSCL = SMCLK/120 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x50; // 7bit address
// UCB0IE |= UCTXIE + UCRXIE;
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
if (UCB0STAT & UCBBUSY) // test if bus to be free
{ // otherwise a manual Clock on is
// generated
P3SEL &= ~EEPROM_CLK; // Select Port function for SCL
P3OUT &= ~EEPROM_CLK; //
P3DIR |= EEPROM_CLK; // drive SCL low
P3SEL |= EEPROM_SDA + EEPROM_CLK; // select module function for the
// used I2C pins
}
}
//----------------------------------------------------------------------------
// Description:
// Initialization of the I2C Module for Write operation.
//----------------------------------------------------------------------------
void I2CWriteInit(void)
{
UCB0CTL1 |= UCTR; // UCTR=1 => Transmit Mode (R/W bit = 0)
UCB0IFG &= ~UCTXIFG;
UCB0IE &= ~UCRXIE; // disable Receive ready interrupt
UCB0IE|= UCTXIE; // enable Transmit ready interrupt
}
//----------------------------------------------------------------------------
// Description:
// Initialization of the I2C Module for Read operation.
//----------------------------------------------------------------------------
void I2CReadInit(void)
{
UCB0CTL1 &= ~UCTR; // UCTR=0 => Receive Mode (R/W bit = 1)
UCB0IFG &= ~UCRXIFG;
UCB0IE &= ~UCTXIE; // disable Transmit ready interrupt
UCB0IE |= UCRXIE; // enable Receive ready interrupt
}
//----------------------------------------------------------------------------
// Description:
// Byte Write Operation. The communication via the I2C bus with an I2C
// (24c04) is realized. A data byte is written into a user defined address.
//----------------------------------------------------------------------------
void EEPROM_ByteWrite(uint16_t Address, uint8_t Data)
{
uint8_t adr_hi;
uint8_t adr_lo;
// FlowFlag = 1;
while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations.
adr_hi = Address >> 8; // calculate high byte
adr_lo = Address & 0xFF; // and low byte of address
I2CBufferArray[2] = adr_hi; // Low byte address.
I2CBufferArray[1] = adr_lo; // High byte address.
I2CBufferArray[0] = Data;
PtrTransmit = 2; //
// UCB0I2CSA = 0x50; // 7bit address
I2CWriteInit();
UCB0CTL1 |= UCTXSTT; // TX Mode , start condition generation
// => I2C communication is started
// while(FlowFlag);
// FlowFlag = 1;
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
UCB0CTL1 |= UCTXSTP; // I2C stop condition
while(UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
}
//----------------------------------------------------------------------------
// Description:
// Random Read Operation. Data is read from the I2C. The I2C
// address is defined with the parameter Address.
//----------------------------------------------------------------------------
uint8_t EEPROM_ByteRead(uint16_t Address)
{
uint8_t adr_hi;
uint8_t adr_lo;
while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations
adr_hi = Address >> 8; // calculate high byte
adr_lo = Address & 0xFF; // and low byte of address
I2CBufferArray[1] = adr_hi; // store single bytes that have to
I2CBufferArray[0] = adr_lo; // be sent in the I2CBuffer.
PtrTransmit = 1;
// Write Address first
I2CWriteInit();
UCB0CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
// Read Data byte
I2CReadInit();
UCB0CTL1 |= UCTXSTT; // I2C start condition
while(UCB0CTL1 & UCTXSTT); // Start condition sent?
UCB0CTL1 |= UCTXSTP; // I2C stop condition
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
return I2CBuffer;
}
void EEPROM_AckPolling(void)
{
while(UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations
do
{
UCB0STAT = 0x00; // clear I2C interrupt flags
UCB0CTL1 |= UCTR; // I2CTRX=1 => Transmit Mode (R/W bit = 0)
UCB0CTL1 &= ~UCTXSTT;
UCB0CTL1 |= UCTXSTT; // start condition is generated
while(UCB0CTL1 & UCTXSTT) // wait till I2CSTT bit was cleared
{
if(!(UCNACKIFG & UCB0STAT)) // Break out if ACK received
break;
}
UCB0CTL1 |= UCTXSTP; // stop condition is generated after
// slave address was sent => I2C communication is started
while(UCB0CTL1 & UCTXSTP); // wait till stop bit is reset
__delay_cycles(500); // Software delay
}
while(UCNACKIFG & UCB0STAT);
}
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch(__even_in_range(UCB0IV,12))
{
case 0: break; // Vector 0: No interrupts
case 2: break; // Vector 2: ALIFG
case 4: break; // Vector 4: NACKIFG
case 6: break;
case 8: break;
case 10: // Vector 10: RXIFG
I2CBuffer = UCB0RXBUF; // store received data in buffer
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
break;
case 12: // Vector 12: TXIFG
UCB0TXBUF = I2CBufferArray[PtrTransmit]; // Load TX buffer
PtrTransmit--; // Decrement TX byte counter
if(PtrTransmit < 0)
{
while(!(UCB0IFG & UCTXIFG));
UCB0IE &= ~UCTXIE; // disable interrupts.
UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}
break;
default: break;
}
}
/*
void Init_I2C(void)
{
P3SEL |= EEPROM_SDA + EEPROM_CLK; // Assign I2C pins to USCI_B0
// Recommended initialisation steps of I2C module as shown in User Guide:
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCTR + UCSWRST; // Use SMCLK, TX mode, keep SW reset
UCB0BR0 = 120; // fSCL = SMCLK/120 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x50; // define Slave Address
// In this case the Slave Address
// defines the control byte that is
// sent to the EEPROM.
// UCB0I2COA = 0x01A5; // own address.
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
if(UCB0STAT & UCBBUSY) // test if bus to be free
{ // otherwise a manual Clock on is
// generated
P3SEL &= ~EEPROM_CLK; // Select Port function for SCL
P3OUT &= ~EEPROM_CLK; //
P3DIR |= EEPROM_CLK; // drive SCL low
P3SEL |= EEPROM_SDA + EEPROM_CLK; // select module function for the
// used I2C pins
}
}
void I2CWriteInit(void)
{
UCB0CTL1 |= UCTR; // UCTR=1 => Transmit Mode (R/W bit = 0)
UCB0IFG &= ~UCTXIFG;
UCB0IE &= ~UCRXIE; // disable Receive ready interrupt
UCB0IE|= UCTXIE; // enable Transmit ready interrupt
}
void I2CReadInit(void)
{
UCB0CTL1 &= ~UCTR; // UCTR=0 => Receive Mode (R/W bit = 1)
UCB0IFG &= ~UCRXIFG;
UCB0IE &= ~UCTXIE; // disable Transmit ready interrupt
UCB0IE |= UCRXIE; // enable Receive ready interrupt
}
void EEPROM_ByteWrite(uint16_t Address, uint8_t Data)
{
uint8_t adr_hi;
uint8_t adr_lo;
while(UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations.
adr_hi = Address >> 8; // calculate high byte
adr_lo = Address & 0xFF; // and low byte of address
I2CBufferArray[2] = adr_hi; // Low byte address.
I2CBufferArray[1] = adr_lo; // High byte address.
I2CBufferArray[0] = Data;
PtrTransmit = 2; // set I2CBufferArray Pointer
I2CWriteInit();
UCB0CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
UCB0CTL1 |= UCTXSTP; // I2C stop condition
while(UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
}
uint8_t EEPROM_ByteRead(uint16_t Address)
{
uint8_t adr_hi;
uint8_t adr_lo;
while(UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations
adr_hi = Address >> 8; // calculate high byte
adr_lo = Address & 0xFF; // and low byte of address
I2CBufferArray[1] = adr_hi; // store single bytes that have to
I2CBufferArray[0] = adr_lo; // be sent in the I2CBuffer.
PtrTransmit = 1; // set I2CBufferArray Pointer
// Write Address first
I2CWriteInit();
UCB0CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
// Read Data byte
I2CReadInit();
UCB0CTL1 |= UCTXSTT; // I2C start condition
while(UCB0CTL1 & UCTXSTT); // Start condition sent?
UCB0CTL1 |= UCTXSTP; // I2C stop condition
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
return I2CBuffer;
}
void EEPROM_AckPolling(void)
{
while(UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations
do
{
UCB0STAT = 0x00; // clear I2C interrupt flags
UCB0CTL1 |= UCTR; // I2CTRX=1 => Transmit Mode (R/W bit = 0)
UCB0CTL1 &= ~UCTXSTT;
UCB0CTL1 |= UCTXSTT; // start condition is generated
while(UCB0CTL1 & UCTXSTT) // wait till I2CSTT bit was cleared
{
if(!(UCNACKIFG & UCB0STAT)) // Break out if ACK received
break;
}
UCB0CTL1 |= UCTXSTP; // stop condition is generated after
// slave address was sent => I2C communication is started
while(UCB0CTL1 & UCTXSTP); // wait till stop bit is reset
__delay_cycles(500); // Software delay
}
while(UCNACKIFG & UCB0STAT);
}
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch(__even_in_range(UCB0IV,12))
{
case 0: break; // Vector 0: No interrupts
case 2: break; // Vector 2: ALIFG
case 4: break; // Vector 4: NACKIFG
case 6: break;
case 8: break;
case 10: // Vector 10: RXIFG
I2CBuffer = UCB0RXBUF; // store received data in buffer
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
break;
case 12: // Vector 12: TXIFG
UCB0TXBUF = I2CBufferArray[PtrTransmit]; // Load TX buffer
PtrTransmit--; // Decrement TX byte counter
if(PtrTransmit < 0)
{
while(!(UCB0IFG & UCTXIFG));
UCB0IE &= ~UCTXIE; // disable interrupts.
UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}
break;
default: break;
}
}
*/
When you see the main.c, I modify based on slaa208a.
when Read opration, after set the TX address then move to LPM0. then even though TX interrupt is coming, it doesn't awake and it is stopped after lpm0.
Please check whether there's another problem except I2C or let me know where I need to modify.
if you have the reference with 5419 and eeprom please introduce it.
Best Regards,
Jay.