Перейти к содержанию

Дмитрий Мартынов

Members
  • Постов

    6
  • Зарегистрирован

  • Посещение

Информация

  • Город
    Москва

Электроника

  • Стаж в электронике
    1-2 года
  • Сфера радиоэлектроники
    микроконтроллеры, цифровая электроника

Посетители профиля

1 002 просмотра профиля

Достижения Дмитрий Мартынов

Новичок

Новичок (1/14)

  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

0

Репутация

  1. В даташите приводится временная диаграмма для режима чтения, поэтому чтение возможно. А еще написано, что если данные на выводах микросхемы меняются быстрее, чем может прочитать микроконтроллер, то эта информация будет потеряна (на диаграмме DATA2 и DATA3 теряются). "If the data on the input port changes faster than the master can read, this data may be lost. The DATA 2 and DATA3 are lost because these data did not meet the setup time and hold time (see Figure 9)." Еще приводится алгоритм чтения, в моем коде выполняется все в той же последовательности, только вместо отправки бита неподтверждения и СТОП состояния посылается состояние ПОВСТАРТ:
  2. да, это все из-за любопытства, спасибо за файлы, я их посмотрю)
  3. 1 - для инициализации дисплея в даташите указан конкретный алгоритм, который я привел в самом первом сообщении. Все, что в нем требуется я делаю вместе с программными задержками вплоть до 4й команды. Затем там написано после 4й команды (4го отправленного полубайта): "после этой команды флаг занятости может быть прочитан". С задержками до 4й команды все нормально, к ним больше не возвращаемся. 2 - Читаю первое сообщение. "Зачем читать флаг". На высоких частотах fSCL модуля TWI будет выше, поэтому отправка команд на дисплей будет производиться быстрее сброса флага BF. Поэтому возникает ризон все же его прочитать, как написано в том самом даташите. "Пока ты его прочитаешь он уже сбросится". Ну пускай он сбросится, если сбросился, значит контроллер готов принимать следующий байт данных. Раз он сбросился , значит контроллер готов к работе, и ждет следующей команды. Так почему же он НЕ инициализируется, когда в коде присутствует команда проверки BF? Почему он инициализируется просто с задержками, во время которых флаг BF также сбрасывается, но только гораздо раньше? ПОВТОРЮСЬ: Корень проблемы не в том, чтобы хоть как-то сделать инициализацию с произвольными задержками, неуказанными в даташите. Имеется необходимость сделать правильную инициализацию с чтением флага занятости BF, исключив необходимость вслепую прописывать задержки, взятые с потолка. Возможно я не совсем хорошо объясняю и поэтому в этом трудно разобраться. 3 - метод отправки полубайта у меня есть и он работает нормально, но все равно спасибо. Ассемблер - это хороший процедурный язык, но не в этой теме. Здесь C++.
  4. Все очень хорошо, но опять же, хотелось бы реализовать чтение флага, что производить команды сразу после готовности контроллера дисплея. Как я уже сказал, инициализация выполняется с задержками, и это уже не так важно. Скинутый код похож на тот, что я уже реализовал. Скорость тактирования по линии SCL микроконтроллера составляет fSCL = 20000Гц, а значит передача байта осуществляется за 0.4 мс. Т.к. режим передачи 4х битовый, на отправку команды требуется 0.8 мс (2 байта). В совокупности все команды превышают время сброса флага занятости, поэтому флаг читается сразу сброшенным. Выходит контроллер дисплея готов принять следующий байт. Однако, инициализации не происходит, как если бы я делал задержки. Значит, сброшенный флаг, который я считываю, не достоверно говорит о готовности принять байт контроллером дисплея. Здесь что-то не так, и в этом мне хочется разобраться. Нужен код с реализацией успешного чтения флага занятости и инициализации дисплея без задержек в 2 мс. Ведь, по сути, мой метод readBF() - это такая же задержка, но она ждет конкретной готовности контроллера. Раз флаг читается нулем - значит контроллер готов. Почему тогда не происходит верной инициализации???? void LCD_I2C::readBF() { transmitByte(0b00001110); //transmits E, RW set to HIGH and RS, set to LOW transmitByte(0b00001010); //transmits E, RS set to LOW and RW set to HIGH initRestart(); //initilizes RESTART state transmitAddrRW(0b01111111); //sends PCF8574AT address + SLA+R do { receiveDataAck(); //read BF (get data to storage register) } while((storage & (1 << BF)) != 0); //wait until BF is 0 initRestart(); //initialiazes RESTART state transmitAddrRW(0b01111110); //sends PCF8574AT + SLA+W }
  5. Значит предлагается использовать задержку в 20 мс, я это учту и попробую. Хочется, конечно, читать BF, вдруг он сбрасывается не за 20, а за 2 мс:) Однако, видимо время обмена по TWI превышает время, за которое сбрасывается BF, поэтому на частоте в 1МГц думаю это уже не так важно. Для более высоких частот проверка BF будет более востребована.
  6. Здравствуйте! Пишу программу на C++ для управления LCD (HD44780) по I2C через модуль расширения портов ввода/вывода PCF8574AT. void LCD_I2C::readBF() { transmitByte(0b00001110); //transmits E, RW set to HIGH and RS, set to LOW _delay_ms(5); transmitByte(0b00001010); //transmits E, RS set to LOW and RW set to HIGH _delay_ms(5); initRestart(); transmitAddrRW(0b01111111); //sends PCF8574AT address + SLA+R do { receiveDataAck(); PORTA = storage; } while((storage & (1 << BF)) != 0); //wait until BF is 0 initRestart(); transmitAddrRW(0b01111110); } Метод void transmitByte(uint8_t data) после инициализации состояния "Старт" и отправки адреса устройства + SLA+W отправляет байт данных по TWI с ожиданием бита подтверждения (команды работают верно, проверял по регистру статуса TWI - 0x08, 0x10 и 0x24). Метод void transmitAddrRW(uint8_t address) отправляет соответственно SLA+W/R + адрес устройства (команда работает также верно). Нареканий к работе TWI у меня нет, т.к. недавно с его помощью успешно запустил часы DS1307 с интеграцией LCD. После передачи запроса на чтение флага занятости инициализируется состояние "ПОВСТАРТ", отправляется адрес устройства + SLA+R, далее идет цикл - запрос байта данных (состояние выводов PCF8574AT) с отправкой бита подтверждения uint8_t receiveDataAck() (команды работают также верно, возвращает storage = TWDR) и вывод storage на порт А микроконтроллера (там установлены светодиоды). Чтение регистра данных TWDR после принятия байта данных (receiveDataAck()) дает следующий результат - 0b00000010 - установлен только бит RW микросхемы. Таким образом, флаг занятости BF = DB7 = 7й бит оказывается сразу же сброшенным, происходит мгновенный выход из цикла - контроллер дисплея не успевает скушать информацию, и инициализация не выполняется (неудачную инициализацию определяю по отсутствию курсора). Ожидалось, что флаг занятости будет установлен в единицу и произойдет несколько итераций перед выходом из цикла. При замене метода ожидания сброса флага занятости BF на программную задержку в 250 мс везде, где это требует datasheet - инициализация происходит успешно (появляется курсор, как и должно быть). Вопрос: что можно сделать, чтобы вместо _delay_ms(250) использовать readBF(), т.к. этот путь мне кажется более верным (уж очень не хочется использовать задержку .__.)? Возможно, проблема в микросхеме, которая неверно выдает информацию при чтении? (Имеется вторая микросхема, она вообще не работает:D) З.Ы. На фото виден результат чтения флага BF и Adress Counter - установлен только бит RW. З.Ы.Ы Кому интересно - вот функция main(). Повторюсь - проблема только в методе readBF(): void LCD_I2C::init() { setBitRate(20000); initStart(); transmitAddrRW(0b01111110); //send PCF8574AT address + SLA+W _delay_ms(60); sendInstruction(0b00110000); //function set 8-bit operation _delay_ms(20); sendInstruction(0b00110000); //function set 8-bit operation _delay_ms(5); sendInstruction(0b00110000); //function set 8-bit operation _delay_ms(5); sendInstruction(0b00100000); //function set 4-bit operation readBF(); //_delay_ms(250); //debug!! sendInstruction(0b00100000); //function set 4-bit operation, 2 lines, 5x8 dots sendInstruction(0b10000000); readBF(); //_delay_ms(250); //debug!! sendInstruction(0b00000000); //display off, cursor off, blinking off sendInstruction(0b10000000); readBF(); //_delay_ms(250); //debug!! sendInstruction(0b00000000); //display clear sendInstruction(0b00010000); readBF(); //_delay_ms(250); //debug!! sendInstruction(0b00000000); //entry mode set increment, display shift off sendInstruction(0b01100000); readBF(); //_delay_ms(250); //debug!! sendInstruction(0b00000000); //display on, cursor off, blinking off sendInstruction(0b11100000); readBF();/ }
×
×
  • Создать...