Мне необходимо сделать slave устройство с интерфейсом I2C. Пытаюсь сделать прием/передачу через прерывание со стороны slave. Slave самодельный на основе МК stm32f103. В качестве master использую отладочную плату stm32f4discovery.
Передача сообщений Master -> Slave работает как надо, а вот Slave -> Master происходит со смещением в области данных, т.е. что я имею ввиду
Транзакция 1: Slave на запрос Master отправляет byte1 byte2 byte3 byte4 byte5 byte6 byte7 byte8
Транзакция 2: затем byte2 byte3 byte4 byte5 byte6 byte7 byte8 byte1
Транзакция 3: byte3 byte4 byte5 byte6 byte7 byte8 byte1 byte2
Транзакция 4: byte4 byte5 byte6 byte7 byte8 byte1 byte2 byte3
Транзакция 5: byte5 byte6 byte7 byte8 byte1 byte2 byte3 byte4
и т.д.
Решил прежде чем отправлять следующий по порядку байт от Slave к Master проверять бит BTF, но он не выставляется после отправки и прога зависает
Код для Slave
Инициализация I2C
CODE
void initI2C()
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIOB_InitSructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
GPIOB_InitSructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIOB_InitSructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIOB_InitSructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIOB_InitSructure);
I2C_ITConfig(I2C1, I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF, ENABLE);
I2C_Cmd(I2C1, ENABLE);
NVIC_EnableIRQ(I2C1_ER_IRQn);
NVIC_EnableIRQ(I2C1_EV_IRQn);
}
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIOB_InitSructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
GPIOB_InitSructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIOB_InitSructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIOB_InitSructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIOB_InitSructure);
I2C_ITConfig(I2C1, I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF, ENABLE);
I2C_Cmd(I2C1, ENABLE);
NVIC_EnableIRQ(I2C1_ER_IRQn);
NVIC_EnableIRQ(I2C1_EV_IRQn);
}
Как описано прерывание
CODE
void I2C1_EV_IRQHandler()
{
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) == SUCCESS)
{
I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR);
(void)(I2C1->SR2);
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_RECEIVED) == SUCCESS)
{
data_in[i] = I2C_ReceiveData(I2C1);
i++;
if(i == 8)
{
i = 0;
}
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_STOP_DETECTED) == SUCCESS)
{
I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF);
I2C_ClearFlag(I2C1, I2C_IT_STOPF);
I2C_Cmd(I2C1, ENABLE);
}
if(I2C_GetFlagStatus(I2C1, I2C_FLAG_TRA) == SET)
{
if(!(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_TRANSMITTED) == SUCCESS))
{
I2C_SendData(I2C1, data_out[j]);
//while(!(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF))); // в этом месте и зависает из за отсутствия BTF
j++;
if(j == 8)
{
j = 0;
}
}
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_ACK_FAILURE) == SUCCESS)
{
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF);
I2C_Cmd(I2C1, ENABLE);
}
}
{
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) == SUCCESS)
{
I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR);
(void)(I2C1->SR2);
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_RECEIVED) == SUCCESS)
{
data_in[i] = I2C_ReceiveData(I2C1);
i++;
if(i == 8)
{
i = 0;
}
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_STOP_DETECTED) == SUCCESS)
{
I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF);
I2C_ClearFlag(I2C1, I2C_IT_STOPF);
I2C_Cmd(I2C1, ENABLE);
}
if(I2C_GetFlagStatus(I2C1, I2C_FLAG_TRA) == SET)
{
if(!(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_TRANSMITTED) == SUCCESS))
{
I2C_SendData(I2C1, data_out[j]);
//while(!(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF))); // в этом месте и зависает из за отсутствия BTF
j++;
if(j == 8)
{
j = 0;
}
}
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_ACK_FAILURE) == SUCCESS)
{
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF);
I2C_Cmd(I2C1, ENABLE);
}
}
Для Master все описано следующим образом
CODE
int main(void){
init_i2c();
while(1)
{
// Передача
I2C_StartTransmission(I2C1, I2C_Direction_Transmitter, SLAVE_ADRESS);
I2C_SendData(I2C1, START_BYTE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 2);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 3);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 4);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 5);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 6);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, END_BYTE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
// Прием
I2C_StartTransmission(I2C1, I2C_Direction_Receiver, SLAVE_ADRESS);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[0] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[1] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[2] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[3] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[4] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF));
I2C_AcknowledgeConfig(I2C1, DISABLE);
dataI2C[5] = I2C_ReceiveData(I2C1);
I2C_GenerateSTOP(I2C1, ENABLE);
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[6] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);
dataI2C[7] = I2C_ReceiveData(I2C1);
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
}
void init_i2c()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x32;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
GPIOB_InitSructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIOB_InitSructure.GPIO_Mode = GPIO_Mode_AF;
GPIOB_InitSructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIOB_InitSructure.GPIO_OType = GPIO_OType_OD;
GPIOB_InitSructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIOB_InitSructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
I2C_Cmd(I2C1, ENABLE);
}
void I2C_StartTransmission(I2C_TypeDef* I2Cx, uint8_t transmissionDirection, uint8_t slaveAddress)
{
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2Cx, slaveAddress, transmissionDirection);
if(transmissionDirection== I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
if(transmissionDirection== I2C_Direction_Receiver)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
init_i2c();
while(1)
{
// Передача
I2C_StartTransmission(I2C1, I2C_Direction_Transmitter, SLAVE_ADRESS);
I2C_SendData(I2C1, START_BYTE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 2);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 3);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 4);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 5);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, 6);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, END_BYTE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
// Прием
I2C_StartTransmission(I2C1, I2C_Direction_Receiver, SLAVE_ADRESS);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[0] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[1] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[2] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[3] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[4] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF));
I2C_AcknowledgeConfig(I2C1, DISABLE);
dataI2C[5] = I2C_ReceiveData(I2C1);
I2C_GenerateSTOP(I2C1, ENABLE);
while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET);
dataI2C[6] = I2C_ReceiveData(I2C1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);
dataI2C[7] = I2C_ReceiveData(I2C1);
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
}
void init_i2c()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x32;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
GPIOB_InitSructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIOB_InitSructure.GPIO_Mode = GPIO_Mode_AF;
GPIOB_InitSructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIOB_InitSructure.GPIO_OType = GPIO_OType_OD;
GPIOB_InitSructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIOB_InitSructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
I2C_Cmd(I2C1, ENABLE);
}
void I2C_StartTransmission(I2C_TypeDef* I2Cx, uint8_t transmissionDirection, uint8_t slaveAddress)
{
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2Cx, slaveAddress, transmissionDirection);
if(transmissionDirection== I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
if(transmissionDirection== I2C_Direction_Receiver)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}