gemeni 0 13 июля, 2016 Опубликовано 13 июля, 2016 (изменено) · Жалоба Здравствуйте! Мне необходимо сделать 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 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); } Как описано прерывание 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); } } Для Master все описано следующим образом 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)); } } Изменено 13 июля, 2016 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться