主题中讨论的其他器件: MSP430F5529
你好。
我正在使用 MSP430FR5994和 I2C EEPROM。 我在迁移部分工作的 I2Croutines.c 时遇到一些困难。
写入 EEPROM 后、电池消耗过多、读取 EEPROM 时不会发生这种情况。
使用另一个 MSP430F5529、写入和读取工作正常、而不会改变电池消耗。
是否有人可以指导我、或者他们是否知道 MSP430FR5994寄存器以更正所附的代码?
我感谢每个人的冷气!
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。