Hello,
I am working on MPC5606s Controller. I am trying to implement a I2C RX/TX driver using interrupt vectors. I have an I2C library that works successfully without interrupts, using only "whiles".
Using this following functions the controller does not execute the interrupt. I add the functions that we use to write data.
void I2C0_init(void) { uint8_t i=0; CGM.SC_SS.R = 0x04000000; // MPC56xxS: Select Periph. set 1 clock to be FMPLL0, SEL1 = 0100 Primary FMPLL CGM.SC_DC[0].B.DE = 1; // MPC56xxS: Enable Periph. set 1 clock to I2C //SIU.PCR[I2C0_SDA].R = 0x0527; // PF6 pin as I2C0 SDA, open-drain, weak pull up //SIU.PCR[I2C0_SCL].R = 0x0527; // PF7 pin as I2C0 SCL, open-drain, weak pull up SIU.PCR[I2C0_SDA].R = 0x0520; // PF6 pin as I2C0 SDA, open-drain, SIU.PCR[I2C0_SCL].R = 0x0520; // PF7 pin as I2C0 SCL, open-drain, //I2C_0.IBFD.B.IBC = 0x2D; // SCL div = 640, 64Mhz / 620 = 103226Hz, 100KHz aprox //I2C_0.IBFD.B.IBC = 0x2E; // SCL div = 768, 64Mhz / 768 = 83333Hz, 83KHz aprox I2C_0.IBFD.B.IBC = 0x65; // SCL div = 640, 64Mhz / 640 = 100000Hz, 100KHz aprox I2C_0.IBAD.R = 0x00; // Set module's I2C address to 0x00 I2C_0.IBCR.B.MDIS = 0; // Clear Module Disable / Enable I2C operations, NO IRQ I2C_0.IBSR.B.IBAL = 1; // Clear the IBAL flag; // Reset I2C bus by sending 9xCLK with SDA at low level I2C_0.IBCR.B.MS = 1; // Set IBCR, Master mode select I2C_0.IBCR.B.TX = 1; // Set IBCR, Transmit mode select I2C_0.IBDR.R = 0x00; // Update IBDR, Send slave I2C address while (I2C_0.IBSR.B.IBIF==0){}; // Check IBSR, Wait until IBIF (byte TX complete) or a timeout expires I2C_0.IBSR.B.IBIF=1; // Set IBSR, Clear the interrupt event flag I2C_0.IBCR.B.MS = 0; // Set IBCR, Generate stop signal; I2C_0.IBCR.B.IBIE = 1; // Enable interrupt INTC_InstallINTCInterruptHandler(I2C_Interupt,125,1); }
uint8_t I2C_write(uint8_t dev,uint8_t addr,uint8_t *pData, uint8_t nBytes) { uint8_t i = 0; i2cWrite_cnt = 0; while ((I2C_0.IBSR.B.IBB == 1)){}; // Check IBSR, Wait whiel IBB == 1 (bus busy) I2C_0.IBCR.B.MS = 1; // Set IBCR, Master mode select I2C_0.IBCR.B.TX = 1; // Set IBCR, Transmit mode select I2C_0.IBCR.B.NOACK = 0; I2C_0.IBSR.B.TCF = 1; /* Transfer in progress */ I2C_0.IBDR.R = dev; // Update IBDR, Send slave I2C address iic_addr = addr; // Copy address -> iic_addr iic_len = nBytes; // Byes to send in interrupt = len for(i=0; i<nBytes; i++) { iic_buffer[i] = *(pData + i); } entery = 0; }
void I2C_Interupt(void) { // uint8_t entery = 0; uint8_t i = 0; if((I2C_0.IBSR.B.TCF == 1) && (ack_flag==1)) /* If transfer is completed */ { entery++; ack_flag= 0; if(entery == 1) { I2C_0.IBDR.R = iic_addr; /* Update IBDR, send internal address of I2C slave */ } else if (entery <= iic_len) { I2C_0.IBDR.R = iic_buffer[entery-2]; } else { entery = 0; I2C_0.IBCR.B.MS = 0; /* Set IBCR, Generate stop signal; */ } } I2C_0.IBCR.B.MDIS = 0; // Clear Module Enable I2C operations, NO IRQ }
Thank
Josep
I suppose you are using CodeWarrior.
1) Macro “#define CALL_USR_INIT 1” must be defined in C/C++ preprocessor to properly initialized interrupts and exception.
2) After calling INTC_InstallINTCInterruptHandler, current interrupt priority must be decreased to unmask interrupt.
3) I see potential issues in using of .B instance during access to status registers. Pay attention to following document, especially section 3.2: