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.
FIXED
had wrong understanding of the interrupt routines of the G255. new code can be found in a post below.
Hello everyone,
I am currently trying to interface an F5529 and a G2553 vie I2C. What i try to do is:
F5529 adresses G2553, G2553 sends some bytes.
I have previously used the F5529 with an RPi, the F5529 being the slave and sending data to the RPi on request. So i have basic knowledge on how I2C works. Now, that im trying to interface the G2553, im getting really frustrated. I read a lot of forums and anything else i could find for 2 days now. Seems like im not the only person with problems but i couldnt find any helpful information.
What i do so far:
Other things i noted:
Things im not sure about:
My code (i tried to minimalize it) for the initialization:
#define OWN_ADRESS 0x35
int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1DIR = BIT0; // Set P1.0 to output, rest of P1 to input P1IE = BIT4; // activate interrupts (for counting Geiger impulses) TACTL = TASSEL_1 + MC_2 + TAIE + ID_2; // ACLK, contmode, interrupt, divide by 8; I2C_Setup(OWN_ADRESS); // setup I2C, 0x3B slave adress _bis_SR_register(LPM3_bits + GIE); // Enter LPM3, enable interrupts } void I2C_Setup(short adress){ P1DIR |= BIT6 | BIT7;
P1REN = BIT6 | BIT7; // enable pullups
P1SEL |= BIT6 | BIT7; // I2C Lanes (P1.6-SCL und P1.7-SDA) (Auf peripheriegerät stellen)
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // USCI im Reset Status festhalten UCB0CTL0 = UCMODE_3 + UCSYNC; // slave + I2C + synchroner Modus UCB0BR0 = 0; // recommendation of a forum member UCB0BR1 = 0; // recommendation of a forum member UCB0I2COA = adress; // Set I2C Slave Adress (0x35 as set with the RPi group) and enable its usage UCB0CTL1 &= ~UCSWRST; // release from reset USCI IE2 = UCB0RXIE; // Enable RX interrupt }
I got a timer Interrupt working and a Port 1 interrupt for pin 1.3.
My Interrupt routines for
#define DATA_REQUEST 0x55 // USCI_B0 Data ISR #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCIAB0TX_VECTOR __interrupt void RX_ISR_I2C(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) RX_ISR_I2C (void) #else #error Compiler not supported! #endif { unsigned short in = UCB0RXBUF; int TicksPerMinute; if(in == DATA_REQUEST){ P1OUT ^= BIT0; UCB0I2CIE = UCSTPIE + UCSTTIE; // Transmission started, activate stop interrupts IE2 |= UCB0TXIE; // Enable TX interrupts } UCB0TXBUF = *sendDataPointer++; } // USCI_B0 State ISR #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCIAB0RX_VECTOR __interrupt void USCIAB0RX_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void) #else #error Compiler not supported! #endif { UCB0STAT &= ~(UCSTPIFG + UCSTTIFG + UCNACKIFG); IE2 |= UCB0TXIE; }
Master Code looks like this (im using a self written I2C library that works well with differenc sensors).
I2C0_SetSlaveAdress simply sets UCB0SCA to its parameter, I2C0_SendAndRead sends start+adress+write, writes a single byte, then repstart, reads n bytes and stores them at the given pointer location (and the following registers).This works well
#define GEIGER_ADRESS 0x35 #define GEIGER_GET_DATA 0x55 int Geiger_GetData(){ unsigned short ReceivedValues[2] = {0, 0}; I2C0_SetSlaveAdress(GEIGER_ADRESS); // set 0x35 (adress of Geiger MSP) I2C0_SendAndRead(GEIGER_GET_DATA, 2, ReceivedValues); // Send comand 0x55 (request data) return ((int)(ReceivedValues[0]<<8) + ReceivedValues[1]); }
Ok Im finding some of the answers myself and will post all of them in here in case someone else is having the same questions.
What is a good way of recognizing an I2C master has adressed me and wants data?
Thanks for your detailed answer!
I had managed to get the communication working yesterday evening, should have closed the thread then maybe. On my way home I sorted all the information i got and established the communication successfully, including the checks of UCTR etc. If anyone is intersted in this, here is the source code:
void I2C_Setup(short adress){ // P1DIR |= BIT6 | BIT7; // P1REN &= ~(BIT6 | BIT7); // enable pullups P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0 P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0 UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMODE_3 + UCSYNC; // I2C Slave, synchronous mode UCB0I2COA = 0x35; // Own Address is 035h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB0I2CIE = UCSTPIE + UCSTTIE; // Enable STT and STP interrupt IE2 = UCB0TXIE; // Enable TX interrupt } // USCI_B0 Data ISR #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCIAB0TX_VECTOR __interrupt void USCIAB0TX_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void) #else #error Compiler not supported! #endif { UCB0TXBUF = *sendDataPointer++; } // USCI_B0 State ISR #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCIAB0RX_VECTOR __interrupt void USCIAB0RX_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void) #else #error Compiler not supported! #endif { if ((UCB0STAT & UCSTTIFG) && (UCB0STAT & UCTR)) // Device was adressed, master wants to write { UCB0CTL1 |= UCTXNACK; // send NACK --> Don't read from Bus, make master send stop condition } else if (UCB0STAT & UCSTPIFG) // { __bic_SR_register_on_exit(CPUOFF); // run main() loop to reset everything } UCB0STAT &= ~(UCSTPIFG + UCSTTIFG); }
On solving this, i headed into another problem tho. COmmunication is only successful in debug mode. If you dont mind having a look at this, i created another thread.
**Attention** This is a public forum