Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

XMC™ Forum Discussions

User14023
Level 1
Level 1
Hi

I'm new to xmc, actually just bought my xmc4700 relax kit 2 weeks ago. And since i was used to avr micros,
eveverythg has a register to it, i2c for example, i can set the interruption, the enable i2c and start comunicating.
But in xmc i cant even find the register to control(enable) i2c in datasheets, am i missing something?
I notice that people go with apps for almost everything, but before getting myself into that i would like to know how van i do it the 'raw way',
Does anyone knows how? Or is just trough apps now?

Cheers, Luis Pereira.
0 Likes
5 Replies
User13817
Level 3
Level 3
Hello Luis,

Sometimes datasheets are tricky or doesn't have enough information to program some peripheral by yourself. I've been using the following method:

- Add I2C (or any other) Dave APP.
- Build the code.
- Check the generated code so you can use it as an example and modify as you want.

Good luck! I've got some problems using I2C also but now is working. I'm using XMC1100.
0 Likes
User14023
Level 1
Level 1
Thanks!
Thats a good way to go around thats true! I have noticed quite an amount of people having trouble with i2c on xmc4700. Just in case...can you tell me the app you are using? Does it follow the same logic: Start I2c...send adress with R/W bit...send register adress with R/W bit..?
0 Likes
User13817
Level 3
Level 3
LuisPereira wrote:
Thanks!
Thats a good way to go around thats true! I have noticed quite an amount of people having trouble with i2c on xmc4700. Just in case...can you tell me the app you are using? Does it follow the same logic: Start I2c...send adress with R/W bit...send register adress with R/W bit..?


I'm using DAVE3. Following you can see the apps and the routine to write/read.

2872.attach

 status_t i2c_write(uint8_t address, uint8_t data[], uint8_t count)
{
/* data receive transmission currently in progress - wait until finished */
while(i2c_read_flag == 1);

I2C001_DataType i2c_data; // Data type to compose USIC I2C TDF code and I2C data in one 16 bit word to be written to the USIC FIFO

// Clear WTDF Flag TODO check if really needed
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_WTDF_Msk;

// Clear WTDF Flag and Flush Buffers TODO check if really needed
I2C001_Handle0.I2CRegs->FMR |= (((uint32_t) 2) << USIC_CH_FMR_MTDV_Pos) & USIC_CH_FMR_MTDV_Msk;
USIC_FlushTxFIFO(I2C001_Handle0.I2CRegs);
USIC_FlushRxFIFO(I2C001_Handle0.I2CRegs);

// Clear ACK, NACK and PCR (Stop Condition) Flag for ACK, NACK, Stop Detection
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_ACK_Msk;
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_NACK_Msk;
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_PCR_Msk;

// Transmission start condition, I2C WRITE condition and slave address
i2c_data.Data1.TDF_Type = I2C_TDF_MStart;
i2c_data.Data1.Data = (address | I2C_WRITE); // address of the i2c device
while(!I2C001_WriteData(&I2C001_Handle0,&i2c_data));

// Wait for ACK or NACK from slave to detect presence of slave with given address
while(!((I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_IICMode_ACK_Msk) || (I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_IICMode_NACK_Msk)));
if(I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_IICMode_NACK_Msk)
return 0;

// Write data bytes
for(uint8_t i = 0; i < count; i++)
{
i2c_data.Data1.TDF_Type = I2C_TDF_MTxData;
i2c_data.Data1.Data = data; // address to write the data to
while(!I2C001_WriteData(&I2C001_Handle0,&i2c_data));
}

// Clear ACK Flag for last frame ACK detection
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_ACK_Msk;

// Stop condition by the master
i2c_data.Data1.TDF_Type = I2C_TDF_MStop;
i2c_data.Data1.Data = ubyteFF; //dummydata
while(!I2C001_WriteData(&I2C001_Handle0,&i2c_data));

//Wait until Transmit Buffer is empty
while(!(I2C001_Handle0.I2CRegs->TRBSR & USIC_CH_TRBSR_TEMPTY_Msk));

//wait until last frame ACK is received
while(!(I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_IICMode_ACK_Msk));

//wait until stop condition detected
while(!(I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_ST4_Msk));

return 1;
}


