Hello,
I have some problem to bring the I2C-Master to work.
My setup:
TivaLaunchpad (I2C-Master)
custom Board with MSP430Gx-Controller (I2C-Slave)
Debugging in CCS with full licence
I2C-pullup with around 4kOhm i think
I2c-clock at 100Kb/s
Below is the program. I will give a short description. The I2C-Master should send the address and 3 data bytes. When i run the program like it is i get the following picture at my oscilloscope:
Here you can see that the address will be sent out and the ACK is set correctly. But the next and only byte is the last one with 0x55. This should be the third byte. The data bytes one and two are missing. Why do this happen? I can´t explain that.
But i tried some more things and all things i have done confused me more and more. Here my other tries with pictures.
Try 1:
- set a breakpoint to the command data put (it´s the second byte)
- program run into the breakpoint and as you can see the address and the first data byte is sent out correctly
- let the program move on
- this is the second data byte and it looks fine
- after this the program will stick in the while loop for waiting of the clearance of the busy byte forever; just a reset helps
Try 2:
- add a 5000 cycle delay between first data byte and second data byte
- without a breakpoint this will stick in the busy-loop forever
Can anyone give me an explanation of that behavior? I think i have tried almost anything but haven´t found a solution. The slave works fine and make all acknowledges he should do. The program never runs into the error interrupt of the I2c.
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
uint8_t SLAVE_ADDRESS = 0x0F;
uint32_t first_byte, second_byte, temperature, result;
static volatile int iCtr=0;
void iicInt(){
iCtr++;
}
void i2c_setup(void) {
//SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
//Enable the I2C Module
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
//Wait at least 5 clock cycles
SysCtlDelay(2);
//Configure SDA and SCL
GPIOPinConfigure(0x00041003);
GPIOPinConfigure(0x00041403);
//Wait at least 5 clock cycles
SysCtlDelay(2);
//Set PE4 as SCL
GPIOPinTypeI2CSCL(GPIO_PORTE_BASE, GPIO_PIN_4);
//Set PE5 as SDA
GPIOPinTypeI2C(GPIO_PORTE_BASE, GPIO_PIN_5);
//Configure Master,
I2CMasterInitExpClk(I2C2_BASE, SysCtlClockGet(), false);
// interrupt
I2CIntRegister(I2C2_BASE, iicInt);
}
typedef struct {
unsigned char all;
union{
unsigned char r1 :1;
unsigned char r2 :1;
unsigned char r3 :1;
unsigned char r4 :1;
unsigned char r5 :1;
unsigned char r6 :1;
unsigned char r7 :1;
unsigned char r8 :1;
}single;
}rel_t;
uint32_t i2c_read() {
volatile rel_t iRelPos;
iRelPos.all = 0x55;
// address + dlc + crc
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, false);
I2CMasterDataPut(I2C2_BASE, 0x01);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_START);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
//SysCtlDelay(5000);
// command
I2CMasterDataPut(I2C2_BASE, 0x07);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
//SysCtlDelay(2000);
// state
I2CMasterDataPut(I2C2_BASE, iRelPos.all);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
/*
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, true );
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
first_byte = I2CMasterDataGet(I2C2_BASE);
*/
return first_byte;
}
void setup()
{
i2c_setup();
}
void main()
{
setup();
while(1)
{
int test = i2c_read();
SysCtlDelay(5000);
}
}
