Is there anyone at Freescale available to help with the I2C operation for the KEA-64. I am having issues reading back the response from an I2C device, There seems to be an issue having the KEA-64 provide the clock signal for the sensor device to replay with the requested data. This is the main issue preventing my proposed demo project from going live, any help would be very much appreciated.
Thanks
Kas
P.s. I have attached my code for a read from address 0x4B register 0x0B, there is just no clock for the devices response from that register.
#include "derivative.h" /* include peripheral declarations */
#define MWSR 0x00 /* Master write */
#define MRSW 0x01 /* Master read */
#define i2c_Start() I2C0_C1 |= 0x10;\
I2C0_C1 |= I2C_C1_MST_MASK
#define i2c_write_byte(data) I2C0_D = data
#define i2c_Wait() while((I2C0_S & I2C_S_IICIF_MASK)==0) {} \
I2C0_S |= I2C_S_IICIF_MASK;
#define i2c_Stop() I2C0_C1 &= ~I2C_C1_MST_MASK;\
I2C0_C1 &= ~I2C_C1_TX_MASK
unsigned char MasterTransmission;
/*******************************************************************/
/*!
* Pause Routine
*/
void Pause(void){
int n;
for(n=1;n<50;n++) {
asm("nop");
}
}
/***********************************************************************************************
*
* @brief Uart_SendChar - Send a single byte on Uart1
* @param byte to send
* @return none
*
************************************************************************************************/
void Uart_SendChar(uint8_t send)
{
while((UART2_S1&UART_S1_TDRE_MASK)==0);
(void)UART2_S1;
UART2_D=send;
}
void writeRegister(unsigned char slaveID, unsigned char registerAddress, unsigned char data)
{
MasterTransmission = MWSR;
slaveID = slaveID << 1;
slaveID |= MasterTransmission;
i2c_Start();
i2c_write_byte(slaveID);
i2c_Wait();
I2C0_D = registerAddress;
i2c_Wait();
I2C0_D = data;
i2c_Wait();
i2c_Stop();
}
void Clk_Init()
{
ICS_C1|=ICS_C1_IRCLKEN_MASK; /* Enable the internal reference clock*/
ICS_C3= 0x50; /* Reference clock frequency = 39.0625 KHz*/
while(!(ICS_S & ICS_S_LOCK_MASK)); /* Wait for PLL lock, now running at 40 MHz (1024 * 39.0625Khz) */
ICS_C2|=ICS_C2_BDIV(1) ; /*BDIV=2, Bus clock = 20 MHz*/
ICS_S |= ICS_S_LOCK_MASK ; /* Clear Loss of lock sticky bit */
}
void UART_Init()
{
SIM_SCGC |= SIM_SCGC_UART2_MASK;
UART2_BDL= 128;
UART2_C1 = 0;
UART2_C2 |= UART_C2_TE_MASK;
UART2_C2 |= UART_C2_RE_MASK;
UART2_C2 |= UART_C2_RIE_MASK;
}
void i2cInit(){
//I2C setup
SIM_SCGC |= SIM_SCGC_I2C_MASK;
SIM_PINSEL |= SIM_PINSEL_I2C0PS_MASK;
I2C0_F = 0x00;
I2C0_C1 = I2C_C1_IICEN_MASK | I2C_C1_MST_MASK | I2C_C1_IICIE_MASK;
}
int main(void)
{
long int delay;
unsigned char i;
unsigned char replay;
char string[] = "My name is Bob C. Marley \r\n\r\n";
Clk_Init();
UART_Init();
SIM_SCGC |= SIM_SCGC_I2C_MASK;
SIM_PINSEL |= SIM_PINSEL_I2C0PS_MASK;
I2C0_F = 0x11;
I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_IICEN_MASK;
I2C0_D = 0x96;
while ((I2C0_S & I2C_S_IICIF_MASK) == 0){
//Wait for data to transmit
}
I2C0_S |= I2C_S_IICIF_MASK;
I2C0_D = 0x0B;
while ((I2C0_S & I2C_S_IICIF_MASK) == 0){
//Wait for data to transmit
}
I2C0_S |= I2C_S_IICIF_MASK;
//Restart
I2C0_C1 |= I2C_C1_RSTA_MASK;
I2C0_D = 0x97;
while ((I2C0_S & I2C_S_IICIF_MASK) == 0){
//Wait for data to transmit
}
I2C0_S |= I2C_S_IICIF_MASK;
I2C0_C1 &= !I2C_C1_TX_MASK;
I2C0_C1 |= I2C_C1_TXAK_MASK;
replay = I2C0_D;
while ((I2C0_S & I2C_S_IICIF_MASK) == 0){
//Wait for data to transmit
}
while(1) {
for (i = 0; string[i] != '\0'; i++){
Uart_SendChar(string[i]);
}
for(delay = 0; delay < 99999; delay++);
}
return 0;
}
Hi,
KEA product is using the same I2C module with KE06 product.
Customer could download CodeWarrior MCU V10.6 software, there provides KE06 product I2C module application code at default installation path:
C:\Freescale\CW MCU v10.6\MCU\CodeWarrior_Examples\Kinetis_Examples\KE\build\cw\ke06\I2C_MasterInt_demo
I also attached KE06 I2C driver for your reference.
Wish it helps.
best regards
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I have looked through a few Freescale I2C demo code for the KEA or other Kinetis boards but none work. Some are just plainly wrong (do not seem to know how to read a register... ) and others just don't make sense. Any real help would be much appreciated, a tried, tested and know to be good demo would be helpful but so far what I have seems to be coded with no testing or any real thought.
Kas
Hi Kas,
Which I2C device you are using?
Wish it helps.
best regards
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hello Ma,
I am using a PmodTMP2 from Digilent that has a Analog Devices ADT7420 on board. I have added two 4.7k pull up resistors one to the SCL line and the other to the SDA line. I can see the KEA-64 sending data but when it comes to recive data from the ADT7420 the KEA-64 does not provide a clock source. I have tried a dummy read and a dummy write but neither seem to provide a clock source.
Kas
Hi Kas,
Analog Devices ADT7420 with the same I2C process with MMA8451 chip.
ADT7420 register read process:
MMA8451 register read process:
Customer could refer K60 100MHz i2c_demo from attached file, which shows how to read data from MMA8451 chip.
I just abstract the read register processing for your reference:
u8 hal_dev_mma8451_read_reg(u8 addr)
{
u8 result;
i2c_start(I2C0_B);
i2c_write_byte(I2C0_B, I2C_ADDR_MMA8451 | I2C_WRITE);
i2c_wait(I2C0_B);
i2c_get_ack(I2C0_B);
i2c_write_byte(I2C0_B, addr);
i2c_wait(I2C0_B);
i2c_get_ack(I2C0_B);
i2c_repeated_start(I2C0_B);
i2c_write_byte(I2C0_B, I2C_ADDR_MMA8451 | I2C_READ);
i2c_wait(I2C0_B);
i2c_get_ack(I2C0_B);
i2c_set_rx_mode(I2C0_B);
i2c_give_nack(I2C0_B);
result = i2c_read_byte(I2C0_B);
i2c_wait(I2C0_B);
i2c_stop(I2C0_B);
result = i2c_read_byte(I2C0_B);
pause();
return result;
}
While K60_100MHz I2C module with a little different with KEA I2C module at I2Cx_FLT register.
Kinetis KE series product with the same I2C module with KEA product, there also with I2C read data from MM8451 example with Processor Expert project.
Customer could find related example from CW V10.6 installation path:
C:\Freescale\CW MCU v10.6\MCU\CodeWarrior_Examples\Processor_Expert\Kinetis\FRDM-KE06Z\I2C_PWM
I also attached that example at this thread for your reference.
Wish it helps.
best regards
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hello Ma,
Can you please look over the code I have posted as it looks very similar, I just do not use macros I call everything explicitly. I have included output from the logic analyzer and as you can see the only thing missing is the clock needed for the device to replay to the KEA-64. I have looked at ALL the code you have provided but NOTHING seems to be working, therefore postinhg more code will NOT help, rather please look at what I have done and let me know what is wrong.
Thanks
Hi Kas,
I checked your code with below error:
in main() function, when you want to change I2C module mode from write to read, the below code is incorrect:
I2C0_C1 &= !I2C_C1_TX_MASK;
The correct code is :
I2C0_C1 &= ~I2C_C1_TX_MASK;
And when you want to get the ADT7420 ID value, it need to read I2C0_D register twice, please refer below code:
i2c_give_nack(I2C0_B); //your code is I2C0_C1 |= I2C_C1_TXAK_MASK;
result = i2c_read_byte(I2C0_B); //your code is replay = I2C0_D;
i2c_wait(I2C0_B); //your code is while ((I2C0_S & I2C_S_IICIF_MASK) == 0){ //Wait for data to transmit }
i2c_stop(I2C0_B); //your code need to add as I2C0_C1 &= ~I2C_C1_MST_MASK; I2C0_C1 &= ~I2C_C1_TX_MASK;
result = i2c_read_byte(I2C0_B); //your code need to add as replay = I2C0_D;
Wish it helps.
best regards
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hello Ma,
From what I can see your code and my code is the same. Where you call a macro I use what is inside the macro. For example, i2c_wait(I2C_B) is exactly the same as while ((I2C0_S & I2C_S_IICIF_MASK) == 0){ //Wait for data to transmit } as this is defined in the header function, yet I am still having issues.
Can you please NOT use any macros an instead use the bare register in correcting what I have done wrong, because I still see nothing really different between what you and I have done.
Kas
Hi Kas,
I am also struck up in the same kind of problem.Please send me the I2C working code if you have finished it.
Hi Kas,
Your code with below error:
in main() function, when you want to change I2C module mode from write to read, the below code is incorrect:
I2C0_C1 &= !I2C_C1_TX_MASK;
The correct code is :
I2C0_C1 &= ~I2C_C1_TX_MASK;
And when you want to get the ADT7420 ID value, it need to read I2C0_D register twice.
Wish it helps.
best regards
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------