74HC595 & LCD нужна подсказка
- Войдите на сайт для отправки комментариев
Чт, 23/02/2012 - 22:06
Попробовал эту библиотеку:
http://arduino.cc/playground/Main/LiquidCrystal#Description
но что то не получается и с какого боку копать не понятно.
Может кто победил ее?

Первое, что приходит на ум - неправильное подключение микросхемы. Но на приведенной фотографии ее не видно. Что-то посоветовать невозможно.
Второе, что приходит на ум - какая-то ошибка в программе. Но программа тоже не приведена. Обсуждать нечего.
Третье, что приходит на ум - требуется рабочее решение "с нуля". Едва ли кто-то бросится решать эту задачу для вас. Остается поиск... Google и Yandex вам в помощь. Почитайте, например, что советует известный персонаж на арене Arduino - ladyada (ответ #5). Может быть, что-то прояснится.
Рекомендую для прочтения статью на Робокрафте robocraft.ru/blog/arduino/541.html - там не только увеличивают количество входов и выходов, но и переопределяют драйвера управления пинами таким образом, чтобы стандартные библиотеки работали через расширенные порты. Там и найдете решение.
Сейчас я тоже занялся lсd дисплеем через регистр. Попытался сделать как написано в статье. Тот же код так же подключил дисплей через 2 регистра. Толку 0. Стать я не очень хорошо написана. Я ничего не понял из неё. А особенно скажите откуда берётся переменная uint8_t. Я когда статью про регистры читал она тоже там присутствовала. Но не где не написано что это.
unit8_t это не переменная, это тип данных, соответствует unsigned char. У автора, наверно, хедер от атмеги подключен, и он привык к этому типу.
Статья, конечно, не подарок, но основная идея там правильная - это переопределение драйвера лонии порта при переходе на внешние регистры.
#include <SPI.h> enum { REG_SELECT = 8 }; // пин, управляющий защёлкой (SS в терминах SPI) void setup() { /* Инициализируем шину SPI. Если используется программная реализация, * то вы должны сами настроить пины, по которым будет работать SPI. */ SPI.begin(); pinMode(REG_SELECT, OUTPUT); digitalWrite(REG_SELECT, LOW); // выбор ведомого - нашего регистра SPI.transfer(0); // очищаем содержимое регистра /* Завершаем передачу данных. После этого регистр установит * на выводах QA-QH уровни, соответствующие записанным битам. */ digitalWrite(REG_SELECT, HIGH); } /* Эта функция сдвигает биты влево на одну позицию, перемещая старший бит * на место младшего. Другими словами, она "вращает" биты по кругу. * Например, 11110000 превращается в 11100001. */ void rotateLeft(uint8_t &bits) { uint8_t high_bit = bits & (1 << 7) ? 1 : 0; bits = (bits << 1) | high_bit; } void loop() { static uint8_t nomad = 1; // это наш бегающий бит /* Записываем значение в сдвиговый регистр */ digitalWrite(REG_SELECT, LOW); SPI.transfer(nomad); digitalWrite(REG_SELECT, HIGH); /* И вращаем биты влево - в следующий раз загорится другой светодиод */ rotateLeft(nomad); delay(1000 / 8); // пробегаем все 8 светодиодов за 1 секунду } Идея то правильная. Только я не могу понять. Собрал всё также как и в статье и прошил тем же скетчем. Но не работает. А ещё забыл сказать у меня дисплей то другой.
Он у меня такой же как и в первом посту. 16/2. Как используя ту статью адаптироваться к моему дисплею? + я не очень понимаю как происходит обращение к регистру.
Можно ли как то рассказать поле подробней и понятней. Кто ни буть пробовал так вот подключить дисплей?
Объясните тогда как работает этот скетч. Статья про регистры.
А именно расскажите про каждые строки. Част строк вообще не подписаны что они делают
Это ж просто "бегающий бит" по внешнему регистру.
В статье, на которую я указал много всего:
1. Определяется новый интерфейс:
class LineDriver { public: virtual void lineConfig(uint8_t pin, uint8_t mode) = 0; virtual void lineWrite(uint8_t pin, uint8_t value) = 0; virtual uint8_t lineRead(uint8_t pin) = 0; };2. Драйвер по-умолчанию
class DefaultLineDriver: public LineDriver { public: virtual void lineConfig(uint8_t pin, uint8_t mode) { pinMode(pin, mode); } virtual void lineWrite(uint8_t pin, uint8_t value) { digitalWrite(pin, value); } virtual uint8_t lineRead(uint8_t pin) { return digitalRead(pin); } static DefaultLineDriver* getInstance() { return &g_instance; } private: static DefaultLineDriver g_instance; // один глобальный экземпляр драйвера };3. Расширяют (переопределяют) класс LiquidCrystal
// LiquidCrystalExt.h class LiquidCrystal: public Print { … public: LiquidCrystal(uint8_t rs, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, LineDriver *line_driver = 0, uint8_t backlight = 0xFF); … protected: void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, LineDriver *line_driver = 0, uint8_t backlight = 0xFF); … LineDriver *_pins; … }; // LiquidCrystalExt.cpp LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, LineDriver *line_driver, uint8_t backlight) { init(1, rs, 0xFF, enable, d0, d1, d2, d3, 0, 0, 0, 0, backlight, line_driver); } void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t backlight, LineDriver *line_driver) { _pins = line_driver; if (!_pins) _pins = DefaultLineDriver::getInstance(); … }4. Добавляют поддержку интерфейса LineDriver в класс для работы с SPI
class SPI_Bus: public LineDriver { public: … virtual void lineConfig(uint8_t pin, uint8_t mode) { /* Оставляем метод пустым, т.к. возможность управления состоянием выводов * зависит от конкретного устройства. */ } virtual void lineWrite(uint8_t line_num, uint8_t value) { /* Каждому байту соответствует 8 "линий данных" (виртуальных пинов). * Проверяем, не превышает ли номер линии максимальный. */ if (line_num < m_bandwidth * 8) { /* Рассчитываем номер байта в буфере и номер бита в байте */ const uint8_t byte_index = line_num / 8, bit_index = line_num % 8; /* Сначала стираем нужный бит в буфере */ m_buffer[byte_index] &= ~(1 << bit_index); /* Потом устанавливаем нужное значение бита ("уровень на линии") */ m_buffer[byte_index] |= (value == LOW ? 0 : 1) << bit_index); /* Шлём изменённое содержимое буфера. Если работаем со сдвиговым * регистром, то нужная ножка регистра поменяет свой уровень на * тот, который задан в аргументе value. */ communicate(&SPI_Bus::operationSendBuffer); } } virtual uint8_t lineRead(uint8_t line_num) { /* Если такой линии нет, возвращаем "низкий уровень на линии" */ if (line_num >= m_bandwidth * 8) return LOW; /* Линия есть, считываем состояние линий в буфер */ communicate(&SPI_Bus::operationReceiveEntireBuffer); const uint8_t byte_index = line_num / 8, bit_index = line_num % 8; /* Читаем нужный бит из буфера и возвращаем соответствующий ему * уровень на линии. */ return (m_buffer[byte_index] >> bit_index) & 1 ? HIGH : LOW; } … };5. Передают указатель на объект сдвигового регистра в конструктор объекта LCD
P.S. Все тексты программ взяты из статьи Подключаем кучу устройств к Arduino по 5 проводам / Arduino-мания :) / RoboCraft
Это всё я уже видел. И ничего не понял из того что написано. В конечном итоге все эти манипуляции в библиотеке сводятся тому что мы её скачиваем и ставим к себе уже готовую. А что писать в скетче мне не ясно. И как подключить дисплей к регистру? Можно ли обойтись одним регистром? Об этом ничего не сказано.
Про бегающий бит тоже есть вопросы.
Как работает это
void rotateLeft(uint8_t &bits)
{
uint8_t high_bit = bits & (1 << 7) ? 1 : 0;
bits = (bits << 1) | high_bit;
}
Что значит эта строка и что она хранит
static uint8_t nomad = 1; // это наш бегающий бит
как выставляются выходы если судя по записи мы туда послали единицу?
SPI.transfer(nomad);
Это просто зацикленный сдвиг битов. Вам, как я понимаю, она Вам вообще никаким боком не нужна.
Ну а работает она просто. В первой строке проверяется наличие старшего бита (1<<7) - маска, "переводится" как 1, сдвинутый влево 7 раз. То есть это ни что иное, как 0b10000000 (двоич.) Если старший бит есть, то промежуточная переменная устанавливается в 1 (0b00000001) - для переноса при сдвиге старшего бита в позицию младшего.
Во вторй строке содержимое bits сдвигается на одну позицию влево и, если был старший бит (high_bit), то он записывается в младшую позицию.
А чтобы было понятно, что писать в скетче, нужно понимать, "как это работает". Ну или хотя бы схему и скетч "в студию" - поможем разобраться.
Послать единицу, это послать 110=000000012 - то есть в 1 установится 1 выход из 8 на регистре
С самим регистром и статьёй я разобрался. Понял как работает SPI.transfer(nomad); или
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay) (статья); только мне непонятна эта переменная MSBFIRST. А так всё ок. Возник вопрос в shiftOut можно задать пины какие хочеш (1,2,3) а в SPI.transfer я так понял нет?
Вторая часть моего вопроса. С регистром для одного проекта разобрался но для другого необходимо 2 регистра. На одном висит монитор на другом светодиоды. Как подключить монитор (16/2) к регистру? Только необходимо монитор полностью к регистру привязать. И что писать в скетче? Ориентируюсь на статью.
Шикарно разобрался))))))
#include <LineDriver.h> #include <SPI.h> #include <SPI_Bus.h> #include <LiquidCrystalExt.h> SPI_Bus shift_register(_8bit, 10); LiquidCrystal lcd(1, 2, 3, 4, 5, 6, &shift_register); void setup() { /* Инициализируем дисплей: 2 строки по 16 символов */ lcd.begin(16, 2); /* Выводим на дисплей традиционную фразу (: */ lcd.print("hello, world!"); } void loop() { lcd.setCursor(0, 1); /* Выводим на дисплей число секунд, прошедших с момента старта Arduino */ lcd.print(millis() / 1000); }Опять что то не работает. Перетыкал провода и снова не пашет
Я вроде разобрался с подключением и библиотеками.
Их много и разные, поэтому много путаницы.
В результате схема:
Библиотека к ней LiquidCrystal_v1.1.7.1.zip
И скетч:
#include <LiquidCrystal_SR.h> LiquidCrystal_SR lcd(11,12,8); // | | | Enable Pin // | \-- Clock Pin // \---- Data Pin // Creat a set of new characters byte armsUp[8] = {0b00100,0b01010,0b00100,0b10101,0b01110,0b00100,0b00100,0b01010}; byte armsDown[8] = {0b00100,0b01010,0b00100,0b00100,0b01110,0b10101,0b00100,0b01010}; void setup(){ lcd.begin(16,2); // initialize the lcd lcd.createChar (0, armsUp); // load character to the LCD lcd.createChar (1, armsDown); // load character to the LCD lcd.home (); // go home lcd.print(F("LiquidCrystal_SR")); } void loop(){ // Do a little animation for(int i = 0; i <= 15; i++) showHappyGuy(i); for(int i = 15; i >= 0; i--) showHappyGuy(i); } void showHappyGuy(int pos){ lcd.setCursor ( pos, 1 ); // go to position lcd.print(char(random(0,2))); // show one of the two custom characters delay(150); // wait so it can be seen lcd.setCursor ( pos, 1 ); // go to position again lcd.print(F(" ")); // delete character }Ну и наконец на бредборде:
Буду рад если кому то это помогло!
Всем добрый день, никак не могу разобраться с подключение lcd через регистр, может есть у кого нибудь схемка? Делал все как в статье robocraft.ru/blog/arduino/541.html, но чтото не выходит
с Arduino (назовем её мама) отправляем команды через Serial Pin (D1 - TX) символы например // Serial.println('W');..
Atmega328 (назовем её дочка) слушает команды через ВХод Serial Pin (D0 - RX) ..
В зависимости от пришедшего символа от мамы,дочка выполнит что хотим.
Таким способом через всего один пин на Arduino
мы можем управлять дополнительно 18 пинами.
Постскриптум В этом уроке я демонстрирую взаимодействия 2 ARDUINO через Serial
саму идею можно расширять до бесконечности.
Учитывая падение цен на Microcontrolle?r ATMEGA328,
получается довольно приятная альтернатива, микросхемам сдвиговым регистрам 74HC595,74HC165
------------------------------------------
скетч sketch: v.01 Arduino увеличиваем кпличество пинов Atmega328 Increase pins
http://yadi.sk/d/lIVZHuBq7GMhG
================================
что нам понадобиться.
Аппаратное:
1. Arduino -1 штука.
2. ATMEGA328P-PU Microcontrolle?r With ARDUINO UNO Bootloader -1 штука.
3. 16.000MHZ 16MHZ 16M HZ HC-49S Crystal Oscillator -1 штука.
4. Светодиоды нужны только для визуального контроля за процессом.
Тогда уж лучше связывать по SPI или TWI.
А теперь сравним быстродействие :) Ведомая ардуина имеет смысл только, если занимается еще чем-то, скажем, динамической индикачией. А просто плодить таким образом выходы... я бы не стал. Контроллер и повиснуть может...
Случаем не подскажете что может означать ошибка:
In file included from sketch_jan12a.ino:4:
E:\arduino\libraries\LiquidCrystal_SR/LiquidCrystal.h:86: error: conflicting return type specified for 'virtual void LiquidCrystal::write(uint8_t)'
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:48: error: overriding 'virtual size_t Print::write(uint8_t)'
не могу найти LiquidCrystal_v1.1.7.1.zip выложите пожалуйста
Первая же ссылка в гугле - https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
спасибо большое! всё заработало
спасибо большое! всё заработало