主题中讨论的其他器件: 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。