Part Number: MSP430FR5994
Other Parts Discussed in Thread: MSP430F5529
Hello.
I am working with MSP430FR5994 and I2C EEPROM. I have some difficulties to migrate the I2Croutines.c that works in parts.
After writing to the EEPROM, excessive battery consumption occurs, something that does not happen when reading the EEPROM.
Using another MSP430F5529, both writing and reading work correctly without changing battery consumption.
Could anyone guide me or if they know the MSP430FR5994 registers to correct the attached code?
I appreciate the colaboration of everyone!
MSP430FR5994 I2C Pin Configuration
////////////////////////////////////////////////////////////////////////////////
// Definição da Porta P5 como Serial I2C das Memórias EEPROMS //
////////////////////////////////////////////////////////////////////////////////
P5OUT = 0; // Reseta Todos os Pinos da Porta P5
P5DIR = 0xFF; // Define Todos os Pinos da Porta P5 como Saídas
P5OUT &=~ 0xFF; // Inicializa Todos os Pinos da Porta P5 com Nível Lógico "0" Baixo
P5SEL0 |= BIT0 | BIT1; // Seleciona o Pino da Porta P5.0 UCB1SDA e P5.1 UCB1SCL como Barramento I2C
P5SEL1 &= ~(BIT0 | BIT1); // Seleciona Módulo Primário Conforme Tabela I/O Function Selection
// Configuração do Barramento I2C das Memórias EEPROMs
UCB1CTLW0 = UCSWRST; // Enable SW reset
UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK; // I2C Master, synchronous mode
UCB1BRW = 160; // fSCL = SMCLK/160 = 100 kHz
UCB1CTLW1 |= 0x40; // Use SMCLK, TX mode, keep SW reset
UCB1CTLW1 |= UCASTP_2;
UCB1CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
//UCB1IE |= UCNACKIE + UCALIE + UCSTPIE + UCSTTIE + UCTXIE0 + UCRXIE0 | UCBCNTIE | USCI_I2C_UCCLTOIFG; // Interrupts Enable
UCB1IE |= UCNACKIE + UCTXIE0 + UCRXIE0; // Interrupts Enable
I2Croutines.h
void InitI2C(char eeprom_i2c_address);
void EEPROM_ByteWrite(unsigned int Address , char Data);
void EEPROM_PageWrite(unsigned int StartAddress , char * Data , unsigned int Size);
char EEPROM_RandomRead(unsigned int Address);
char EEPROM_CurrentAddressRead(void);
void EEPROM_SequentialRead(unsigned int Address , char * Data , unsigned int Size);
void EEPROM_AckPolling(void);
I2CRoutines.c
#include "I2Croutines.h"
#include "delay.h"
#define MAXPAGEWRITE 33
int PtrTransmit;
char I2CBufferArray[66];
char I2CBuffer;
/*----------------------------------------------------------------------------*/
// Description:
// Initialization of the I2C Module
/*----------------------------------------------------------------------------*/
void InitI2C(char eeprom_i2c_address)
{
while (UCB1STAT & UCBUSY); // wait until I2C module has
// finished all operations.
// Direciona para o Endereço de Memória EEPROM Correto para o Uso
UCB1I2CSA = eeprom_i2c_address; // define Slave Address
// In this case the Slave Address
// defines the control byte that is
// sent to the EEPROM.
}
/*---------------------------------------------------------------------------*/
// Description:
// Initialization of the I2C Module for Write operation.
/*---------------------------------------------------------------------------*/
void I2CWriteInit(void)
{
UCB1CTL1 |= UCTR; // UCTR=1 => Transmit Mode (R/W bit = 0)
UCB1IFG &= ~UCTXIFG;
UCB1IE &= ~UCRXIE; // disable Receive ready interrupt
UCB1IE |= UCTXIE; // enable Transmit ready interrupt
}
/*----------------------------------------------------------------------------*/
// Description:
// Initialization of the I2C Module for Read operation.
/*----------------------------------------------------------------------------*/
void I2CReadInit(void)
{
UCB1CTL1 &= ~UCTR; // UCTR=0 => Receive Mode (R/W bit = 1)
UCB1IFG &= ~UCRXIFG;
UCB1IE &= ~UCTXIE; // disable Transmit ready interrupt
UCB1IE |= UCRXIE; // enable Receive ready interrupt
}
/*----------------------------------------------------------------------------*/
// Description:
// Byte Write Operation. The communication via the I2C bus with an EEPROM
// (2465) is realized. A data byte is written into a user defined address.
/*----------------------------------------------------------------------------*/
void EEPROM_ByteWrite(unsigned int Address, char Data)
{
char adr_hi;
char adr_lo;
while (UCB1STAT & 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();
UCB1CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
UCB1CTL1 |= UCTXSTP; // I2C stop condition
while(UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent
}
/*----------------------------------------------------------------------------*/
// Description:
// Page Write Operation. The communication via the I2C bus with an EEPROM
// (24xx65) is realized. A data byte is written into a user defined address.
/*----------------------------------------------------------------------------*/
void EEPROM_PageWrite(unsigned int StartAddress, char * Data, unsigned int Size)
{
volatile unsigned int i = 0;
volatile char counterI2cBuffer;
char adr_hi;
char adr_lo;
unsigned int currentAddress = StartAddress;
unsigned int currentSize = Size;
unsigned int bufferPtr = 0;
char moreDataToRead = 1;
while (UCB1STAT & UCBUSY); // wait until I2C module has
// finished all operations.
// Execute until no more data in Data buffer
while(moreDataToRead)
{
adr_hi = currentAddress >> 8; // calculate high byte
adr_lo = currentAddress & 0xFF; // and low byte of address
// Chop data down to 64-byte packets to be transmitted at a time
// Maintain pointer of current startaddress
if(currentSize > MAXPAGEWRITE)
{
bufferPtr = bufferPtr + MAXPAGEWRITE;
counterI2cBuffer = MAXPAGEWRITE - 1;
PtrTransmit = MAXPAGEWRITE + 1; // set I2CBufferArray Pointer
currentSize = currentSize - MAXPAGEWRITE;
currentAddress = currentAddress + MAXPAGEWRITE;
// Get start address
I2CBufferArray[MAXPAGEWRITE + 1] = adr_hi; // High byte address.
I2CBufferArray[MAXPAGEWRITE] = adr_lo; // Low byte address.
}
else
{
bufferPtr = bufferPtr + currentSize;
counterI2cBuffer = currentSize - 1;
PtrTransmit = currentSize + 1; // set I2CBufferArray Pointer.
moreDataToRead = 0;
currentAddress = currentAddress + currentSize;
// Get start address
I2CBufferArray[currentSize + 1] = adr_hi; // High byte address.
I2CBufferArray[currentSize] = adr_lo; // Low byte address.
}
// Copy data to I2CBufferArray
char temp;
for(i ; i < bufferPtr ; i++)
{
temp = Data[i]; // Required or else IAR throws a
// warning [Pa082]
I2CBufferArray[counterI2cBuffer] = temp;
counterI2cBuffer--;
}
I2CWriteInit();
UCB1CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
UCB1CTL1 |= UCTXSTP; // I2C stop condition
while(UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent
EEPROM_AckPolling(); // Ensure data is written in EEPROM
}
}
/*----------------------------------------------------------------------------*/
// Description:
// Current Address Read Operation. Data is read from the EEPROM. The current
// address from the EEPROM is used.
/*----------------------------------------------------------------------------*/
char EEPROM_CurrentAddressRead(void)
{
while(UCB1STAT & UCBUSY); // wait until I2C module has
// finished all operations
I2CReadInit();
UCB1CTL1 |= UCTXSTT; // I2C start condition
while(UCB1CTL1 & UCTXSTT); // Start condition sent?
UCB1CTL1 |= UCTXSTP; // I2C stop condition
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent
return I2CBuffer;
}
/*----------------------------------------------------------------------------*/
// Description:
// Random Read Operation. Data is read from the EEPROM. The EEPROM
// address is defined with the parameter Address.
/*----------------------------------------------------------------------------*/
char EEPROM_RandomRead(unsigned int Address)
{
char adr_hi;
char adr_lo;
while (UCB1STAT & 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();
UCB1CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
// Read Data byte
I2CReadInit();
UCB1CTL1 |= UCTXSTT; // I2C start condition
while(UCB1CTL1 & UCTXSTT); // Start condition sent?
UCB1CTL1 |= UCTXSTP; // I2C stop condition
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent
return I2CBuffer;
}
/*----------------------------------------------------------------------------*/
// Description:
// Sequential Read Operation. Data is read from the EEPROM in a sequential
// form from the parameter address as a starting point. Specify the size to
// be read and populate to a Data buffer.
/*----------------------------------------------------------------------------*/
void EEPROM_SequentialRead(unsigned int Address , char * Data , unsigned int Size)
{
char adr_hi;
char adr_lo;
unsigned int counterSize;
while (UCB1STAT & 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();
UCB1CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
// Read Data byte
I2CReadInit();
UCB1CTL1 |= UCTXSTT; // I2C start condition
while(UCB1CTL1 & UCTXSTT); // Start condition sent?
for(counterSize = 0 ; counterSize < Size ; counterSize++)
{
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
Data[counterSize] = I2CBuffer;
}
UCB1CTL1 |= UCTXSTP; // I2C stop condition
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts
while(UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent
}
/*----------------------------------------------------------------------------*/
// Description:
// Acknowledge Polling. The EEPROM will not acknowledge if a write cycle is
// in progress. It can be used to determine when a write cycle is completed.
/*----------------------------------------------------------------------------*/
void EEPROM_AckPolling(void)
{
while (UCB1STAT & UCBUSY); // wait until I2C module has
// finished all operations
do
{
UCB1STAT = 0x00; // clear I2C interrupt flags
UCB1CTL1 |= UCTR; // I2CTRX=1 => Transmit Mode (R/W bit = 0)
UCB1CTL1 &= ~UCTXSTT;
UCB1CTL1 |= UCTXSTT; // start condition is generated
while(UCB1CTL1 & UCTXSTT) // wait till I2CSTT bit was cleared
{
if(!(UCNACKIFG & UCB1STAT)) // Break out if ACK received
break;
}
UCB1CTL1 |= UCTXSTP; // stop condition is generated after
// slave address was sent => I2C communication is started
while (UCB1CTL1 & UCTXSTP); // wait till stop bit is reset
delay_ms(5); // Aguarda 5 milisegundos
}while(UCNACKIFG & UCB1STAT);
}
/*----------------------------------------------------------------------------*/
// Interrupt Service Routines
// Note that the Compiler version is checked in the following code and
// depending of the Compiler Version the correct Interrupt Service
// Routine definition is used.
/*----------------------------------------------------------------------------*/
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = EUSCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(EUSCI_B1_VECTOR))) USCI_B1_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCB1IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: break; // Vector 4: NACKIFG
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0
I2CBuffer = UCB1RXBUF; // store received data in buffer
__bic_SR_register_on_exit(LPM3_bits); // Exit LPM0
break;
case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0
UCB1TXBUF = I2CBufferArray[PtrTransmit]; // Load TX buffer
PtrTransmit--; // Decrement TX byte counter
if(PtrTransmit < 0)
{
while (!(UCB1IFG & UCTXIFG)); // USCI_B1 TX buffer ready?
UCB1IE &= ~UCTXIE; // disable interrupts.
UCB1IFG &= ~UCTXIFG; // Clear USCI_B1 TX int flag
__bic_SR_register_on_exit(LPM3_bits); // Exit LPM3
}
break;
case USCI_I2C_UCBCNTIFG: break; // Vector 26: BCNTIFG
case USCI_I2C_UCCLTOIFG: break; // Vector 28: clock low timeout
case USCI_I2C_UCBIT9IFG: break; // Vector 30: 9th bit
default: break;
}
}
Anderson Portela.