I2C module initialisation

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

I2C module initialisation

1,646件の閲覧回数
Psy_coder
Contributor II

The chip is MK10DN512VMC10. I'm trying to initialise the I2C module so that I can interface with accellerometer/gyroscope. I can't get to the point where I can configure the gyroscope. I'm failing to just see the SCL square waves on the oscilloscope. When I try to write to the I2C registers the system runs into hard fault.

here is my code

#define I2C_Frequency_Divider_register__I2C1_F (*(uint32_t *)0x40067001U)
#define I2C_Control_Register_1__I2C1_C1 (*(uint32_t *)0x40067002U)
#define I2C_Status_Register__I2C1_S (*(uint32_t *)0x40067003U)

#define Pin_Control_Register_n__PORTE_PCR0 (*(uint32_t *)0x4004D000U)
#define Pin_Control_Register_n__PORTE_PCR1 (*(uint32_t *)0x4004D004U)
#define System_Clock_Gating_Control_Register_4_SIM_SCGC4 (*(uint32_t *)0x40048034U)
#define System_Clock_Gating_Control_Register_5_SIM_SCGC5 (*(uint32_t *)0x40048038U)

 

void mcu_Initialise()
{

Pin_Control_Register_n__PORTE_PCR0 = 0x00000620U;
Pin_Control_Register_n__PORTE_PCR1 = 0x00000620U;

System_Clock_Gating_Control_Register_4_SIM_SCGC4 |= 0x00000080U;
System_Clock_Gating_Control_Register_5_SIM_SCGC5 |= 0x00002000U;

}

 

void intitialiseI2C()
{

I2C_Frequency_Divider_register__I2C0_F |= 0x29U; //writing to this register takes the system into hard fault

I2C_Control_Register_1__I2C1_C1 |= 0x80;

}

int main(void) {

BOARD_InitBootPins();
BOARD_InitBootClocks();
 mcu_Initialise();
intitialiseI2C();

}

0 件の賞賛
6 返答(返信)

1,482件の閲覧回数
Psy_coder
Contributor II

I have finally managed to get data out of my I2C module. Man I'm sure I wrote 10000 different codes just trying to read the WhoAmI register. After 3 months of suffering it turned out the problem was not in the code, it was a hardware issue. The module I'm trying to read has a reset pin. According to the datasheet this reset pin should be connected to ground if not used. So that's what I did the first time I started working with it, I soldered it to ground. I was giving up on this module. I just pulled out this reset wire without even desoldering it properly, and luckily I just decided to run the code just one more time before breaking the SDA and SCL line and throwing away the module and to my surprise I got an acknowledgement. Now I can start configuring the module. Thanks to everyone who took their time and participated in this thread, especially bobpadock

 

0 件の賞賛

1,573件の閲覧回数
Psy_coder
Contributor II

I have 3 weeks now failing to just get the WhoAmI value from the I2C module "FXOS8700 + FXAS21002"

What is wrong with my code, what am I missing?

The supply voltage to the I2C module is 5V. Before programming the mcu, Both the SCL and SDA lines measure 5 volts with reference to the ground. Then when I'm in debugg, with oscilloscope connected to the I2C bus, The voltage drops from 5V to 3.75V and stay there when I mux PortD in my code. Shouldn't i be seeing square waves on the scl line even with no data transfer between mcu and the module?

I get Arbitration lost in the status register.

What is wrong with my code?

Below is my code

Printing "ReceivedByte" array on tera term shows wrong WhoAmI value
uint8_t Receivedbyte[3];
uint8_t WhoAmI_address[1] = {0x0D};
size_t RegSize = 1;

void Mcu_Initialise()
{
PORTD->PCR[8] = 0x01000000; //clear the ISF flag
PORTD->PCR[9] = 0x01000000; //clear the ISF flag

PORTD->PCR[8] |= 0x00000200; //mux PTD8 for I2C0_SCL
PORTD->PCR[9] |= 0x00000200; //mux PTD9 for I2C0_SDA

SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK; // I2C0 clock
SIM->SCGC5 |= 0x00002000U; //portD

//I'm not sure about the following two lines
EnableIRQ(I2C0_IRQn);
NVIC_SetPriority(I2C0_IRQn,0);

}

