I am trying to get the I2C module working on the KEA but I am having no luck with this. I can see using a logic that the SCL line goes high before the SDA line and at the end the SDA goes low before the SCL, but there is no data being transmitted. Below is the code that I am using, any help would be very much appreciated.
Thankfully
Kas
Sorry I tried to insert the code in code format but the insert function completely screwed up everything so I had to do it without
/****************************************************************************** | ||||||||||||||||||
* LAB1 - Serial Communications Interface (UART) * | ||||||||||||||||||
* * | ||||||||||||||||||
* This lab demonstrates how to use the UART module to receive and send * | ||||||||||||||||||
* characters. Using interrupts, it waits for characters sent from a PC * | ||||||||||||||||||
* terminal and echoes the received data. | * | |||||||||||||||||
* | * |
* To use this demo you need to open a serial terminal. The OpenSDA port *
* is used to communicate via UART2 to the KEA64 microcontroller. * | ||||||||
* * | ||||||||
* Open the Terminal Utility and set the baud rate to 9600, leave all * | ||||||||
* the other settings with the default values. Click the Open Port button * | ||||||||
* and the console should connect. Every character you write to the serial * | ||||||||
* console will be replied by the KEA64 MCU. * | ||||||||
******************************************************************************/ |
/**********************************************************************************************
* External objects
**********************************************************************************************/
#include "derivative.h" /* include peripheral declarations */
#include "UART.h"
#include "CLK.h"
#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
/**********************************************************************************************
* Global variables
**********************************************************************************************/
unsigned char MasterTransmission;
/**********************************************************************************************
* Constants and macros
**********************************************************************************************/
/**********************************************************************************************
* Local types
**********************************************************************************************/
/**********************************************************************************************
* Local function prototypes
*********************************************************************************************/
void Enable_Interrupt(UINT8 vector_number);
void Uart_Interrupt (UINT8 data);
void i2cInit();
void Pause(void);
void writeRegister(unsigned char slaveID, unsigned char registerAddress, unsigned char data);
unsigned char readRegister(unsigned char slaveID, unsigned char registerAddress);
/**********************************************************************************************
* Local variables
**********************************************************************************************/
/**********************************************************************************************
* Local functions
**********************************************************************************************/
/**********************************************************************************************
* Global functions
**********************************************************************************************/
/***********************************************************************************************
*
* @brief main() - Program entry function
* @param none
* @return none
*
************************************************************************************************/
int main(void)
{
UINT32 counter = 0; | |||||||
long int delay; | |||||||
Clk_Init(); | /* Configure clocks to run at 20 Mhz*/ | ||||||
UART_Init(); | /*Initialize Uart 2 at 9600 bauds */ | ||||||
i2cInit(); | |||||||
Uart_SetCallback(Uart_Interrupt); | /* Set the callback function that the UART driver will call when receiving a char */ | ||||||
Enable_Interrupt(INT_UART2); | /* Enable UART2 interrupt */ |
for(;;) { | ||
counter++; | ||
readRegister(0x4B, 0x0B); | ||
for(delay = 0; delay < 999999; delay++); | ||
} | ||
return 0; |
}
/***********************************************************************************************
*
* @brief Uart_Interrupt(UINT8 data). Serial reception callback. This function is called each time a character
* | is received on the serial port. |
* @param data received from serial port
* @return none
*
************************************************************************************************/
void Uart_Interrupt (UINT8 data)
{
Uart_SendChar(data); /* Echos data that is received*/ |
}
/***********************************************************************************************
*
* @brief Enable_Interrupt(UINT8 vector_number). Enable interrupts from desired module.
* @param Module interrupt number from the interrupts vector table
* @return none
*
************************************************************************************************/
void Enable_Interrupt(UINT8 vector_number)
{
vector_number= vector_number-16; |
/* Set the ICPR and ISER registers accordingly */ | |
NVIC_ICPR |= 1 << (vector_number%32); | |
NVIC_ISER |= 1 << (vector_number%32); |
}
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;
}
/*******************************************************************/
/*!
* Pause Routine
*/
void Pause(void){
int n;
for(n=1;n<50;n++) {
asm("nop");
}
}
unsigned char readRegister(unsigned char slaveID, unsigned char registerAddress)
{
unsigned char result; | |
unsigned int j; | |
MasterTransmission = MRSW; | |
slaveID = slaveID << 1; | |
slaveID |= MasterTransmission; | |
i2c_Start(); | |
i2c_write_byte(slaveID); | |
i2c_Wait(); | |
I2C0_D = registerAddress; | |
i2c_Wait(); | |
/* Do a repeated start */ | |
I2C0_C1 |= I2C_C1_RSTA_MASK; | |
/* Send Slave Address */ | |
I2C0_D = (slaveID << 1) | 0x01; //read address | |
i2c_Wait(); | |
/* Put in Rx Mode */ | |
I2C0_C1 &= (~I2C_C1_TX_MASK); | |
/* Turn off ACK */ | |
I2C0_C1 |= I2C_C1_TXAK_MASK; | |
/* Dummy read */ | |
result = I2C0_D ; | |
for (j=0; j<5000; j++){}; | |
i2c_Wait(); | |
/* Send stop */ | |
i2c_Stop(); | |
result = I2C0_D ; | |
Pause(); | |
return result; |
}
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(); |
}
Hi Kas,
There is I2C sample code available for KEXX serials, please kindly refer to http://cache.freescale.com/files/software_development_tools/snippets/KEXX_I2C_SC.zip for details, which work together with ke_drv_lib to implement read or write data by I2C interface. which include the master and slave sample code.
Hope that helps,
Have a great day,
Kan
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hello Kan,
Are there any simple, barebones examples. I am looking to something very simple. I do not want to use drivers, macros and anything else. I am looking for a simple example to get the I2C working correctly and where I can see EXACTLY what registers are being used. It appears whenever I ask for help here I get more examples and demo code that is using bloated code. I am looking preferably for someone to look at the SMALL code snippet I have provided and point out what is wrong not give me 20 more examples from other Kinetis controllers and that use 3 or 4 files. KISS = KEEP IT SIMPLE...
Thank you
Hi Kas,
I found myself today in the same situation.
For any other programmer who will face the same issue in the future, here is the code i used to sucessfully write over i2c:
error_t i2c_set_dac(i2c_data_t address_byte, i2c_data_t low_byte, i2c_data_t high_byte)
{
error_t error = ERROR_SUCCESS;
i2c_data_t first_byte = 0;
// generate start condition
I2C0_C1 |= I2C_C1_MST_MASK;
// LSB is not write flag
first_byte = address_byte << 1;
// push data to send
I2C0_D = first_byte;
// wait until sent
while((I2C0_S & I2C_S_IICIF_MASK)==0);
// delete interrupt flag
I2C0_S &= I2C_S_IICIF_MASK;
// check for ack
if( (I2C0_S & I2C_S_RXAK_MASK)!= 0 ){
error |= ERROR_FAILED;
}
// push data to send
I2C0_D = high_byte;
// wait until sent
while((I2C0_S & I2C_S_IICIF_MASK)==0);
// delete interrupt flag
I2C0_S &= I2C_S_IICIF_MASK;
// check for ack
if( (I2C0_S & I2C_S_RXAK_MASK)!= 0 ){
error |= ERROR_FAILED;
}
// push data to send
I2C0_D = low_byte;
// wait until sent
while((I2C0_S & I2C_S_IICIF_MASK)==0);
// delete interrupt flag
I2C0_S &= I2C_S_IICIF_MASK;
// check for ack
if( (I2C0_S & I2C_S_RXAK_MASK)!= 0 ){
error |= ERROR_FAILED;
}
// generate stop condition
I2C0_C1 &= ~I2C_C1_MST_MASK;
return error;
}
Best regards,
Roger