А ещё такой вопрос, не касающийся CPAL: может ли быть такое что используя стандартную библиотеку STM в режиме Мастер не отпускает линию что бы принять ACK от слэйва после отправки адреса устройства? Просто некоторое время slave нормально отвечал, затем я немного решил порефакторить код и всё сломалось. Вернул на место, всё равно ничего не работает. Смотрю по осцилограмме - слэйв не отправляет ACK. Хотя в его работе вообще ничего меняться не должно было. Выкладываю код:
Инициализация:
CODE
//Инициализация GPIO
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
// SCL пин
GPIO_InitStruct.GPIO_Pin = I2C1_SCL_PIN;
GPIO_Init(I2C1_SCL_PORT, &GPIO_InitStruct);
GPIO_PinAFConfig(I2C1_SCL_PORT, I2C1_SCL_PIN_SOURCE, GPIO_AF_I2C1);
// SDA пин
GPIO_InitStruct.GPIO_Pin = I2C1_SDA_PIN;
GPIO_Init(I2C1_SDA_PORT, &GPIO_InitStruct);
GPIO_PinAFConfig(I2C1_SDA_PORT, I2C1_SDA_PIN_SOURCE, GPIO_AF_I2C1);
// Конфигурация I2C
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_Cmd(I2C1, DISABLE);
I2C_DeInit(I2C1);
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = I2C1_OWN_ADDRESS;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED;
I2C_Init(I2C1, &I2C_InitStruct);
// Включение интерфейса
I2C_Cmd(I2C1, ENABLE);
чтение регистра
CODE
// Проверка готовности линии
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// Генерация первого старта
I2C_GenerateSTART(I2Cx, ENABLE);
// Проверка что линия свободна
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// Отправка адреса подчинённого устройства (запись)
I2C_Send7bitAddress(I2Cx, slaveAddress, I2C_Direction_Transmitter);
// Проверка ACK от подчинённого устройства (есть ли такой адрес на шине)
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// Отправка адреса регистра чтения
I2C_SendData(I2Cx, regAddress);
// Проверка ACK от подчинённого устройства
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Генерация повторного старта
I2C_GenerateSTART(I2Cx, ENABLE);
// Проверка что линия свободна
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// Отправка адреса подчинённого устройства (чтение)
I2C_Send7bitAddress(I2Cx, slaveAddress, I2C_Direction_Receiver);
// Проверка ACK от подчинённого устройства
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// Завершаем приём
I2C_AcknowledgeConfig(I2Cx, DISABLE);
// Проверка что байт принят (данные загружены в регистр DR)
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
// Генерируем стоп
I2C_GenerateSTOP(I2C1, ENABLE);
return I2C_ReceiveData(I2Cx);
И после первой отправки адреса устройства ACK я так и не дожидаюсь. Устройство STA381BWS.
Добавил к коду сдвиг адреса Slave'а на один бит влево. Ничего не изменилось.