Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите по I2C
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам
dROb
Здравствуйте! Засел за одну маленькую проблеммку, потратил уже кучу времени, отступаться поздноsm.gif
Есть устройство, а именно I2C 2x16 LCD дисплей (скорее всего на контроллере PCF2119ru)
Пытаюсь управлять им с Arduino, нашёл код, который у людей вполне себе работает. У меня он работает, но немного не так как надо. Первоначально я думал что экран вообще не включается, но оказалось что он включается, только на самом-самом низком уровне контраста. Вот этот контраст я и пытаюсь подкрутить уже пол-дня !!!

Поняв что не могу подобрать правильную команду, или подаю команду как то неправильно - решил подойти к вопросу с другой стороны. Дело в том что есть устройство, работающее с этим экраном ПРАВИЛЬНО, то есть текст на нём появляется, и с нужным контрастом. В общем решил пошпионить за i2c линией, и понять, что именно делаю не так я, и как это делает устройство. На ардуино же собрал простенький сканер, и получил некий дамп, с которым пытаюсь разобраться ещё пол дня sm.gif Но, поскольку с i2c я только знакомлюсь - пока расшифровка не увенчалась большим успехом. Итак, вот дамп, который: 1. Инициализирует экран, 2. Выводит на него немного инфы (жирным шрифтом мои комментарии, что я вроде как расшифровал sm.gif )

S010010001P (вот эти начальные команды вообще непонятны. Что происходит?)
S001010101P
S001010001P
S111010001P
S111010101P
S101010001P
S111011001P (здесь первый раз упоминается i2c адрес устройства - 11101100)
S110000001P
S011000001P
S011000101P
S01110110000000000000110100000001100000
S000P
S0110001000101000000S0111011000000000S0000P
S101100010001010100P
S0111011010000000000110P
S1100010001010100P
S0111010100000001100000P
S11000100010110P
(где то здесь, или несколькими строками ниже, инициализация заканчивается, и начинается написание приветственного сообщения " PowerPanel! \n©06 Eagle Tree")—
S011101100000000000000000010P
S011101S001000000010100000010100000010100000010100000010100000010100000010100000
01010000001010000001010000001010000001010
S011101100000000010000P
S01100010000110101000S011101100100000001S000P
S0110001000110000010S01110110P
S0000010000P
S011000100010110010P
S0111011010000000S00
(приветственное сообщение написано - происходит обновление части текста на экране, а именно - одной-двух цифр)

S011101100000000000110000000P
S011101100010000000111011010P
S011101100010000000110000010P
S011101100010000000110010000P
S011101100010000000101000000P
S0111
S011101100000000000100011110P
S011101100010000000101101000P
S011101100000000000100011110P
S011101100010000000101101010P
S011101100000000000100011110P
S0111

Пару кусочков почти раскладываются на логичные составляющие, например
S 01110110 0 0000000 0 01000010 1 0P - 0x76 0x00 0x42? (в устройство 0x76, передать 0x00 - Control byte for Instruction, но зачем тут 0x42 - или это ответ на Главный Вопрос Вселенной? sm.gif Также, возможно это позиционирование курсора, 0x00 - команда, 0x42 - позиция)
S 01110110 0 0100000 0 01011001 0 0P - 0x76 0x40 0x59 (в устройство 0x76, передать 0x40 - Напечатать Символ, 0x59 - Код символа)
S 01110110 0 0100000 0 01010000 0 0P - 0x76 0x40 0x28
S 01110110 0 0100000 0 01010000 0 0P - 0x76 0x40 0x28
S 01110110 0 0000000 0 01000010 1 0P - 0x76 0x00 0x21
S 0111

На всякий случай мой код инициализации, который не до конца верен, выглядит так, для сравнения (думаю, что в нём есть правильные строчки)
Код
i2c_rep_start(0x76+0);      // ETPP i2c address: 0x3B in 7 bit form. Shift left one bit and concatenate i2c write command bit of zero = 0x76 in 8 bit form.
i2c_write(0x00);            // ETPP command register
i2c_write(0x34);            // Function Set 001D0MSL D : data length for parallel interface only; M: 0 = 1x32 , 1 = 2x16; S: 0 = 1:18 multiplex drive mode, 1×32 or 2×16 character display, 1 = 1:9 multiplex drive mode, 1×16 character display; H: 0 = basic instruction set plus standard instruction set, 1 = basic instruction set plus extended instruction set
i2c_write(0x0C);            // Display on   00001DCB D : 0 = Display Off, 1 = Display On; C : 0 = Underline Cursor Off, 1 = Underline Cursor On; B : 0 = Blinking Cursor Off, 1 = Blinking Cursor On
i2c_write(0x06);            // Cursor Move  000001IS I : 0 = DDRAM or CGRAM address decrements by 1, cursor moves to the left, 1 = DDRAM or CGRAM address increments by 1, cursor moves to the right; S : 0 = display does not shift,  1 = display does shifts


В общем просьба к знающим людям - прокомментировать что происходит у меня на линии. Буду рад даже кускам знаний, может у кого за что глаз зацепилсяsm.gif . Т.е. как правильно разложить этот дамп для лучшего понимания? Что означают каждые кусочки данных? Почему так странно начинается инициализация (ожидается что это будет что то вроде - АдресУстройства, затем 0x00, затем 0x36 ....)