/*
* @brief Reads a number of data bytes from the addressed slave
* If NACK is detected 0 will be returned otherwise 1 will be returned
**/
status_t i2c_read(uint8_t address, uint8_t data[], uint8_t count)
{

rxData = data;

// Configure message data length
I2C001_DataType i2cdata; // Data type to compose USIC I2C TDF code and I2C data in one 16 bit word to be written to the USIC FIFO

// Set FIFO Trigger Limit to expected number of bytes
i2c_setRxFifoTriggerLimit(count);

// Clear WTDF Flag TODO check if really needed
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_WTDF_Msk;

// Clear WTDF Flag and Flush Buffers TODO check if really needed
I2C001_Handle0.I2CRegs->FMR |= (((uint32_t) 2) << USIC_CH_FMR_MTDV_Pos) & USIC_CH_FMR_MTDV_Msk;
USIC_FlushTxFIFO(I2C001_Handle0.I2CRegs);
USIC_FlushRxFIFO(I2C001_Handle0.I2CRegs);

// Clear ACK and NACK Flag for ACK/NACK Detection
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_ACK_Msk;
I2C001_Handle0.I2CRegs->PSCR |= USIC_CH_PSR_IICMode_NACK_Msk;

// Transmission start condition, I2C READ condition and slave address
i2cdata.Data1.TDF_Type = I2C_TDF_MStart;
i2cdata.Data1.Data = address | I2C_READ;
while(!I2C001_WriteData(&I2C001_Handle0,&i2cdata));

// Wait for ACK or NACK from slave to detect presence of slave with given address
while(!((I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_IICMode_ACK_Msk) || (I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_IICMode_NACK_Msk)));
if(I2C001_Handle0.I2CRegs->PSR_IICMode & USIC_CH_PSR_IICMode_NACK_Msk)
return 0;


// Read data from slave
i2c_read_flag = 1;
i2cdata.Data1.TDF_Type = I2C_TDF_MRxAck0;
i2cdata.Data1.Data = ubyteFF;

for(uint8_t bytecount=0; bytecount < count; bytecount++)
{
while(!I2C001_WriteData(&I2C001_Handle0,&i2cdata));
}

// Stop condition by the master
i2cdata.Data1.TDF_Type = I2C_TDF_MStop;
i2cdata.Data1.Data = ubyteFF;
while(!I2C001_WriteData(&I2C001_Handle0,&i2cdata));

// wait until data is finally received
while(i2c_read_flag == 1);

return 1;
}


Hope this helps you 🙂
0 Likes
User14023
Level 1
Level 1
That is great, thanks! 🙂
0 Likes
User14023
Level 1
Level 1
Thinking again...i'm going to start slowlyyyyy...at this momento the whole app thing is getting me confused...to much i don't know about its work.
Sooo...i build up the tiniest example using I2C_Master app. The intentio is to use the reading from an x-axis register (from the mpu-9250 accelerometer) and place that reading as the duty cycle of a PWM.
The byte reading is actually a 0 to 255 reading and not the 0 to 100 that the duty ccle would need but it would do the trick for now. Since theres so much i dont know if i HAVE to do, specially in comparison with my AVR codes
so here it goes...

#include //Declarations from DAVE Code Generation (includes SFR declaration)

#define IO_EXPANDER_ADDRESS 0xB0 //The adress for MPU9250 - 0b1101 000X
#define ACCEL_XOUT_H 0x3B //Adress for the x-axis reading register in the MPU9250

/* Transmit callback handling variables */
volatile uint8_t tx_completion_0 = 0;
volatile uint8_t rx_completion_0 = 0;


/* Transmit callback handling function */
void tx_callback_0(void)
{
tx_completion_0 = 1;
}

/* Receive callback handling function*/
void rx_callback_0(void)
{
rx_completion_0 = 1;
}


int main(void)
{
DAVE_STATUS_t status;
status = DAVE_Init(); /* Initialization of DAVE APPs */
if(status != DAVE_STATUS_SUCCESS)
{/* Placeholder for error handler code. The while loop below can be replaced with an user error handler. */
XMC_DEBUG("DAVE APPs initialization failed\n");
while(1U){}
}

uint8_t received_data;


/* Wake up MPU9250 - Putting zeros in 0x6B.*/
I2C_MASTER_Transmit(&I2C_MASTER_0,true,IO_EXPANDER_ADDRESS,0,2,false);
while(tx_completion_0 == 0);
tx_completion_0 = 0;

while(1U)
{
/*Read the register of x-axis from accelerometer and place it in received_data.*/
I2C_MASTER_Receive(&I2C_MASTER_0,true,ACCEL_XOUT_H,&received_data,1,true,true);
while(rx_completion_0 == 0);
rx_completion_0 = 0;

//Sets the Duty cycle of PWM_0_PIN1_1 with the value of the received reading in x-axis.
PWM_SetDutyCycle(&PWM_0_PIN1_1,received_data);
}
}
0 Likes