Hi. I'm trying to write a program that will be transmitting one byte of data from the accelerometer via UART. Unfortunately this not working. By UART all the time is sent a value of "3A", an address "slave" accelerometer.
Up - UART terminal
I2C I initiated with the file header h, using KDS 2.0.
Program:
for(;;){
unsigned char Kp;
I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
I2C0_C1 = I2C0_C1 | (1 << 5);//start
I2C0_D=0x3A;//slave adress of accelerometer - Write
while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer
I2C0_D=0x01;//Sending accelerometer register adress
while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer
I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart
I2C0_D=0x3B;//slave adress of accelerometer - Read
while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer
I2C0_C1 = I2C0_C1 & ~(1 << 4);//clear TX
I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK
Kp=I2C0_D;//receive data from I2C
I2C0_C1 = I2C0_C1 & ~(1 << 5);//set Stop
I2C0_C1 = I2C0_C1 & ~(1 << 7);//Disable I2C
Transmisja(Kp);//Transmit byte value via UART
}
Please help.
EDIT. When I changed the program (i add "while ( !(I2C0_S & (1<<7)) )"):
for(;;){
unsigned char Kp;
I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
I2C0_C1 = I2C0_C1 | (1 << 5);//start
I2C0_D=0x3A;//slave adress of accelerometer - Write
while ( !(I2C0_S & (1<<7)) );//Wait for end of trans.
while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer
I2C0_D=0x01;//Sending accelerometer register adress
while ( !(I2C0_S & (1<<7)) );//Wait for end of trans.
while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer
I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart
I2C0_D=0x3B;//slave adress of accelerometer - Read
while ( !(I2C0_S & (1<<7)) );//Wait for end of trans.
while ( !(I2C0_S & (1)) );//Wait for ACK from accelerometer
I2C0_C1 = I2C0_C1 & ~(1 << 4);//clear TX
I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK
Kp=I2C0_D;//receive data from I2C
I2C0_C1 = I2C0_C1 & ~(1 << 5);//set Stop
I2C0_C1 = I2C0_C1 & ~(1 << 7);//Disable I2C
Transmisja(Kp);//Transmit byte value via UART
}
Program send 00 once..and stop working
Hello wojciech22a:
There is a sample code package for KL25 (KL25_SC) which includes a simple driver for the on-board MMA8451 accelerometer so you don't have to write code from scratch. You can find it in the next product link, under "LAB and Test Software":
Freescale Freedom Development Platform for Ki|Freescale
KL25 is also fully supported with the KSDK platform. More info here: Software Development Kit for Kinetis MCUs|Freescale.
... and getting started guides here:
Writing my first KSDK1.2 Application in KDS3.0 - Hello World and Toggle LED with GPIO Interrupt
Line scan camera with KSDK [ADC + PIT + GPIO] <- The KSDK guide in this link is targeted for FRDM-KL25.
If you want to continue writing your own code, here is some feedback:
- Poll the I2C_S[IICIF] flag instead of I2C_S[TCF], even if not using interrupts. The IICIF is more reliable than the TCF flag. Remember to clear the IICIF flag after each byte transfer by writing 1 to it.
- Checking for I2C_S[RXAK] flag (acknowledge) in a loop is not useful. You should only check the flag after a transfer completes and then take action based on received ACK or NACK.
- At the last stage where you try to read from the accelerometer, you are not polling for the transfer completion and you send the stop signal right away. This should be the sequence:
1- Clear TX bit.
2- Set NACK.
3- I2C_D dummy read to start transfer (this generates the clocks in SCL line).
4- Wait/poll for transfer to complete (IICIF).
5- Send stop (MST = 0)
6- Set TX bit
7- Read I2C_D to get the valid received data.
Regards!,
Jorge Gonzalez
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thank Jorge for your help.
According to your instructions I changed the program on the following:
I2C0_C1 = I2C0_C1 | (1 << 7);//Enable I2C
for(;;){
unsigned char Kp;
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
I2C0_C1 = I2C0_C1 | (1 << 5);//Start
I2C0_D=0x3A;//Slave adress of MMA8451Q -write
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_D=0x0D;//sending adress of register "WHO AM I"
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 | (1 << 2);//Rstart
I2C0_D=0x3B;//Slave adress of MMA8451Q - read
while ( !(I2C0_S & (1<<1)) );//Waiting of end of transmission - IICIF
I2C0_S = I2C0_S | (1 << 1);//Set IICIF
I2C0_C1 = I2C0_C1 & ~(1 << 4);//RX mode
I2C0_C1 = I2C0_C1 | (1 << 3);//set NACK
// Kp=I2C0_D;
while (! (I2C0_S & (1<<1)) );//Wait for end of trans -receive - IICIF
I2C0_C1 = I2C0_C1 & ~(1 << 5);//STOP
I2C0_C1 = I2C0_C1 | (1 << 4);//TX mode
Kp=I2C0_D;//Receive data
Transmisja(Kp);//Transmit via uart
}
But this program is also not working. He is not sending anything via UART.Program is stopping on the one of the "while" loop
Hello,
Try with this conditonal statement:
while((I2C0_S & I2C_S_IICIF_MASK)==0);
Regards!
Jorge Gonzalez
Thank, but still do not working. I Also set IICE bit in C1 register, without any results. Futher part of configuration register:
Maybe the problem is that i using PTA1 and PTA2 pins on OpenSDA virtual COM connection. But i dont think so because this is another I / O port than PTE24 and PTA24 in which and using i2c interface. Or maybe other I2C settings:
The project has processor expert support. Why are writing to registers directly instead of using Processor Expert APIs?
You can use the provided methods (SendBlock, ReceiveBlock) to create your application. Also, do not enable interrupts if you plan to use polling method. Or the other way, enable the interrupts but do not poll the I2C flags, instead fill the interrupt service routine with the required code.
Actually, there is a good tutorial by colleague Erich Styger to use the on-board accelerometer of FRDM-KL25Z. Have a look to this link:
Tutorial: Accelerating the KL25Z Freedom Board | MCU on Eclipse
And also a custom component targeted specifically for the accelerometer:
Extended Driver for the MMA8451Q Accelerometer | MCU on Eclipse
Regards!
Jorge Gonzalez