void I2C_Initialise()
{
I2C0->A1 = 0;
I2C0->F = 0;
I2C0->C1 = 0;
I2C0->S = 0xFFU;
I2C0->C2 = 0;

I2C0->S |= I2C_S_IICIF_MASK ; //clear IICIF

I2C0->F = 0x27U; //bus clock is 48MHz, calculated baud rate for 100khz
I2C0->C1 = I2C_C1_IICEN_MASK;
//I2C0->C1 |= I2C_C1_IICIE_MASK; // When I enable this interrupt the system gets stuck in CLOCK_GetOutClkFreq() function. When I disable it I'm able to run my code from mcu_initialise() to Read()

void StartCondition()
{
I2C_MasterStart(I2C0, FXOS8700CQ_Address, kI2C_Write);
}

void StartRepeat()
{
I2C_MasterRepeatedStart(I2C0, FXOS8700CQ_Address, kI2C_Read);
}

void sendRegister()
{

I2C_MasterWriteBlocking(I2C0, WhoAmI_address, RegSize, kI2C_TransferNoStopFlag);
}
void Read()
{
I2C_MasterReadBlocking(I2C0,ReceivedByte, RegSize, kI2C_TransferNoStartFlag);
}
int main()
{
BOARD_InitPins();
__disable_irq();
InitVersion();
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();

mcu_Initialise();
intitialiseI2C();
StartCondition();
sendRegister();
StartRepeat();
Read();
}

0 件の賞賛

1,566件の閲覧回数
bobpaddock
Senior Contributor III

[Will someone PLEASE fix the form to not allow replies when not logged in!  Just lost a long one.]

Isn't there a bit in C1 that needs set to indicate this is the Master?  I don't have a datasheet at hand.

SCL is only toggling during a transfer, not all the time.

How is 5V involved in this?

SCL/SDA need set to open-drain/collector.
Some NXP parts are only pseudo-open ports, going above 3.6V could damage something in such parts, which is where your 3.7V comes from when the code starts.

Is the Accel/Gyro/whatever a 5V part? That would be rare.

 

1,634件の閲覧回数
bobpaddock
Senior Contributor III

Do you really want to be using OR (|=) rather than assignment (=) everyplace?

The hard fault indicates that the module clock is not running.

 

0 件の賞賛

1,614件の閲覧回数
Psy_coder
Contributor II

"Do you really want to be using OR (|=) rather than assignment (=) everyplace?"

I didn't think it could be the effect towards my problem because I thought it simply means I'm setting individual bits in a register without affecting the other bits, but I have removed the "|" as you suggested. The problem is still there though

"The hard fault indicates that the module clock is not running."

Do you mean the I2C module clock?... If that's the case, then it means my logic is flawed of thinking I'm enabling the clock with the line - 

System_Clock_Gating_Control_Register_4_SIM_SCGC4 = 0x00000080U;

0 件の賞賛

1,608件の閲覧回数
bobpaddock
Senior Contributor III

It is best to use the defines from the header file rather than magic numbers like 0x80:

SIM_SCGC4_I2C1_MASK

Yes, that would enable the clock for I2C1.

Look at the clock tree diagram for your part and see if anything else upstream in the clock tree also needs setup.

As to the |= issue, it usually makes no difference, other than a bit of wasted CPU time.
The critical place it can bite you is in clearing a bit in a status requester, with the 'Write-1-To-Clear' mechanism.  Give consideration to when to use (=) and when to use (|=).  NXP frequently uses |= in their examples, when they really shouldn't.

As example:


SIMs should use |= to prevent turning off other active clocks while turning on I2C clock.

I2C FRQ DIV should not use |= to be sure the register is as you want and it wasn't changed by something like a bootloader from the data sheet default value.