Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обращение к I2C - устройству через /dev - интерфейс
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
kovigor
Добрый день !
Есть вот такая отладочная плата:
http://www.freescale.com/webapp/sps/site/p...p?code=IMX53QSB

В файле "~/ltib/rpm/BUILD/linux-2.6.35.3/Documentetion/i2c/dev-interface" написано, что можно работать с моим устройством, подключенным к i2c, через интерфейс "/dev":

"Usually, i2c devices are controlled by a kernel driver. But it is also possible to access all devices on an adapter from userspace, through the /dev interface." ...

Что я и делаю. Устройство - графический индикатор с адресом 0x70, заведомо исправный, освоенный и проверенный. Естественно, драйвера к нему нет, и, как я понял (см. цитату, приведенную выше), без него можно обойтись. Написал вот такую программку:

Код
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>

//Variables needed for I2C communications
int i2c_file;
int i2c_adapter_nr = 1;
//Indicator address: 0x70
//Content: "0" - "Control", "1" - "Data"
//Direction: "0" - "Write", "1" - "Read"
int i2c_addr = 0x70;
char i2c_filename[20];
char i2c_data_buffer[10]; //Buffer for reading/writing data

/*************************************************************/
//"Main" function
int main (int argc, char ** argv)
{
//I2C bus as file opening
snprintf(i2c_filename, 19, "/dev/i2c-%d", i2c_adapter_nr);
i2c_file = open(i2c_filename, O_RDWR);
if (i2c_file < 0){printf("I2C as file opening error ! Exiting ...\n%d", i2c_file);
                  return(1);
                 }
/*sleep(0.1);*/

//Indicator I2C-address transmitting
if (ioctl(i2c_file, I2C_SLAVE, 0x70 >> 1) < 0){
printf("device selecting error ! Exiting ...\n");
close(i2c_file);
return(1);
                                              }

//Writing a data byte to Indicator
i2c_data_buffer[0] = 0b11100010;
if (write(i2c_file, i2c_data_buffer, 1) != 1){
printf("Writing error ! Exiting ...\n");
close(i2c_file);
return(1);
                                             }

close(i2c_file);
printf("All OK !!!\n");
}


Происходит странная вещь - адрес появляется на шине, индикатор его подтверждает (судя по осциллограмме), но сам записываемый байт "0b11100010" на шину не выставляется - мастер шины (т.е., отладочная плата) его просто не отсылает. Вместо этого после отсылки младшего бита адреса при низком уровне на CLK индикатор выставляет бит подтверждения ("0" на линии "Data"; так и должно быть), затем плата взводит CLK в единичку и потом не сбрасывает его в ноль, но оставляет его в состоянии лог. "1" навсегда, а индикатор, видя такое поведение платы, удерживает линию "DATA" в нуле и не отпускает. Шина "залипает", и исправляется это только перезагрузкой.

Кто подскажет, в чем тут дело ?
xor.kruger
Для начала, чтобы убедится что ваше устройство работает 100 % нормально, "потыкайте" в него утилитами i2ctools, есть как в составе busybox так и buildroot.
kovigor
Цитата(xor.kruger @ Dec 26 2012, 14:27) *
Для начала, чтобы убедится что ваше устройство работает 100 % нормально, "потыкайте" в него утилитами i2ctools, есть как в составе busybox так и buildroot.

Индикатор рабочий - я вдоволь наигрался с ним, подключив к своей платке на AVR и освоив работу с ним на достаточном уровне. Все в полном соответствии с документацией, и осциллограммы - в том числе ...
P.S. Есть идея: проанализировать код ошибки, возвращаемый функцией "write". Сейчас я этим и займусь ...
xor.kruger
Стесняюсь спросить, а зачем вы делаете 0x70 >> 1 ?
kovigor
Цитата(xor.kruger @ Dec 26 2012, 15:23) *
Стесняюсь спросить, а зачем вы делаете 0x70 >> 1 ?

А иначе осциллограф показывает на шине не "0x70", а "0xe0" ...

P.S. "Write" возвращает код ошибки errno = 5 (I/O error)
xor.kruger
У меня когда-то была подобная проблема с подключением камеры от мобильного. Камера в системе зарегистрировалась под другим адресом, который не совпадал по даташиту.
Все таки попробуйте сделать
Код
i2cdetect <номер_шины>
Утилита покажет на каком точно адресе висит ваше устройство, а потом с помощью i2cdump снимите дамп с "задетекченого" адреса.
kovigor
Цитата(xor.kruger @ Dec 26 2012, 15:58) *
Код
i2cdetect <номер_шины>

