2009-12-29 06:01 PM
I2C on STM8S105
2011-05-17 06:06 AM
Dear all,
I'm trying to use the I2C device on my STM8S105. On this MCU I2C is implemented as alternative function. I've set the AF6 flag for I2C so that it should work. But when I send the start flag, the control of “I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT)� fails and the program hangs. On the oscilloscope I can see that SDA is pulled down to low level, so only the flags are not set by hardware. The same code works fine on STM8S208 and STM8S103. On this MCUs I2C can be used directly. Are there any other settings needed for using alternative functions? Best regards!2011-05-17 06:06 AM
Hi,We also found sometime STM8S105 will not sent ACK when it received an address. IIC bus will be hold
2011-05-17 06:06 AM
Please let us know if someone is aware of the solution
Mat
2011-05-17 06:06 AM
Hi
This is a code segment that controls an external I2C multiplexer on my hardawre. It works and seems reliable, it may help you.
There may be some minor differences in the library functions as the target is an stm8L151.
BYTE ee_SelectI2CMuxChannel(BYTE bChannel)
{
BYTE bI2CMuxAddr = I2CMUXADDR,bSelByte=0;
WORD wSelMuxErrorPollLoop;
// Selects the I2C channel using the PCA9540 I2C multiplexer
wSelMuxErrorPollLoop=I2CMUX_ERROR_TIMEOUT;
/* While the bus is busy */
do
{
WDG_RESET;
}
while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY) && (--wSelMuxErrorPollLoop) );
if(wSelMuxErrorPollLoop == 0 ) return 0; // Timeout - bus busy
I2C_GenerateSTART(I2C1,ENABLE); // Send start
wSelMuxErrorPollLoop=I2CMUX_ERROR_TIMEOUT;
while ((!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) && --wSelMuxErrorPollLoop) ;
if(wSelMuxErrorPollLoop == 0) return 0;
// Send and wait for address to be transmitted
I2C_Send7bitAddress(I2C1,I2CMUXADDR, I2C_Direction_Transmitter);
wSelMuxErrorPollLoop=I2CMUX_ERROR_TIMEOUT;
while((!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))&&(--wSelMuxErrorPollLoop));
// Check correct ack and possible timeout condition
if ((I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) != 0x00) || (wSelMuxErrorPollLoop == 0))
{
return 0;
}
// Decide on which bank of devices
if(bChannel == 1) bSelByte = I2CMUX_SEL_CH1; else bSelByte = I2CMUX_SEL_CH0;
// Send and wait for address to be transmitted
I2C_SendData(I2C1,bSelByte);
wSelMuxErrorPollLoop=I2CMUX_ERROR_TIMEOUT;
while ((!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))&&(--wSelMuxErrorPollLoop));
// Check correct ack ( AF = ACK FAIL FLAG ) and possible timeout condition
if ((I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) != 0x00) || (wSelMuxErrorPollLoop == 0))
{
return 0;
}
// Generate stop
I2C_GenerateSTOP(I2C1,ENABLE);
return 1;
}
2011-05-17 06:06 AM
Hi Patrick;
After sending the address I2CMUXADDR you don't need to wait on the I2C_FLAG_AF, this check should be removedif ((I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) != 0x00) || (wSelMuxErrorPollLoop == 0))
{
return 0;
}
What is the frequency (Fcpu) used in your application and what is the timout value(I2CMUX_ERROR_TIMEOUT)? Regards mozra2011-05-17 06:06 AM
Hi Mozra
The Pollloop is a failsafe, its value is unimportant. Under normal circumstances the polling will end quickly. But if a straight while loop is used, if something goes wrong execution will hang . At least if the function returns an error the error can be tracked down more easily.