This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello everyone! I am trying to connect and run this program below with an EEPROM 24LC1025 via I2C but it is locking and does not exit the loop as described:
// Copy data to I2CBufferArray unsigned char temp; for(i ; i < bufferPtr ; i++) { temp = Data[i]; // Required or else IAR throws a // warning [Pa082] I2CBufferArray[counterI2cBuffer] = temp; counterI2cBuffer--; }
#define I2C_PORT_SEL P3SEL #define I2C_PORT_OUT P3OUT #define I2C_PORT_REN P3REN #define I2C_PORT_DIR P3DIR #define SDA_PIN BIT0 // UCB0SDA pin P3.0 #define SCL_PIN BIT1 // UCB0SCL pin P3.1 #define SCL_CLOCK_DIV 0x0A // SCL clock devider void InitI2C(unsigned char eeprom_i2c_address); void EEPROM_ByteWrite(unsigned int Address , unsigned char Data); void EEPROM_PageWrite(unsigned int StartAddress , unsigned char * Data , unsigned int Size); unsigned char EEPROM_RandomRead(unsigned int Address); unsigned char EEPROM_CurrentAddressRead(void); void EEPROM_SequentialRead(unsigned int Address , unsigned char * Data , unsigned int Size); void EEPROM_AckPolling(void);
#include <MSP430F5529.h> #include "I2Croutines.h" #define MAXPAGEWRITE 64 int PtrTransmit; unsigned char I2CBufferArray[66]; unsigned char I2CBuffer; /*----------------------------------------------------------------------------*/ // Description: // Initialization of the I2C Module /*----------------------------------------------------------------------------*/ void InitI2C(unsigned char eeprom_i2c_address) { I2C_PORT_DIR |= SDA_PIN + SCL_PIN; I2C_PORT_SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0 I2C_PORT_OUT |= SDA_PIN + SCL_PIN; // 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 = SCL_CLOCK_DIV; // fSCL = SMCLK/11 = 95.3kHz UCB0BR1 = 0; UCB0I2CSA = eeprom_i2c_address; // define Slave Address // In this case the Slave Address // defines the control byte that is // sent to the EEPROM. //UCB0I2COA = 0x01A5; // own address. UCB0IE |= UCTXIE + UCRXIE + UCNACKIE; UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation if (UCB0STAT & UCBBUSY) // test if bus to be free { // otherwise a manual Clock on is // generated I2C_PORT_SEL &= ~SCL_PIN; // Select Port function for SCL I2C_PORT_OUT &= ~SCL_PIN; // I2C_PORT_DIR |= SCL_PIN; // drive SCL low I2C_PORT_SEL |= SDA_PIN + SCL_PIN; // select module function for the // used I2C pins }; __enable_interrupt(); } /*---------------------------------------------------------------------------*/ // 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 EEPROM // (2465) is realized. A data byte is written into a user defined address. /*----------------------------------------------------------------------------*/ void EEPROM_ByteWrite(unsigned int Address, unsigned char Data) { unsigned char adr_hi; unsigned char 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(LPM3_bits + GIE); // Enter LPM0 w/ interrupts UCB0CTL1 |= UCTXSTP; // I2C stop condition while(UCB0CTL1 & 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, unsigned char * Data, unsigned int Size) { volatile unsigned int i = 0; volatile unsigned char counterI2cBuffer; unsigned char adr_hi; unsigned char adr_lo; unsigned int currentAddress = StartAddress; unsigned int currentSize = Size; unsigned int bufferPtr = 0; unsigned char moreDataToRead = 1; while (UCB0STAT & 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 unsigned char temp; for(i ; i < bufferPtr ; i++) { temp = Data[i]; // Required or else IAR throws a // warning [Pa082] I2CBufferArray[counterI2cBuffer] = temp; counterI2cBuffer--; } I2CWriteInit(); UCB0CTL1 |= UCTXSTT; // start condition generation // => I2C communication is started __bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts UCB0CTL1 |= UCTXSTP; // I2C stop condition while(UCB0CTL1 & 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. /*----------------------------------------------------------------------------*/ unsigned char EEPROM_CurrentAddressRead(void) { while(UCB0STAT & UCBUSY); // wait until I2C module has // finished all operations I2CReadInit(); UCB0CTL1 |= UCTXSTT; // I2C start condition while(UCB0CTL1 & UCTXSTT); // Start condition sent? UCB0CTL1 |= UCTXSTP; // I2C stop condition __bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts while(UCB0CTL1 & 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. /*----------------------------------------------------------------------------*/ unsigned char EEPROM_RandomRead(unsigned int Address) { unsigned char adr_hi; unsigned char 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(LPM3_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(LPM3_bits + GIE); // Enter LPM0 w/ interrupts while(UCB0CTL1 & 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 , unsigned char * Data , unsigned int Size) { unsigned char adr_hi; unsigned char adr_lo; unsigned int counterSize; 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(LPM3_bits + GIE); // Enter LPM0 w/ interrupts // Read Data byte I2CReadInit(); UCB0CTL1 |= UCTXSTT; // I2C start condition while(UCB0CTL1 & UCTXSTT); // Start condition sent? for(counterSize = 0 ; counterSize < Size ; counterSize++) { __bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts Data[counterSize] = I2CBuffer; } UCB0CTL1 |= UCTXSTP; // I2C stop condition __bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts while(UCB0CTL1 & 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 (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); } /*---------------------------------------------------------------------------*/ /* 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=USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) #else #error Compiler not supported! #endif { if(UCTXIFG & UCB0IFG) { UCB0TXBUF = I2CBufferArray[PtrTransmit];// Load TX buffer PtrTransmit--; // Decrement TX byte counter if(PtrTransmit < 0) { while (!(UCB0IFG & UCTXIFG)); // USCI_B0 TX buffer ready? UCB0IE &= ~UCTXIE; // disable interrupts. UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(LPM3_bits); // Exit LPM0 } } else if(UCRXIFG & UCB0IFG) { I2CBuffer = UCB0RXBUF; // store received data in buffer __bic_SR_register_on_exit(LPM3_bits); // Exit LPM0 } }
#include <MSP430F5529.h> #include "I2Croutines.h" #include <stdio.h> #include <intrinsics.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stdint.h> #include <math.h> //****************************************************************************// // Endereço (s) da(s) Memória (s) do Data Logger // //****************************************************************************// #define Banco1 0x50 // Endereço 0x50 do Banco 0 da EEPROM 24LC1025 #define Banco2 0x54 // Endereço 0x51 do Banco 1 da EEPROM 24LC1025 #define Banco3 0x51 // Endereço 0x54 do Banco 0 da EEPROM 24LC1025 #define Banco4 0x55 // Endereço 0x55 do Banco 1 da EEPROM 24LC1025 unsigned char VerNome[33] = "Teste com Memoria EEPROM 24LC1025"; unsigned char Unidade_Coletado[5] = "m3/h"; unsigned int MS_Byte, LS_Byte; unsigned int Memoria = 65535; unsigned char *Ponteiro_Geral; float Constante_Bateria = 3.12345; int length = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Desabilita o WDT // Set up XT1 P5SEL |= BIT4+BIT5; // Select XT1 UCSCTL6 &= ~(XT1OFF); // XT1 On UCSCTL6 |= XCAP_3; // Internal load cap UCSCTL3 = 0; // FLL Reference Clock = XT1 //SFRIE1 = OFIE; // Enable osc fault interrupt // Disable VUSB LDO and SLDO USBKEYPID = 0x9628; // set USB KEYandPID to 0x9628 // access to USB config registers enabled USBPWRCTL &= ~(SLDOEN+VUSBEN); // Disable the VUSB LDO and the SLDO USBKEYPID = 0x9600; // access to USB config registers disabled // Disable SVS PMMCTL0_H = PMMPW_H; // PMM Password SVSMHCTL &= ~(SVMHE+SVSHE); // Disable High side SVS SVSMLCTL &= ~(SVMLE+SVSLE); // Disable Low side SVS // P1.2/TA0.1 P1DIR |= BIT0; // P1.0 output RTCCTL01 = RTCTEV_3; RTCPS0CTL = RT0PSDIV_7; // Set RTPS0 to /256 RTCPS1CTL = RT1IP_6 + RT1PSIE + RT1SSEL_3;// Set RT1IP to /4, enable // RT1PS interrupt and select // RTOPS output as clock // Rotina para Recuperação de Dados do Nome Atribuido ao Data Logger Anteriormente // Rotinas para Recuperação de Dados do Fator da Vazão, Unidade Coletado e Intervalo Coletado Atribuido ao Data Logger Anteriormente InitI2C(Banco1); // Inicializa o Banco1 da Memória EEPROM EEPROM_PageWrite(0, VerNome, 32); // Salva na Memória EEPROM o Nome dado ao Data Logger for(length=0;length<=32;length++) { VerNome[length] = ' '; } EEPROM_SequentialRead(0 , VerNome , 33); // Resgata o Último Nome Dado ao Data Logger EEPROM_PageWrite(34, Unidade_Coletado, 5); for(length=0;length<=4;length++) { Unidade_Coletado[length] = 0; } EEPROM_SequentialRead(34 , Unidade_Coletado , 5); MS_Byte = Memoria; // Carrega o Valor Mais Significativo MSD LS_Byte = Memoria>>8; // Carrega o Valor Menos Significativo LSD Memoria = 0; EEPROM_ByteWrite(40,MS_Byte); // Escreve na EEPROM o Byte MSB com o valor do Endereço da Última Memória EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(41,LS_Byte); // Escreve na EEPROM o Byte LSB com o valor do Endereço da Última Memória EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM Memoria = EEPROM_RandomRead(40); // Efetua a Leitura na EEPROM do Byte com o valor do Último Endereço de Memória Salvo Memoria |= ((unsigned int)EEPROM_RandomRead(41)<<8); Ponteiro_Geral = (unsigned char *)&Constante_Bateria; // Armazena o Valor da Constante da Bateria no Ponteiro 32-Bits EEPROM_ByteWrite(42,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(43,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(44,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(45,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(46,*Ponteiro_Geral); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM *Ponteiro_Geral = 0; // Reseta a Variável de Ponteiro para Novo Cilco Constante_Bateria = 0.0; Ponteiro_Geral = (unsigned char *)&Constante_Bateria; // Efetua a Leitura dos Dados do Fator de Vazão Coletado Anteriormente na EEPROM por Ponteiro *Ponteiro_Geral++ = EEPROM_RandomRead(42); *Ponteiro_Geral++ = EEPROM_RandomRead(43); *Ponteiro_Geral++ = EEPROM_RandomRead(44); *Ponteiro_Geral++ = EEPROM_RandomRead(45); *Ponteiro_Geral = EEPROM_RandomRead(46); // Rotinas para Recuperação de Dados do Fator da Vazão, Unidade Coletado e Intervalo Coletado Atribuido ao Data Logger Anteriormente InitI2C(Banco2); // Inicializa o Banco1 da Memória EEPROM EEPROM_PageWrite(0, VerNome, 33); // Salva na Memória EEPROM o Nome dado ao Data Logger for(length=0;length<=32;length++) { VerNome[length] = 0; } EEPROM_SequentialRead(0 , VerNome , 33); // Resgata o Último Nome Dado ao Data Logger EEPROM_PageWrite(34, Unidade_Coletado, 5); for(length=0;length<=4;length++) { Unidade_Coletado[length] = 0; } EEPROM_SequentialRead(34 , Unidade_Coletado , 5); MS_Byte = Memoria; // Carrega o Valor Mais Significativo MSD LS_Byte = Memoria>>8; // Carrega o Valor Menos Significativo LSD Memoria = 0; EEPROM_ByteWrite(40,MS_Byte); // Escreve na EEPROM o Byte MSB com o valor do Endereço da Última Memória EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(41,LS_Byte); // Escreve na EEPROM o Byte LSB com o valor do Endereço da Última Memória EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM Memoria = EEPROM_RandomRead(40); // Efetua a Leitura na EEPROM do Byte com o valor do Último Endereço de Memória Salvo Memoria |= ((unsigned int)EEPROM_RandomRead(41)<<8); Ponteiro_Geral = (unsigned char *)&Constante_Bateria; // Armazena o Valor da Constante da Bateria no Ponteiro 32-Bits EEPROM_ByteWrite(42,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(43,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(44,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(45,*Ponteiro_Geral++); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM EEPROM_ByteWrite(46,*Ponteiro_Geral); // Escreve na EEPROM o Byte com o valor da Constante da Bateria EEPROM_AckPolling(); // Verifica se completou o ciclo de escrita na EEPROM *Ponteiro_Geral = 0; // Reseta a Variável de Ponteiro para Novo Cilco Constante_Bateria = 0.0; Ponteiro_Geral = (unsigned char *)&Constante_Bateria; // Efetua a Leitura dos Dados do Fator de Vazão Coletado Anteriormente na EEPROM por Ponteiro *Ponteiro_Geral++ = EEPROM_RandomRead(42); *Ponteiro_Geral++ = EEPROM_RandomRead(43); *Ponteiro_Geral++ = EEPROM_RandomRead(44); *Ponteiro_Geral++ = EEPROM_RandomRead(45); *Ponteiro_Geral = EEPROM_RandomRead(46); do{ __bis_SR_register(LPM3_bits + GIE); __no_operation(); } while(1); __bis_SR_register(LPM3_bits + GIE); } // RTC Interrupt Service Routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=RTC_VECTOR __interrupt void RTC_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void) #else #error Compiler not supported! #endif { P1OUT ^= 0x01; // Toggle P1.0 RTCCTL01 &= ~RTCTEVIFG; RTCPS1CTL &= ~RT1PSIFG; }
Hello Anderson,
Take a look at the example code below. Are you able to run this code succesfully?
Hello Eddie!
Thank you for your feedback!
I debug this example via IAR and the MSP430F5529LP kit and it hangs at:
void EEPROM_AckPolling(void)
{
.........
.........
while (UCB0CTL1 & UCTXSTP);
__delay_cycles(500);
while(UCNACKIFG & UCB0STAT);
}
The RTC interrupt is running normally.
We have already used this library in our products with the MSP430FG4618 and it works very well.
We need to start using MSP430F5529 with this library now.
I saw in other topics people go through the same problem too.
Can you simulate and debug this example to verify the behavior of USCB0?
**Attention** This is a public forum