Цитата(dfyz.s @ Feb 6 2013, 06:40)

Большое спасибо за подробное описание!
На Ваш вопрос мне в личку я не могу отправить ответ в личку Вам, т.к. мне идет сообщение, что личка у Вас или отключена, или переполнена. Что бум делать?
А пока сюда. Извините, если много букав.
1. Функция Init_I2C() должна быть вызвана на этапе инициализации программы. Если предполагается работа с I2C1, то port равен 0, если работа с I2C2, то port равен 1, а если нужно будет общаться в проекте по двум шинам, надо вызвать Init_I2C() два раза:
Init_I2C(0, 0);
Init_I2C(1, 0);
Если второй параметр равен 0, будет установлена скорость I2C в 400kHz.
Далее, при необходимости произвести обмен по I2C1 или I2C2, нужно вызывать функции, указав им номер порта для обмена.
Например:
Чтение 10-ти байт с устройства I2C с адресом 0x58 на шине I2C2 (port = 1) простейшей функцией ReadW_I2C выглядит так:
Код
{
unsigned char buffer[1+10] = {0x58};
int result;
result = ReadW_I2C(1, buffer, 0, 10); // 0 bytes to write to before, 10 bytes to read
if (result == 10)
{
// full success, all bytes read,
// the received data are in buffer[1] to buffer[10]
memcpy(myglobalbuffer, &buffer[1], result); // copy the received bytes to some global buffer
} else {
// some error occurred: the result contains an error code if < 0 or
// maybe less than 10 bytes has been read if result >= 0 and < 10.
// make a decision what to do...
}
}
Другой пример чтения 16-ти байт из I2C EEPROM размером до 64KB с адреса 0xAABB в этой памяти, и пусть EEPROM сидит на I2C1 (port = 0). Сама EEPROM имеет адрес 0xA0 на шине.
Код
{
unsigned char buffer[1+2+16] = {0xA0}; // one byte for the I2C ID, 2 bytes for memory address, 16 bytes for data.
int result;
buffer[1] = 0xAABB / 256; // MSB goes first!
buffer[2] = 0xAABB % 256; // LSB
result = ReadW_I2C(0, buffer, 2, 16); // 2 bytes of memory address to write to before, 16 bytes to read afterwards
if (result == 16)
{
// full success, all bytes read,
// the received data are in buffer[3] to buffer[18]
memcpy(myglobalbuffer, &buffer[3], result); // copy the received bytes to some global buffer
} else {
// some error occurred: the result contains an error code if < 0 or
// maybe less than 16 bytes has been read if result >= 0 and < 16.
// make a decision what to do...
}
}
Следует помнить, что функция ReadW_I2C() - блокирующая, то есть не возвращает управление, пока не проделает всю работу. Если устройство "затянет" шину (а такое бывает), все повиснет. Чтобы такое не случилось, следует использовать, например, ReadC_I2C(), которая будет вызывать call back, пока крутится в цикле ожидания. Таким образом, можно в этом call back анализировать время работы и оборвать процесс, если он затянулся. См. комментарии к ReadC_I2C() в коде.
2. О конструкции control[port].rcc и функции RCC_Configuration() заморачиваться пока не нужно. Это моя функция, которая обрабатывает поле структуры control для указанного порта (то есть, для I2C1 или I2C2) с целью включить тактирование периферии, связанной с I2C1 или I2C2. Кстати, коль Вы упомянули, что недавно программируете этот процессор, укажу в этой связи на типичное недопонимание сути его работы (как следует из вопросов на форуме): прежде, чем начать работать с тем или иным периферийным устройством - I2C, USART и т.п. - необходимо сначало включить ему тактирование через узел RCC. Вот этим и занимается RCC_Configuration(), а структура control содержить всякие адреса, флаги и прочие вещи, необходимые для тех или иных операций с I2C. Короче, обо всем "позабочено", см. пункт 1). ответа.
Успехов.