Пробую ...
Сверхстранно !!!!! Запустил "i2cdetect". До адреса 0x70 осциллограф показывает на шине вполне корректные осциллограммы, но после обращения по адресу 0x70 индикатор захватывает шину, как я описал выше: "после отсылки младшего бита адреса при низком уровне на CLK индикатор выставляет бит подтверждения ("0" на линии "Data"; так и должно быть), затем плата взводит CLK в единичку и потом не сбрасывает его в ноль, но оставляет его в состоянии лог. "1" навсегда, а индикатор, видя такое поведение платы, удерживает линию "DATA" в нуле и не отпускает. Шина "залипает", и исправляется это только перезагрузкой.". Чудеса !!!!!!!
xor.kruger
Хм, да уж...
Попробуйте включить в ядре всю отладочную информацию по I2C - может ядро успеет что-нибудь вменяемое ответить перед тем как повиснет.
Также я бы попробовал включить в ядре GPIO I2C BUS (Опция в ядре - CONFIG_I2C_GPIO), выключил поддержку аппаратной шины и перевесить туда ваше устройство (естественно перед этим поправив файл-платформ). Может поведение будет другим.
Ну и еще момент... с подтяжками все нормально ? sm.gif
kovigor
Цитата(xor.kruger @ Dec 26 2012, 16:35) *
Ну и еще момент... с подтяжками все нормально ? sm.gif

Так вот и я о том же. Лог. уровень, которым индикатор выставляет подтверждения, весьма завышен - порядка 0.6В. Очень возможно, что дело в этом. Подтяжки по 4.7К смонтированы на отладочной плате ее заводом-изготовителем ...

А ядро ... Другие же устройства на шине работают ? Да. Так что едва ли дело в ядре. Похоже как раз на завышенный лог. 0 ...

P.S. Привел уровень в норму. Не помогло - дело не в уровне. Завтра попробую вместо индикатора подключить обычную Serial EEPROM, и посмотрю, что будет
Ruslan1
Цитата(kovigor @ Dec 26 2012, 14:04) *
Сверхстранно !!!!! Запустил "i2cdetect". До адреса 0x70 осциллограф показывает на шине вполне корректные осциллограммы, но после обращения по адресу 0x70 индикатор захватывает шину

Просто идея: А может на самой плате что-то по этому адресу висит? что этот icdetect находит, если без индикатора просканировать плату ?
Или может на другом адресе что-то висит, но дешифрация неполная и это "что-то" какой-то диапазон физических адресов занимает.
kovigor
Цитата(Ruslan1 @ Dec 26 2012, 23:09) *
Просто идея: А может на самой плате что-то по этому адресу висит? что этот icdetect находит, если без индикатора просканировать плату ?
Или может на другом адресе что-то висит, но дешифрация неполная и это "что-то" какой-то диапазон физических адресов занимает.

Спасибо. Сейчас буду вашу идею проверять, и кое-какие свои идеи ...

P.S. Вместо индикатора подключил к плате Serial EEPROM. В данном случае все работает, как следует. Продолжаю разбираться ...
Sergei_Ilchenko
Немного не в тему, а есть у кого переходник на HDMI в СПб?
kovigor
Проблема решилась. Причина ее чисто электротехническая: у индикатора слишком слабый передатчик, чтобы выставлять корректное подтверждение для i.MX53. Я сразу заметил, что все абоненты шины ведут себя, как полагается, и только индикатор выдает лог.0, равный не нулю вольт, а где-то 0.4 ... 0.6 вольт. Очевидно, это не нравилось i.MX53, и происходил сбой. Проблема решилась путем увеличения смонтированных на отладочной плате подтягивающих резисторов с 4.7К до 20К. Вот так.
Всем спасибо за помощь ...

P.S. Думал, индикатор неисправный, так нет же. Запаял другой точно такой же RDX0048, и увидел тот же завышенный до ~0.4 ... 0.6 вольт уровень лог.0, идущего от индикатора. При этом у всех прочих абонентов шины этот уровень держится около нуля. Видимо, это такая особенность этого индикатора -своеобразный "подарок разработчиков". Буду иметь в виду ...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.