Ok, so I am trying to get IIC between MC9S08AW32 and MC9RS08KB4 using processor expert working. My SCL freq match exactly at 125 kHz but my SDA is a bit different (1.8 us on Master and 1.75 us on Slave) and perhaps this is an issue. I am trying to get the 7 analog values from the kb4 to the aw32. The data is coming over but not perfect. I get one or two values that seem to be correct but then I get some zeros OR very large numbers mixing inbetween the good data. I believe errors are happening while transmitting from slave (seems to be tx_buffer_full error) after a few successful transmission. Below is the I2C code related to Master and Slave. Please, if anyone can help me out on this one it would be much appreciated.
MASTER:
//if transmit complete
if (IICTxFlag == 0){
IICTxError = I2C1_SendBlock(&IICTxData, 2, &IICTxRet);
if (IICTxError != ERR_OK){
//handle error
}
while ((!IICTxFlag) && (I2C1_CheckBus() == I2C1_BUSY));
startRx = 1;
}
//start reception of data
if (startRx == 1){
for (IICLoop; IICLoop < 7; IICLoop++){
IICRxError = I2C1_RecvBlock(&IICRxData, 2, &IICRxRet);
if (IICRxError != ERR_OK){
//handle error
}
while((!IICRxFlag) && (I2C1_CheckBus() == I2C1_BUSY));
//if receive complete
adRemChannels[IICLoop] = (IICRxData[0] << 8) | IICRxData[1];
IICRxFlag = 0;
}
if (IICLoop >= 7){
IICLoop = 0;
IICTxFlag = 0;
startRx = 0;
solarV2Counts = adRemChannels[0];
solarV1Counts = adRemChannels[1];
windV3Counts = adRemChannels[2];
windV2Counts = adRemChannels[3];
windV1Counts = adRemChannels[4];
solarAmpsCounts = adRemChannels[5];
windAmpsCounts = adRemChannels[6];
}
}
SLAVE:
//receive data on full buffer
while (!IICRxFlag);
if ((IICRxFlag == 1) && (startTx == 0)){
IICRxError = I2C1_RecvBlock(&IICRxData, 2, &IICRxRet);
if (IICRxError != ERR_OK){
//handle error
}
while((!IICRxFlag) && (I2C1_CheckBus() == I2C1_BUSY));
//if message command good (MM), send data to master
if ((IICRxData[0] == 0x4D) && (IICRxData[1] == 0x4D)){
IICRxData[0] = 0;
IICRxData[1] = 0;
startTx = 1;
}
}
if (startTx == 1){
for (loop; loop < 7; loop++){
IICTxData[0] = (unsigned char)(adChannels[loop] >> 8);
IICTxData[1] = (unsigned char)adChannels[loop];
IICTxError = I2C1_SendBlock(&IICTxData, 2, &IICTxRet);
if (IICTxError != ERR_OK){
//handle error
}
while (((IICTxFlag & TX_EMPTY) == 0) && (I2C1_CheckBus() == I2C1_BUSY));
}
if (loop >= 7){
loop = 0;
startTx = 0;
IICRxFlag = 0;
}
}
Hi
I would clear the loop variable in Slave directly after checking of startTx
for (loop=0;loop<7;loop++) {...
to be sure about data alignment
Pavel
Ok, so I made loop = 0 before entering startTx on slave as you suggested. It helped but comm not totally ironed out. I get all the information coming back from my other micro, but something (error) is causing the info to get out of order (solarCounts will show windampCounts and the like). I am using PE on both master and slave. On slave, i have my input buffer at 2 and output buffer at 3 (per example via help component). On master, the length of buffer arrays are 2. Is this where my problem could be? Am I not making room for the empty character somewhere those causing sporadic transmission buffer full errors that then gets the comm out of order? I am pulling hairs now because code looks correct but functionality is not (very very very close though). Perhaps someone with experience can point me in the right direction.
Thanks
MASTER:
unsigned char IICTxFlag = 0;
unsigned char IICTxError = 0;
unsigned char IICTxData[2];
unsigned int IICTxRet = 0;
unsigned char IICRxFlag = 0;
unsigned char IICRxError = 0;
unsigned char IICRxData[2];
unsigned int IICRxRet = 0;
unsigned char startRx = 0;
unsigned int RxData;
.
.
.
//if transmit complete
if (IICTxFlag == 0){
IICTxError = I2C1_SendBlock(&IICTxData, 2, &IICTxRet);
if (IICTxError != ERR_OK){
//handle error
while (I2C1_CheckBus() == I2C1_BUSY);
IICTxFlag = 0;
}
else{
while ((!IICTxFlag) || (I2C1_CheckBus() == I2C1_BUSY));
IICLoop = 0;
startRx = 1;
}
}
//start reception of data
if (startRx == 1){
for (IICLoop; IICLoop < 7; IICLoop++){
IICRxError = I2C1_RecvBlock(&IICRxData, 2, &IICRxRet);
//below is needed
if (IICRxError != ERR_OK){
while (I2C1_CheckBus() == I2C1_BUSY);
IICRxFlag = 0;
break;
}
while ((!IICRxFlag) || (I2C1_CheckBus() == I2C1_BUSY));
//if receive complete
adRemChannels[IICLoop] = (IICRxData[0] << 8) | IICRxData[1];
IICRxFlag = 0;
}
if (IICLoop >= 7){
IICLoop = 0;
IICTxFlag = 0;
startRx = 0;
solarV2Counts = adRemChannels[0];
solarV1Counts = adRemChannels[1];
windV3Counts = adRemChannels[2];
windV2Counts = adRemChannels[3];
windV1Counts = adRemChannels[4];
solarAmpsCounts = adRemChannels[5];
windAmpsCounts = adRemChannels[6];
}
}
SLAVE:
#define | TX_CHAR | 1 | |
#define | BUFFER_FREE | 2 | |
#define | TX_EMPTY | 4 |
unsigned int adChannels[7] = { 0, 0, 0, 0, 0, 0, 0 };
unsigned char IICTxFlag = 0;
unsigned char IICRxFlag = 0;
unsigned char IICTxError = 0;
unsigned char IICRxError = 0;
unsigned char IICErrorFlag = 0;
unsigned char IICTxData[2];
unsigned char IICRxData[2];
unsigned int IICTxRet = 0;
unsigned int IICRxRet = 0;
unsigned char IICReadFlag = 0;
unsigned char IICWriteFlag = 0;
unsigned char startTx = 0;
unsigned char loop = 0;
void main(void)
{
/* Write your local variable definition here */
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. | ***/ |
IICRxData[0] = 0;
IICRxData[1] = 0;
IICTxData[0] = 0;
IICTxData[1] = 0;
/* Write your code here */
(void)AD1_Measure(1);
(void)AD1_GetValue(adChannels);
I2C1_ClearRxBuf();
I2C1_ClearTxBuf();
/* For example: for(;;) { } */
for(;;){
//receive data on full buffer
while (!IICRxFlag);
if ((IICRxFlag == 1) && (startTx == 0)){
IICRxError = I2C1_RecvBlock(&IICRxData, 2, &IICRxRet); | |||
if (IICRxError != ERR_OK){ | |||
//handle error | |||
while(I2C1_CheckBus() == I2C1_BUSY); | |||
IICRxFlag = 0; | |||
(void)I2C1_ClearRxBuf(); | |||
(void)I2C1_ClearTxBuf(); | |||
} | |||
else{ | |||
while((!IICRxFlag) || (I2C1_CheckBus() == I2C1_BUSY)); | |||
//if message command good (MM), send data to master | |||
if ((IICRxData[0] == 0x4D) && (IICRxData[1] == 0x4D)){ | |||
(void)I2C1_ClearRxBuf(); | |||
IICRxData[0] = 0; | |||
IICRxData[1] = 0; | |||
startTx = 1; | |||
loop = 0; | |||
} | |||
} |
}
if (startTx == 1){
for (loop; loop < 7; loop++){ | |||
IICTxData[0] = adChannels[loop] >> 8; | |||
IICTxData[1] = (unsigned char)(adChannels[loop]); | |||
IICTxFlag = 0; | |||
IICTxError = I2C1_SendBlock(&IICTxData, 2, &IICTxRet); | |||
if (IICTxError != ERR_OK){ | |||
//handle error | |||
while (I2C1_CheckBus() == I2C1_BUSY); | |||
(void)I2C1_ClearTxBuf(); | |||
break; | |||
} | |||
//while ((IICTxFlag & TX_EMPTY) == 0); | |||
//while (((IICTxFlag & TX_EMPTY) == 0) || (I2C1_CheckBus() == I2C1_BUSY)); | |||
while (I2C1_CheckBus() == I2C1_BUSY); | |||
} | |||
if (loop >= 7){ | |||
loop = 0; | |||
startTx = 0; | |||
IICRxFlag = 0; | |||
} |
}
}
Also, the slave code below never seems to set my IICTxFlag. I followed example on help component and via interrupts, IICTxFlag |= TX_EMPTY, TX_CHAR, and BUFFER_FREE. If I use the commented out code "while ((IICTxFlag & TX_EMPTY) == 0);" after send block command, i never make it past the statement in code as if that flag is never setting. I dont know how this is possible. I altered that specific statement for each state of IICTxFlag and none of them made it past that line of code.
if (startTx == 1){
for (loop; loop < 7; loop++){
IICTxData[0] = adChannels[loop] >> 8;
IICTxData[1] = (unsigned char)(adChannels[loop]);
IICTxFlag = 0;
IICTxError = I2C1_SendBlock(&IICTxData, 2, &IICTxRet);
if (IICTxError != ERR_OK){
//handle error
while (I2C1_CheckBus() == I2C1_BUSY);
(void)I2C1_ClearTxBuf();
break;
}
//while ((IICTxFlag & TX_EMPTY) == 0);
//while (((IICTxFlag & TX_EMPTY) == 0) || (I2C1_CheckBus() == I2C1_BUSY));
while (I2C1_CheckBus() == I2C1_BUSY);
}
if (loop >= 7){
loop = 0;
startTx = 0;
IICRxFlag = 0;
}
}