2016-07-04 05:49 AM
Hi,
I am working on a project where I have got an STM32F407VG set up as an I2C slave. I'm able to receive incoming bytes correctly, and I'm able to send one byte without issue. However I need to be able to send multiple bytes to the mast, but I'm unable to do so. The I2C interface is initialised with:void init_i2c_slave()
{
I2C_InitTypeDef I2C_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* I2C configuration ---------------------------------------------------------*/
I2C_Config();
/* Initialize I2C peripheral */
/* I2C Init */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE;
I2C_InitStructure.I2C_OwnAddress1 = SLAVE_ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2Cx, &I2C_InitStructure);
// I2C1 interrupts
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
I2C_StretchClockCmd(I2Cx, ENABLE);
I2C_Cmd(I2Cx, ENABLE);
}
And I have the following to handle event interrupts:
//Clear ADDR by reading SR1, then SR2
void I2C_clear_ADDR()
{
I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR);
((void)(I2Cx->SR2));
}
//Clear STOPF by reading SR1, then writing CR1
void I2C_clear_STOPF()
{
I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF);
I2C_Cmd(I2Cx, ENABLE);
}
void I2C1_BUF_IRQHandler()
{
buf[0] = I2C_ReceiveData(I2C1);
I2C_ClearITPendingBit(I2Cx, I2C_IT_BUF);
}
void I2C1_EV_IRQHandler(void)
{
char num_msg = 0;
if(I2C_GetITStatus(I2Cx, I2C_IT_AF)) I2C_ClearITPendingBit(I2Cx, I2C_IT_AF);
switch (I2C_GetLastEvent(I2Cx))
{
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
I2C_clear_ADDR(I2Cx);
break;
case I2C_EVENT_SLAVE_BYTE_RECEIVED:
I2C_Regs[reg_idx++] = I2C_ReceiveData(I2Cx);
break;
case I2C_EVENT_SLAVE_STOP_DETECTED:
I2C_clear_STOPF(I2Cx);
break;
case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //EV1
I2C_clear_ADDR(I2C1);
//Decode command
switch (I2C_Regs[0])
{
case 0x03: // read gennum register previously selected
I2C_SendData(I2Cx, I2C_Regs[reg_idx++]);
break;
}
break;
case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3
I2C_SendData(I2Cx, I2C_Regs[reg_idx++]);
break;
case of transmission EV3_2
I2C_ClearITPendingBit(I2Cx, I2C_IT_AF);
break;
default:
break;
}
}
void I2C1_ER_IRQHandler(void)
{
//GPIO_SetBits(GPIOD, RED);
//Can't use nice switch statement, because no fxn available
if(I2C_GetITStatus(I2Cx, I2C_IT_SMBALERT)) {
} else if(I2C_GetITStatus(I2Cx, I2C_IT_TIMEOUT)) {
} else if(I2C_GetITStatus(I2Cx, I2C_IT_PECERR)) {
} else if(I2C_GetITStatus(I2Cx, I2C_IT_OVR)) {
//Overrun
//CLK stretch disabled and receiving
//DR has not been read, b4 next byte comes in
//effect: lose byte
//should:clear RxNE and transmitter should retransmit
//Underrun
//CLK stretch disabled and I2C transmitting
//haven't updated DR since new clock
//effect: same byte resent
//should: make sure discarded, and write next
} else if(I2C_GetITStatus(I2Cx, I2C_IT_AF)) {
//Detected NACK
//Transmitter must reset com
//Slave: lines released
//Master: Stop or repeated Start must must be generated
//Master = MSL bit
//Fixup
I2C_ClearITPendingBit(I2Cx, I2C_IT_AF);
} else if(I2C_GetITStatus(I2Cx, I2C_IT_ARLO)) {
//Arbitration Lost
//Goes to slave mode, but can't ack slave address in same transfer
//Can after repeat Start though
} else if(I2C_GetITStatus(I2Cx, I2C_IT_BERR)) {
//Bus Error
//In slave mode: data discarded, lines released, acts like restart
//In master mode: current transmission continues
}
}
I have spent a lot of time searching for an answer to this issue, and have studied the reference manual, but I can't see what I've missed in the I2C set up which means that I dodn't get the I2C_EVENT_SLAVE_BYTE_TRANSMITTED. I have watched the trace from master to slave on a logic analyser and can see the the transmitter is generating clocks, but the mcu is not sending anything.
Can someone please give me a hint as to what I've missed
Thank you
Andrew