Alex11
Здесь вообще ничего не происходит:
S010010001P (вот эти начальные команды вообще непонятны. Что происходит?)
S001010101P
S001010001P
S111010001P
S111010101P
S101010001P
S111011001P (здесь первый раз упоминается i2c адрес устройства - 11101100) - не тот адрес, а сдвинутый
S110000001P
S011000001P
S011000101P
Это попытки найти устройство по разным адресам, ACK нет, можно выкинуть.

Эти строчки неправильно оцифрованы. Не может быть между S и P ничего не кратного 9 битам:
S01110110000000000000110100000001100000
S000P
Но начало, вроде бы за здравие. Передан адрес, получен ACK. Скорее всего, должно быть интерпретировано так:
S01110110 0 00000000 0 00110100 0 00001100 0 00????00 0P - 0x76, 0x00, 0x34, 0x0c, 0x?? - Очень похоже на Вашу инициализацию

S0110001000101000000S0111011000000000S0000P - здесь опять ошибка оцифровки, так не бывает.
Скорее всего, предыдущая строка не заканчивалась стопом, а идет продолжение инициализации, затем начало следующей команды:

? 0 11000100 0 10100000 0
S01110110 0 0000000? 0 000?
Дальше невозможно что-то понимать, т.к. ни начала ни конца и ошибки в интерпретации стартов и стопов.

Попробуйте поаккуратнее разобраться в осциллограмме, тогда будет проще.
dROb
Alex11, спасибо за ответ! Потихоньку начинаю понимать i2c sm.gif
Что касается дампа коммуникаций и его ошибок - боюсь, лучшего я ничего получить не смогу - осциллографа нет, а данный лог получен простейшим сниффером на Ардуино sm.gif Поэтому, думаю, нужно мне просто побольше времени, и вручную править ошибки в дампе (надеюсь удастся). или найти ошибку в самом сниффере, но на это у меня пока знаний не хватает. Вот, на всякий случай сам сниффер, думаю кому-то может пригодиться:
Код
/**
* I2C bus snooper. Written to eavesdrop on MCU to EEPROM
* communications in a HL168Y blood pressure monitor. SCL
* is connected to Arduino pin 2 and SDA to pin 3.
*/
#define MAX_EVENTS 5
int SCLport = 2;
int SDAport = 3;

char data[MAX_EVENTS];
int dp = 0;

void setup()   {                
  pinMode(SCLport, INPUT);  
  pinMode(SDAport, INPUT);
  Serial.begin(115200);
  Serial.println ("Hi There!");
}

void loop()                    
{
  unsigned char s;
  dp = 0;
  
   lookForStart:
  
   // Expect both SCL and SDA to be high
  while ( (PIND & 0b00001100) != 0b00001100);
  // both SLC and SDA high at this point
  
  // Looking for START condition. Ie SDA transitioning from
  // high to low while SLC is high.
  while ( (PIND & 0b00001100) != 0b00000100);
  data[dp++] = 'S';
   // wait for SCL low
  while ( (PIND & 0b00000100) != 0);
  
  lookForData:
  
  while (dp < MAX_EVENTS) {
    
     // wait for SCL low
    while ( (PIND & 0b00000100) != 0);
    
    // Wait for SCL to transition high
    while ( (PIND & 0b00000100) == 0);
    
    // Sample SDA at the transition point
    s = PIND & 0b00001000;
    data[dp++] = (s == 0 ? '0' : '1');
    
    // Wait for SCL to transition low while looking
    // for start or stop condition. A START or STOP
    // means the previous bit isn't a data bit. So will
    // write START, STOP condition into the same memory slot
    if (s == 0) {
      while ( (PIND & 0b00000100) != 0) {
        if ( (PIND & 0b00001000) != 0) {
           // detected STOP condition
           data[dp-1] = 'P';
           goto lookForStart;
        }
      }
    } else {
      while ( (PIND & 0b00000100) != 0) {
        if ( (PIND & 0b00001000) == 0) {
           // detected START condition
           data[dp-1] = 'S';
           goto lookForData;
        }
      }
    }
  }
  // have exceed storage. Dump to serial port and restart.
  writeData();
}

void writeData () {
  int i;
  for (i = 0; i < dp; i++) {
    Serial.print (data[i]);
    if (data[i] == 'P') {
      Serial.println ("");
    }
  }
  Serial.println ("");
}
vladimir_orl
Насколько я знаю, там под контраст отдельный аналоговый вход.
dROb
Цитата(vladimir_orl @ Sep 28 2012, 10:56) *
Насколько я знаю, там под контраст отдельный аналоговый вход.

Нет, наверное это не мой случай - в моем устройстве ровно четыре провода, GND, SDA, SCL, VCC... и ничего больше
Golikov A.
1. Найти описания контролера и список команд
2. Прочитать описание протокола и2ц

В контролере если нет внешнего кода есть регистр контраста. Но доступ к нему не тривиальный. Надо вызвать режим смены кодовой страницы, сменить кодовую страницу, в ней выдать адрес регистра контраста, и потом значение контраста.

Но почему трудно прочесть 12 страниц про и2ц и 1-2 страницы описания контролера?!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.