Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Решай головоломку с котиками!

Котолэнд: блок пазл

Головоломки, Казуальные, 2D

Играть

Топ прошлой недели

  • Oskanov Oskanov 8 постов
  • alekseyJHL alekseyJHL 6 постов
  • XpyMy XpyMy 1 пост
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Новости Пикабу Помощь Кодекс Пикабу Реклама О компании
Команда Пикабу Награды Контакты О проекте Зал славы
Промокоды Скидки Работа Курсы Блоги
Купоны Biggeek Купоны AliExpress Купоны М.Видео Купоны YandexTravel Купоны Lamoda
Мобильное приложение

Avr

С этим тегом используют

Arduino Микроконтроллеры Электроника Своими руками Самоделки Программирование Все
63 поста сначала свежее
67
Dionisnation
Dionisnation
9 лет назад

Программирование AVR - Ассемблер. Уроки по AVR от Романа Звездопадова⁠⁠

Советую к просмотру подборку видеоуроков по программированию 8 битных AVR микроконтролеров на ассемблере

О 8 битных микроконтроллерах. На чем лучше программировать.

Программирование AVR Ассемблер. Урок 1. Вводный.

Программирование AVR Ассемблер. Урок 2. Порты. Мигалка.

Программирование AVR Ассемблер. Урок 3. Таймер. Мигалка на таймере.

Программирование AVR Ассемблер. Урок 4. АЦП.

Программирование AVR Ассемблер. Урок 5. Динамическая индикация.

Программирование AVR Ассемблер. Урок 6. Аналоговый компаратор.

Программирование AVR Ассемблер. Урок 7. ШИМ(PWM). Управление серво.

Программирование AVR Ассемблер. Урок 8. Внешние прерывания.

Программирование AVR Ассемблер. Урок 9. USART.

Программирование AVR Ассемблер. Урок 10. SPI.

Программирование AVR Ассемблер. Урок 11. LCD.

Программирование AVR Ассемблер. Урок 12. 1-Wire.

Программирование AVR Ассемблер. Урок 13. TWI(I2C).

Программирование AVR Ассемблер. Урок 14. Управление шаговым двигателем.

Программирование AVR Ассемблер. Урок 15. ЦАП(DAC). Модифицированный синус.

Программирование AVR Ассемблер. Урок 16. Двоично-десятичные дешифраторы.

Программирование AVR Ассемблер. Урок 17. Сдвиговые регистры.

Программирование AVR Ассемблер. Урок 18. EEPROM.

Программирование AVR Ассемблер. Урок 19. Светодиодные матрицы. Бегущая строка.

Программирование AVR Ассемблер. Урок 20. Сторожевой таймер(Watch Dog Timer).

Показать полностью 20
Avr Assembler Ассемблер Микроконтроллеры Программирование Technobrother Видео Длиннопост
7
9
STARTS
STARTS
9 лет назад

Atmega8 + lcd через шину i2c и датчик температуры)⁠⁠

Всем доброго времени суток) Решил поделиться своими успехами в программировании мк atmega8) Подключил lcd через шину i2c, которая позволяет управлять lcd, используя лишь 2 провода) При чем имеется возможность программного включения и отключения подсветки) 

Atmega8 + lcd через шину i2c и датчик температуры) Avr, Микроконтроллеры, Lcd дисплей, Программирование, Atmega8, Хобби, Радиоэлектроника, Длиннопост

Использовал макетку, со стороны кажется что тут нихрена не 2 провода под lcd и не 1 провод под датчик температуры, но на самом деле это так) Просто вставлены еще провода программирования)

Atmega8 + lcd через шину i2c и датчик температуры) Avr, Микроконтроллеры, Lcd дисплей, Программирование, Atmega8, Хобби, Радиоэлектроника, Длиннопост

Сзади виден программатор usbasp, с помощью которого и программируется данный мк)

Atmega8 + lcd через шину i2c и датчик температуры) Avr, Микроконтроллеры, Lcd дисплей, Программирование, Atmega8, Хобби, Радиоэлектроника, Длиннопост

Спасибо, что просмотрели мой пост) Я еще новичок в этом нелегком деле и только начинаю все изучать) 

Показать полностью 3
[моё] Avr Микроконтроллеры Lcd дисплей Программирование Atmega8 Хобби Радиоэлектроника Длиннопост
27
5
DarkDaiver77
9 лет назад

Электронный термометр своими руками. Часть вторая.⁠⁠

В общем все-таки взял себя в руки и доделал что и планировал вот тут

http://pikabu.ru/story/yelektronnyiy_termometr_svoimi_rukami...

Когда запилил тут пост, обещал что работу продолжу и выложу код. Что собственно я и делаю.

Исходный код лежит тут


https://github.com/hruslowkirill/TermoRegulator


Задача такова: сделать устройство, к которому подключить 3 реле и 3 термометра. На основании показаний с термометра необходимо включать или отключать реле. Задача услодняется тем, что температура включения/выключения и гистерезис для каждой реле, должны быть настраиваемыми. То есть, в устройстве должен быть дисплей с меню и кнопки.

И так приступим. За основу я взял контроллер AtMega8, что оказалось не совсем правильным решением, так как там всего 4 кБ памяти для программы. В эти 4к я уложился, но программа занимает 99.7% памяти, что не позволяет добавить ничего нового. Ну да ладно.


Для начала рисуем схему устройства. Altium Designer был выбран для этой цели и для последубщего проектирования PCB (printed circuit board).

Электронный термометр своими руками. Часть вторая. Программирование, Avr, Atmega, Си, Тег, Электроника, Длиннопост, Видео

На схеме присутствуют:

- Микроконтроллер AtMega8

- Кварцевый генератор для контроллера. Именно он задает частоту процессора.

- LCD дисплей 16x2

- Потенциометр, нужен для настройки контраста LCD дисплея

- 3 термодатчика DS18B20

- 3 кнопки (+ - OK)

- Гнездо питания

- Выводы для подключения реле (реле на схеме нет)

Все детали дешевые и заказываются на ebay.


После того, как мы удволитворены результатом, мы разводим плату и получается вот такая красивая штука

Электронный термометр своими руками. Часть вторая. Программирование, Avr, Atmega, Си, Тег, Электроника, Длиннопост, Видео

Красные дорожки с одной стороны платы, синие с другой. Есть несколько вариантов как превратить файл на даске в реальную плату. Я выбрал легкий и дорогой способ - отправить на завод, чтобы ее распечатали на заказ. Отправляем файл и деньги и получаем вот такую готовую плату:

Электронный термометр своими руками. Часть вторая. Программирование, Avr, Atmega, Си, Тег, Электроника, Длиннопост, Видео

Получилась она очень неоптимизированная... но ладно, первый блин комом.

Далее все эелементы напаиваются на плату по схеме. И получаем готовое устройство. Но как вы уже доагадались не хватает прошивки. А без прошивки это все просто кусок кремния.

Программа для этого устройства написана на языке С в среде AVR Studio 5. Исходный код можно получить пройдся по ссылке в начале поста.


Что же там есть:

- lcd.h, lcd.c - код для управления LCD дисплеем. В первоначальом варианте, при выводи текста мы отчищаем экран а потом отправляем на дисплей строку для отображения. Но это предает эффект мерцания, что очень некрасиво выглядет. Проблема преодолевается методом двойной буферизации - то есть мы отправляем данные для вывода, которые созраняются локально в памяти, а потом за раз отправляются на дисплей. Выглядет это примерно так:

Электронный термометр своими руками. Часть вторая. Программирование, Avr, Atmega, Си, Тег, Электроника, Длиннопост, Видео

-ds18b20.h, ds18b20.c - код для опроса датчиков температуры

-relay.h, relay.c - код для работы с релюшками

-settings.h, settings.c - код для работы с постоянной памятью для сохранения настроек

regulator8.c - код основной программы.


Если кого, то интересует а как собственно устройства управляются программой. У каждого устройства свой протокол общения, но все сводится к тому что, контроллер может подать напряжение на ножку или отключить. От так же может проверить если напряжение на ножке или нет. LCD общается через 7 ног, тогда как термометр только через одну. 


Но как быть когда нет устройства под рукой? Есть такая программа как proteus - симулятор электрических схем. Работает он не очень хорошо, но для данного проекта вполне достаточно. В программе собирается схема с наших компонентов. Но вам это делать не обязательно, проект доступен на github. Указав путь к файлу с программой и к файлу с содежанием памяти можно начинать симуляцию. 


Электронный термометр своими руками. Часть вторая. Программирование, Avr, Atmega, Си, Тег, Электроника, Длиннопост, Видео

В проекте вместе реле стоят обыные LED если температу на датчике ниже заданной в настройках температуры с заданным гистерезисом, то LED отключается. Кому интересно может поиграть с кодом и симулятором.


В начальный момент, LCD показывает температуру всех датчиков. Для того чтобы зайти в меню надо нажать кнопку OK и дердать около 10 секунд. Дальше разобраться можно интуитивно.



Видео с работающим устройством:

В общем если есть вопросы или замечания пишите в комментариях!

Гордо ставлю тег Моё.

Показать полностью 5 1
[моё] Программирование Avr Atmega Си Тег Электроника Длиннопост Видео
16
410
TocTeeeP
TocTeeeP
9 лет назад

DIY: самодельный Wi-fi чайник⁠⁠

Мой  первый серьезный проект в электронике. Простите за качество и дрожь в руках, я просто хотел показать, что у меня получилось.  

[моё] Чайник Wi-Fi Самоделки Avr Видео
70
61
Dionisnation
Dionisnation
9 лет назад

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ…⁠⁠

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Статья не моя. Но будет полезная моим подписчикам которые подписались ради DIY. Взята из сообщества Easyelectronics (Не рекламирую, просто указываю чтобы опять тапками не бросались)

Далее от Автора :
Прочитав пару статей других пользователей, захотелось самому начеркать чего-то полезного для остальных. Как все поняли из названия, речь пойдет о создании USB mass storage device класса на програмной реализации V-USB.

Знакомство мое с данной библиотекой произошло случайно и оч. давно. Как и большинство(наверное) на то время любителей я все работал на микрухах типа pl2303 и FT245(232), а они, как известно, не позволяют изменять класс устройства (тока то, что зашито на заводе и все). Купить контроллер с аппаратной частью USB возможности не было, вот, как говорится, и понеслось!) Бодяжил много чего полезного и бесполезного, но как говориться тока для себя зануды любимого. Как-то читал на одном известном форуме, что реализовать то или иное устройство на данной «псевдо» USB нереально, а передавать большие объемы данных и подавно. Так и задался целью замутить чегонить вроде USB флешки или микрофона. И то и другое сделал, но из-за того что я тяжелый на подъем, в массы так и не выкладывал. Вот и моя первая проба познакомить уважаемое сообщество со своим проектом.


Сразу оговорюсь, что все приведенные фотки моего девайса тока для ознакомления, потому как это платка мой программатор AVR по USB со своим бутом и прогой для апдейту. Схему я конечно выложу, но плату разводить, наверное, специально для этого проекта, не буду.

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Проект выполнен на IAR’е, sPlan, SprintLayout, Device Monitoring Studio и утюге под пиво =) Ну, в путь!


Для начала, немного теории. MSD или Mass Storage Class это ничто иное, как один из стандартных классов USB для описания и взаимодействия с утройствами хранения информации. Реализаций и стандартов MSD довольно много и заморачиваться на каждом из них нет смысла. Опишу самый распространенный из них(он же самый простой на мой взгляд): Bulk-only или BBB.


В стандарте USB есть такое понятие, как конечная точка(end-point). Конечная точка — это часть USB-устройства, которая имеет уникальный идентификатор и является получателем или отправителем информации, передаваемой по шине USB. Проще говоря, это буфер, сохраняющий несколько байт. Обычно это блок данных в памяти или регистр микроконтроллера. Данные, хранящиеся в конечной точке, могут быть либо принятыми данными, либо данными, ожидающими передачу. Хост также имеет буфер для приема и передачи данных, но хост не имеет конечных точек.


Конечная точка имеет следующие основные параметры:

1 - Частота доступа к шине

2 - Допустимая величина задержки обслуживания

3 - Требуемая ширина полосы пропускания канала

4 - Номер конечной точки

5 - Способ обработки ошибок

6 - Максимальный размер пакета, который конечная точка может принимать или отправлять;

7 - Используемый конечной точкой тип посылок

8 - Направление передачи данных

Любое USB-устройство имеет конечную точку с нулевым номером (Endpoint Zero). Эта точка позволяет хосту опрашивать устройство с целью определения его типа и параметров, выполнять инициализацию и конфигурирование устройства.


Кроме нулевой точки, устройства, обычно, имеют дополнительные конечные точки, которые используются для обмена данными с хостом. Дополнительные точки могут работать либо только на прием данных от хоста (входные точки, IN), либо только на передачу данных хосту (выходные точки, OUT). Число дополнительных конечных точек устройств определяется режимом передачи.


Для низкоскоростных устройств допускается наличие одной или двух дополнительных конечных точек, а для высокоскоростных — до 15 входных и 15 выходных дополнительных точек.


Но это тока теория, которая выглядит довольно абстрактно. Будем считать, что конечная точка, это ничто иное как фунция в языке C, которая тока принимает параметры, или только возвращает значения.


Так вот, мы строим устьройство, отвечающее спецификации bulk-only. И тут самое приятное: все события делятся на три фазы:

1 - Прием команды от хоста(копьютера)(CBW)

2 - Прием/Передача запрашиваемых данных(DATA)

3 - Передача хосту результата выполнения принятой комманды(STATUS)

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Здесь видно, что мы принимаем данные и отправляем данные, значит мы имеем 2 конечные точки (от хоста к устройству и наоборот), а, исходя из выбранной спецификации, эти точки используют bulk передачу данных.


Следовательно мы должны сконфигурировать библиотеку V-USB соответсвующим образом:

1 - Описываем конечную точку-in

2 - Конечную точку-out

3 - Указываем v-USB, что мы используем 2 конечные точки помимо основной (control-endpoint)

4 - Задаем класс устройсва USB — Mass Storage Class Bulk-only (Не пугайтесь, все это легко видно из файлов прошивки).

На этом весь процесс создания устройства MSD bulk-only закончен и мы приступаем к тому, что принимаем от хоста комманды и соответсвенно реагируем на них!


Теперь вкратце о тех самых коммандах от хоста. Их не так много и большинство из низ поступают только пару раз. Итак хост может попросить от нас следующее:

   ► Inquiry — запрос основных характеристик устройства

   ► Test unit ready — проверка готовности устройства, в т.ч. наличия диска в дисководе.

   ► Request sense — возвращает код ошибки предыдущей команды.

   ► Read capacity — возвращает ёмкость устройства.

   ► Read (4 варианта) — чтение.

   ► Write (4 варианта) — запись.

   ► Mode select — установка параметров устройства.

   ► Mode sense — возвращает текущие параметры устройства

Теперь далее. Пересмотрев массу устройств хранения информации (EEPROM, nand и т.д.) я выбрал, наверное, самое распространненое SD/MMC карту памяти. Подключение ее к AVRке давно известно, а протокол хорошо разжеван. Еще один плюс в том, что эти карты могут читать/писать по 512 байт данных, что очень подходит для данной задачи.


Так, основными коммандами MSD bulk-only устройстве являются чтение и запись блоков информации. Драйвер Windows (да простят меня пользователи Linux) обращается к нашему устройству по принципу LBA, то есть адрес логического блока (или его номер, что одно и тоже) и их количество.


В нашем случае один логический блок это сектор размером в 512 байт. Так если ОС запросит у нас данные из 20-го LBA, то мы просто умножим 20 на 512 и получим линейный адрес на устройстве носителя. Затем прочитем/запишем нужное число блоков и все! Знать что-то о данных на устройстве хранения информации и способе их размещения AVR не должна. Наша задача обеспечить возможность чтения и записи этих самых блоков из/на устроство хранения информации, а остальное сделает ОС.)


Теперь я представлю Вам мою схемку. Сразу оговорюсь, делал на быструю руку, так как печатку делал из головы (схема не сложная):

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Многие заметят, что практически стандартная схема для устройств на V-USB, и что я немного перемудрил с ней, на я повторюсь, что собрал флешку из моего программатора, поэтому здесь немного изврата присутствует. Перемычка JP2 предназначена для прошивки нашего устройства и должна быть установлена только во время обновления прошивки устройства(разъем Х2). Диоды D1 и D2 предназначены для задания рабочего напряжения питания ~3.6V. Можно обойтись и одним(проверено неоднократно), хотя при грамотном подходе лучше сделать не так как я=)


Ну а теперь немного по коду программы. Сначала опишем конфигурацию аппаратной части нашего устройства в файле «usbconfig.h»:

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Здесь мы указали, что порт, к которому подключены дифференциальные сигналы D+ и D-, это порт PORTD, а выводы, к которым они подключены, соответсвенно 3 и 2. Частота кварцевого резонатора равна 16 Мгц. Затем мы описали, что мы сами управляем процессом подключения нашего устройства к шине USB. Для этого мы сделали следующее:

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Это видно из схемы: резистор R7, подключенный к выводу 1 порта PORTD. Далее в программе нам это понадобиться для того, чтобы произвести подключение к хосту в момент времени, который нам более всего подходит. (напомню, что Хост определяет наличие подключения устройства к шине в случае подтягивания линии D- к Vdd. Это я для низкоскоростных устройств).


В рекомендации от V-USB сказано, что линия D+ должна быть подключена к INT0, но я внес некоторые изменения и подключил ее к INT1, что в принципе не запрещено (подключают к IN0 т.к. прерывание INT0 имеет наивысший приоритет в системе прерываний AVR. прим. DH), поэтому я указываю на соответствующие изменения в следующих строках:

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

В принципе, в описании аппаратной части USB это все.


В этом же файле мы указываем, что класс и подкласс устройства определяется классом и подклассом интерфейса (это я про то, что мы используем стандартный интерфейс MSD bulk-only). Это делается следующим образом:

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост
Так же мы помним, что мы имеем 2 конечные точки (т.к. мы принимаем и отправляем данные от хоста), значит мы указываем на это библиотеке V-USB:
USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост
Теперь пару слов о следующих определениях:
USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Поскольку мы использовали стандартный класс USB MSD, то и описать устройство это класса обязаны мы. Позже я вернусь к этим строкам, а пока мы оставим их в покое.


В принципе в этом файле вроде как и все, но я оговорюсь для наиболее дотошных (как я=): я не пират и не пытался нарушить чьета права? использовав VID/PID, которые в моем файле usbconfig.h. Мало того, я даже не знаю чье они, просто первые попавшиеся под руку==)


Пожалуй, распишу немного процесс инициализации устройства на V-USB.


Немного выше я определил небольшой макрос USB_CFG_PULLUP_IOPORTNAME в соответствии со схемой, что в свою очередь дало мне возможность производить подключение и отключение от шины USB в произвольные моменты времени. Так вот, для подключения к шине используется макрос


usbDeviceConnect();

при вызове которого происходит подтяжка линии D- к напряжению питания устройства. Хост определяет это событие и начинает процедуру конфигурации устройства USB: Сброс девайса, присвоение адреса и т.д.


Во всей этой рутинной суете главное для нас это этап запроса дескриптора устройства, который в свою очередь содержит поддерживаемую версию USB, максимальный размер пакета для control конечной точки, идентификаторы устройства и производителя VID/PID, версию устройсва, строковые номера индексов(если таковые присутсвуют) и количество конфигураций нас родимых.


Поскольку мы проектируем свое собственное ни на что не похожее устройства, то давайте опишем этот дескриптор (Здесь и далее я рассматриваю файлы «MassStorage.h» и «MassStorage.cpp»)

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост
Помните, выше мы описали #define USB_CFG_DESCR_PROPS_DEVICE. Так вот, определив это, мы сообщили библиотеке V-USB, что используется пользовательский «описатель устройства», и при запросе хостом данной информации V-USB передаст то, что мы с вами только что описали. Мы видим, что я описал в usbDescriptorDevice количество конфигураций устройтва равным 1. Что это значит? Это значит что наше устройство может работать только в одном режиме, который мы определим чуть ниже. Так вот наш режим(или конфигурация, если правильнее):
USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост
USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Хочу отметить, что в дескрипторе кофигурации мы встраиваем дескриптор интерфейса и дескрипторы конечных точек. Этот (или эти, если хотите) дескриптор передается V-USB благодаря ранее описанному определению


#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_LENGTH(32)

В этом же десрипторе (usbDescriptorConfiguration) мы указали, пожалуй, самую важную информацию для нашего устройства, а именно:


   ► устройство класса MSD

   ► тип передачи — bulk-only

   ► размеры конецчных точек и их направление


После того, как хост получил дескрипторы устройства, конфигурации, интерфейса и конечных точек, он (хост) начинает «общаться» с нашим устройством как MSD bulk-only. Поскольку мы работаем со стандартным интерфейсом MSD, то никакие control передачи для control конечной точки нас не интересуют. Вместо этого мы определим функцию 

USB_PUBLIC void usbFunctionWriteOut(unsigned char* ucData, unsigned char ucLen)

которая будет принимать все interrupt/bulk передачи данных от хоста к нашему устройству для всех конечных точек, кроме 0 (это control точка). Напомню, что максимальное количество байт, которое может быть принято через usbFunctionWriteOut за один вызов равно 8 байтам (это ограничение V-USB). Ну вот, теперь мы готовы принимать поступающие от хоста байты =))) И на этом этапе мы перейдем к следующему этапу — разделение потока байт от хоста на вменяемые пакеты, которые несут нам полезную информацию. Как мы узнали ранее, хост может направлять в MSD устройство толька комманды и данные. Теперь мы сделаем следующее: 

   ► разделим входной поток данных на комманды и данные

   ► обработаем комманды в соответсвие с их предназначением или примем данные от хоста

   ► ответим хосту на обработанную комманду (предварительно отправив запрошенные данные, если необходимо)

Для того, чтобы воплотить в жизнь написанное чуть выше, давайте разберемся с несколькими положениями, которые касаются Mass Storage Class в целом и bulk-only в частности. Как я уже оговаривал, Mass Storage Class(MSC) не подразумевает того, что устройство, которое работает согласно этой спецификации, занет что-либо о фойловой системе на своем насителе. Оснойвной задачей такого устройсва является предостваление запрашиваемой информации с носителя в нужном объеме и с нужного адреса. Это, с одной стороны, облегчает работу нам с вами, с другой стороны позволяет строить устройства, не привязанные к конкретным накопителям. Все, что мы должны уметь, это выполнить требуемое хостом действие. А действия эти не так уж и сложны(если не вдаваться во все мелочи данного протокола) — выполнять команды из набора SCSI. Я описал все необходимые из них ранее.


Далее. Раскажу немного о том, как согласно MSC bulk-only происходит обмен информацией между нашим устройством и хостом. Опознав нас свами на шине, сбросив, инициализировав и настроив наше устройство, хост посылает нам комманды в так называемом Command Block Wrapper(CBW). Содержимое этого блока разнится от комманды к команде, но самое главное, размер этого CBW остается неизменным. Это положение позволяет нам принять весь CBW при помощи V-USB не смотря на ограничение в 8 байт. Итак, приняв при помощи функции usbFunctionWriteOut CBW, мы можем выделить из него нужные нам данные, а именно — комманды, отсылаемые на исполнение хостом и параметры, которые зависят от принятой комманды. Наверняка у некоторых появится вопрос: А что же будет, если хост будет часто посылать комманды в наш адрес или мы долго будем на них отвечать??? Вот тут проявляется еще один аспект выбранного нами варианта MSD. Хост не будет посылать в наш адрес следующую комманду до тех пор, пока мы не сообщим о результате выполнения предыдущей(есть нюанс с таймаутом, но в программе для нашего устройства мы это обойдем)!!! Также хост присваевает каждому отсылаемому нам CBW уникальный тэг(или номер), так что мы можем обработать одну комманду и ответить на нее даже в случае если хост не дождался нас и отослал еще чтото в наш адрес. Вы скажете, а если мы зависли? Не беда, попытавшись пару раз и не получив никакого КПД с нашей стороны, хост просто будет нас игнарировать. С другой стороны bulk передача согласно спецификации USB не гарантирует доставку данных конечной точки, так что это дает нам дополнительное время на «ногодрыгание».


Но что-то меня опять понесло в теорию=) Давайте все-таки опишем этот самы загадочный CBW:

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Вроде, на первый взгляд, ничего сложного. Теперь давайте пройдемся по его основным элементам (распишу только самые необходимые, если кому интересно, могу лично и подробнее). dCBWSignature — сигнатура блока CBW. Ничего интересного для нас, просто константа(чтото вроде USBD если смотреть в char. dCBWTag — вот это один из камней приткновения в CBW. Значение этого поля и есть тот самы номер пакета. Позже мы будем использовать это занчение для сообщения хосту орезультате выполнения операции с таким тегом. dCBWDataTransferLength — вроде понятно из названия и указывает на размер передаваемых за данную транзакцию, байт. Никогда и никого не интересовало и врядли будет. bCBWFlags — всевозможные флаги. значений много и интерпритаций еще больше. Просто не обращаем внимания. bCBWLUN — номер логического устройства, которому адресован CBW. У нас вроде одно такое устройство, но если кто будет делать картридер, то может и пригодится =) bCBWCBLength — размер переданного CBW. CBWCB[16] — вот она, полезная информация. Этот массив содержит и номер комманды, и параметры для нее, и многое другое. С этим блоком мы познакомимся позже, когда будем знакомиться с коммандами SCSI.


Мы помним, что в MSD bulk-only все транзакции делятся максинум на три этапа. Так вот, приняли мы CBW и выделили из него нужную нам информацию. Это и есть первый этап: так называемый command transport. Из приведенной блок-схемы выше мы видим, что следующим этапом в нашишем диалоге могжут быть передача данных хосту (либо прием их от него) или передача статуса обработки принятого CBW. Так вот, передача того самого статуса являестя обязательным этапом для любой комманды. Этот этап как бы подтвердает тот факт, что мы приняли от хоста CBW с номером dCBWTag и выполнили ее(вне зависимости от результата ее выполненя). Этот этап называется status transport, а данные передаются определенным блоком, имя которому CSW. Давайте опишем и его:

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Эта небольшая структурка как бы является завершением транзакции MSD вида коммандв->данные->статус. Поля этой структуры означают следующее: dCSWSignature — сигнатура блока CSW (это константа, в char это USBS), dCSWTag — номер блока(должен совпадать с номером CBW, для которого высылается статус), dCSWDataResidue — разности между ожидаемым чилом байт от хоста dCBWDataTransferLength в блоке CBW и реально принятыми(при OUT передаче) и наобоот, между запрошенным чилов байт в dCBWDataTransferLength и переданным хосту. Ну и наконец bCSWStatus — результат выполнения комманды с тегом dCSWTag. Нуль — значит все впорядке, другие значения — смотрим в спецификации =))).


Ну и на последок в этапах транзакций осталась стадия передачи данных(data transport). Напомню, что этот этап не всегда присутствует в процессе общения MSD с хостом. Есть энное количество комманд, которые не требуют передачи данных. Но все же этот этап присутствует и мы его сейчас рассмотрим. Мы знаем, что данные могут передаваться как от хоста к MSD, так и наоборот(мы же помним, что мы описали 2 конечные токи in и out). Так вот, в данной реализации MSD от хоста к MSD могут передаваться только данные для записи на носитель информации, а от MSD к хосту как данные прочитанные с носителя, так и запрашиваемые хостом параметры нашего устройства.


В принципе про этапы передачи информации MSD наверное и все. Теперь я коснусь реализации всего написанного выше. Примем исходное сосояние(назовем его RxCBW)=) Хост нам не передал не байта и мы ожидаем от него CBW. Размер этого блока мы занем, а следовательно первые sizeof(CBW) приятых байт и будут CBW. Как только мы приняли CBW мы начинаем его анализировать. Анализ блока CBW начинается с того, что мы распознаем комманду, которая находиться в USB_MSD_CBW.CBWCB[0]. Значение этого байта и есть комманда, которую хост просит нас выполнить. На этом этапе, в зависимости от предложенной нам комманды, устройство может перейти в одно из нескольких состояний: прием данных от хоста(RxData), передача данных хосту(TxData) или передача статуса(TxStatus). При переходе в состояние RxData мы принимаем от хоста n байт информации, записываем ее на носитель и переходим в состояние TxStatus. При переходе в состояние TxData мы передаем хосту запрошенную информацию n байт и переходим в состояние TxStatus. Из состояния TxStatus, передав блок CSW хосту, переходим в состояние RxCBW и ожидаем новые байты от хоста. Сейчас попробую предстваить это во временной диаграмме.

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Ну как-то так (я понимаю, что не все, наверное, понятно, так что готов ответить на вопросы).

Выложу немного скринов, для разнообразия

USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост
USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост
USB ФЛЕШКА НА ATMEGA8 И V-USB. ОТ ИДЕИ К ГОТОВОМУ УСТРОЙСТВУ… Много букв, Technobrother, Код, Своими руками, Avr, Atmega, Atmega8, Длиннопост

Я так пологаю, что расписывать работу с картой SD(MMC) не имеет смысла, т.к. про это написано очень много. Пожалуй опишу основные грабли, на которые я наступал в этом процессе (так думаю будет логичнее). Так вот, первое(и наверное основное), я не вседа использую внешнюю подтяжку на линии _CS карты памяти, из-за чего иногда возникают довольно большие неприятности. потому (хотя это и не очень красиво) в таких случаях я всегда первым делом настраиваю должным образом вывод _CS. Второе, не все карты, с которыми я работал(а их было не мало, поверьте), подразумевают размер блока для чтения/записи равным 512 байт. Потому при инициализации карты я страхуюсь и устанавливаю размер этого блока 512. Видел пару карт, которые поддерживали размер блока для чтения/записи в 1 байт, а есть, которые тока 2048 и ни грамом больше(тока 1 раз встречал). В данном проекте я использовал карту kingston на 1гб, хотя можно и другие, думаю проблем не возникнет. Третье, не всегда карта памяти инициализируется на максимальной скорости SPI(возможно это зависит и от разводки, использование проводов и много от чего еще), поэтому можно производить инициализацию на меньших скоростях, хотя у меня на 16Мгц все прекрасно работает на максимуме. Четвертое, линия MISO avr'ки. Я раньше не использовал внешнюю подтяжку на этом выводе, от чего поимел много головной боли. Теперь использую всегда, чего и советую начинающим. Наверное это основное, поэтому поедем дальше.


Мы разобрали процесс(или логики) работы нашего MSD. Научились принимать пакеты CBW, отправлять CSW и данные.

Файлы с исходным кодом.

Вроде как все. Если у общественности возникнут вопросы, замечания, пожелания более подробного описания или чего-то еще, то буду рад помочь!


Жду откликов, предложений и т.п. Мот у кого возникнет идея создания устройства на V-USB, то готов поучавствовать в коммандном проекте. Сейчас займусь работой с v-usb и сенсорной панелью вместо мышки=) Всем удачи!


Файлы : mmc_test.zip, MassStorage.Mega8.libusb.zip

Показать полностью 18
Много букв Technobrother Код Своими руками Avr Atmega Atmega8 Длиннопост
8
16
Dionisnation
Dionisnation
9 лет назад

ПОДКЛЮЧЕНИЕ ДИСПЛЕЯ NOKIA 1616 НА ПРИМЕРЕ LPC1343⁠⁠

ПОДКЛЮЧЕНИЕ ДИСПЛЕЯ NOKIA 1616 НА ПРИМЕРЕ LPC1343 Много букв, Код, Technobrother, Lcd дисплей, Nokia, Avr, Своими руками, Длиннопост

Дисплей с подсветкой, имеет разрешение 128х160 пикселей и глубину цвета 18 бит. Размеры примерно 28х36мм. шлейф имеет 12 контактных площадок (1-я и 12-я не подключены) с шагом 0.5мм. Логика вся работает от 3.3В и лучше не завышать. От 5В скорее всего сгорит. На подсветку надо около 7В.

UPD: По правильному на питание цифровой схемы надо подать 1.8В и на аналоговую 2.7В, но всё прекрасно работает и от одного источника 3.3В (уже пол года не сгорело ничего), по даташитам это напряжение в пределах допустимого. Так же в комментариях отмечено что появились дисплеи с 3В подсветкой, мне на днях похоже такой же попался, имейте это ввиду.


Работа с дисплеем аналогична работе с Nokia 6100 (статей на эту тему предостаточно) по тому глубоко вдваться не стану, а сконцентрируюсь на различиях.


Отмечу что мне попадалось 2 разновидности дисплеев, но оба работают с данным кодом. Различить их можно по форме шлейфа. Шлейф в форме буквы T — хороший дисплей, верх будет со стороны шлейфа. Если же шлейф просто прямоугольный выходит, то со стороны шлейфа у вас будет низ и ужасно тусклая подстветка. Не знаю, то ли мне бракованный дисплей попался, толи они все такие. На счет подсветки и качества соврал. Промывал от канифоли плату спиртом, в итоге просто слои рассеивателей и поляризаторов разошлись. Не давайте спиртного дисплею, он спивается быстро! :)


Как подключить


В моём варианте работает следующая схема включения:

ПОДКЛЮЧЕНИЕ ДИСПЛЕЯ NOKIA 1616 НА ПРИМЕРЕ LPC1343 Много букв, Код, Technobrother, Lcd дисплей, Nokia, Avr, Своими руками, Длиннопост

Важно! на данной схеме учтены только «подключенные» выводы, крайние в счет не берутся. Таким образом 1-й вывод на схеме соответствует 2-му на дисплее. 10 вывод схемы — 11-му на дисплее.


Взаимодействие


Данный дисплей, как и большенство других цветных Nokia, для взаимодействия использует интерфейс SPI 9 бит. Возможно взаимодействие в режимах 0 и 3 (если память не изменяет). Успешно работает на скоростях 4Мб/с и 9Мб/с, больше проверять не стал. Линия данных на самом деле у дисплея двунаправленная и по ней можно считать такую информацию как ID контроллера в дисплее, но мы её быдем использовать только для записи.


Старший бит является признаком данных: для команды он равен 0, для данных 1. младшие 8 бит содержат либо сами данные, либо код команды.


Ну и естественно перед работой с дисплеем его надо сбросить. делаеся это выбором дисплея и подачей на вывод Reset низкого уровня в моём случае на 100мс. После снятия сброса надо так же выдержать паузу, что бы дисплей успел инициализироваться.


Перечислять команды дисплея не буду, поскольку сам их не знаю. Но большенство команд едины для разных моделей дисплеев и при желании сможете разобраться сами.


И так, получается следующий набор функций (для LPC1343)

void SPI_init() { // Раздел 13.2 UM10375


// Reset SSP (пункт 4)


LPC_SYSCON->PRESETCTRL &= ~(1<<0); // "маска" сброса SSP


LPC_SYSCON->PRESETCTRL |= (1<<0); // 1 в бит RST_SSP_0



// Enable AHB clock to the SSP domain. (пункт 2)


LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11);



// Divide by 1 (SSPCLKDIV also enables to SSP CLK) (пункт 3)


LPC_SSP->CPSR = 0; // отключим тактирование (а то мало ли)



// Set P0.9 to SSP MOSI


LPC_IOCON->PIO0_9 &= ~(7<<0);


LPC_IOCON->PIO0_9 |= (1<<0); // использовать как вывод MOSI


LPC_IOCON->PIO0_9 |= IOCON_COMMON_MODE_PULLUP;



// Set 2.11 to SSP SCK (0.6 and 0.10 can also be used)


LPC_IOCON->SCKLOC = 1; // SCK на вывод 2.11


LPC_IOCON->PIO2_11 &= ~(7<<0); // сброс текущей функции порта ввода-вывода


LPC_IOCON->PIO2_11 |= (1<<0); // использовать как вывод SCK


LPC_IOCON->PIO2_11 |= IOCON_COMMON_MODE_PULLUP;



// Set P0.2/SSEL to GPIO output and high


LPC_IOCON->PIO0_2 &= ~(7<<0); // сброс текущей функции порта ввода-вывода


LPC_IOCON->PIO0_2 |= (1<<0); // использовать как вывод SSEL (можно обычным GPIO как 0)


LPC_IOCON->PIO0_2 |= IOCON_COMMON_MODE_PULLUP;


LPC_GPIO0->DIR |= 1<<2;


LPC_GPIO0->DATA |= 1<<2;



// If SSP0CLKDIV = DIV1 -- (PCLK / (CPSDVSR X [SCR+1])) = (72,000,000 / (2 x [3 + 1])) = 9.0 MHz


LPC_SSP->CR0 = ( (8<<0) // Размер данных 1000 - 9 бит


| (0<<4) // Формат фрейма 00 - SPI


| (0<<6) // Полярность 0 - низкий уровень между фреймами


| (0<<7) // Фаза 0 - по нарастанию


| (3<<8) // Делитель частоты шины на бит


) ;



// Clock prescale register must be even and at least 2 in master mode


LPC_SSP->CPSR = 2; // пердделитель 2-254 (кратно 2)



// Enable device and set it to master mode, no loopback (разрешаем работу)


LPC_SSP->CR1 = ( (0<<0) // 0 - Loop Back Mode Normal


| (1<<1) // Разрешение работы 1 - разрешено


| (0<<2) // Режим ведущий-ведомый 0 - мастер


);


}



void SPI_send(uint16_t value) {


while ((LPC_SSP->SR & ((1<<1) | (1<<4))) != (1<<1)); // если буффер передачи не переполнен и устройство не занято


LPC_SSP->DR = value;


}



// Вспомогательные макросы


#define LCD_send(x) SPI_send(x)


#define LCD_command(cmd) LCD_send(cmd)


#define LCD_data(data) LCD_send(0x0100|(uint8_t)(data))



void LCD_reset(void) {


// Настройка для вывода Reset дисплея


LPC_IOCON->PIO0_8 &= ~(7<<0); // сброс текущей функции порта ввода-вывода


LPC_IOCON->PIO0_8 |= IOCON_COMMON_MODE_PULLUP;


LPC_GPIO0->DIR |= 1<<8;


LPC_GPIO0->DATA |= 1<<8;


// Настройка для вывода Select


LPC_IOCON->PIO0_2 &= ~(7<<0); // Временно отключаем спецфункцию вывода выбора SPI


delayms(100);


// Сброс дисплея


LPC_GPIO0->DATA &= ~(1<<2); // ncs = 0


LPC_GPIO0->DATA &= ~(1<<8); // nrst = 0


delayms(100);


LPC_GPIO0->DATA |= 1<<8; // nrst = 1


LPC_GPIO0->DATA |= 1<<2; // ncs = 1


delayms(100);


// Возврат спецфункции


LPC_IOCON->PIO0_2 |= (1<<0); // использовать как вывод SSEL


}

В этих функциях по сути собран весь аппаратно-зависимый код. именно по этой причине функция LCD_reset включена сюда, хотя правильнее её описать в следующем разделе. Я использовал «фоновый вывод данных», так функция SPI_send сначала ожидает окончания вывода предидущего байта (9 бит), затем помещает очередной байт (9 бит) на вывод и возвращается не ожидая завершения операции вывода.


Важно: Линию выбора дисплея CS обязательно надо периодически освобождать, иначе вывода никакого не будет, получите просто белый экран. У меня используется полностью аппаратный контроль.


Инициализация дисплея


Идем по пути найменьшего сопротивления, и одалживаем у тов. Rossum’а код для работы с дисплеями Nokia из проекта NokiaSuperBreakout. Не беда что нашего дисплея нет в перечислении, берём тот что соответствует диспею 132х160 контроллер SPFD54124B.


Данный код настраивает дисплей на 16-битный индексный режим вывода, в итоге получаем формат BGR 5-6-5. по биту глубины на R и B мы теряем, но зато получаем возможность передавать только 2 бата на один пиксель, взамен 3-х в 18битном режиме.


Перед инициализацией надо не забыть сбросить дисплей (иногда критично).

const uint16_t init_lcd1616ph[] = {


0xBA, 0x107, 0x115, // Data Order


0x25, 0x13F, // Contrast


0x11, // Sleep Out


0x13, // Display Normal mode



0x37,0x100, // VSCROLL ADDR


0x3A,0x105, // COLMOD pixel format 4=12,5=16,6=18


0x29, // DISPON


0x20, // INVOFF


0x13 // NORON


};



void LCD_init()


{


const uint16_t *data = &init_lcd1616ph[0];


uint16_t size = sizeof(init_lcd1616ph)/sizeof(init_lcd1616ph[0]);


while(size--) {


LCD_send(*data++);


}


LCD_command(0x2D);


int i;


for (i = 0; i < 32; i++)


LCD_data(i<<1);


for (i = 0; i < 64; i++)


LCD_data(i);


for (i = 0; i < 32; i++)


LCD_data(i<<1);


delay(100);


m_lcdResetClip();


EndDraw();


SetFont(0);


}

Про m_lcdResetClip, EndDraw и SetFont потом.


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



Вывод графики



Принцип вывода у всех встреченных мной дисплеев один. Вначале передается команда выбора диапазона строк, затем диапазона столбцов, после чего попиксельно выводятся пиксели в получившееся окно. Таким образом для вывода изображения в области [ x1:y1, x2:y2 ] надо передать следующую последовательность:


[PASET] [y1] [y2] [CASET] [x1] [x2] [RAMWR] [pixel_1] [pixel_2]… [pixel_N]


Однако, в отличии от 6100 дисплей для 1616 каждая из величин координат (x1, x1, y1, y2) имеет 2-хбайтовый размер, не смотря на то, что старший байт всегда нулевой. Контроллер дисплея сам будет переносить «курсор» вывода в окне на следующую строку вывода, при достижении правой границ окна. Направление заполнения слева-направо, сверху вниз. Удобно. Ну и немаловажный фактор: левый верхний угол имеет координату x:y = 2:1.


Таким образом получаем что на операцию вывода требуется передать 11 служебных байт плюс 2хN байт данных. Естественно получаем что выгоднее выводить прямогольными областями по несколько пикселей за раз.


Ну а теперь к ложке дегтя. К сожалению при передаче координат «вне экрана» предсказать поведение дисплея нельзя. Он вроде как и «закольцован» на размер в 256 байт, но артефакты попадаются порой очень странные. По этому у вас есть выбор: либо не передавать координаты вне экрана, либо делать програмное отсечение. Я выбрал второй вариант и вот что из этого получилось:

// Nokia1616


#define displayOffsetX 2


#define displayOffsetY 1


#define displayWidth 128


#define displayHeight 160



#define RGB(r, g, b) (((uint32_t)(R))|((uint32_t)(g)<<8)|((uint32_t)(b)<<16))


#define RECT_set(rect, l, t, r, b) { (rect).left = (l); (rect).top = (t); (rect).right = (R); (rect).bottom = (b); }



// Описание переменных


RECT m_lcdBound; // Установленная для вывода область


POINT m_lcdOutput; // Очередная позиция для вывода


RECT m_lcdClip; // Размеры области отсечения


uint8_t m_lcdClipOutput; // Активны ли отсечения в текущей итерации вывода



uint32_t BeginDraw(int16_t left, int16_t top, uint16_t width, uint16_t height)


{


int16_t right = left + width - 1;


int16_t bottom = top + height - 1;


if( left >= m_lcdClip.left && top >= m_lcdClip.top && right <= m_lcdClip.right && bottom <= m_lcdClip.bottom ) { // RectInRect


// область вывода полностью видима, используем "быстрый" вывод без проверок отсечения


m_lcdClipOutput = 0;


} else {


// область вывода частично либо полностью невидима на дисплее, используем вывод с проверкой отсечений


m_lcdClipOutput = 1;


m_lcdOutput.x = left;


m_lcdOutput.y = top;


RECT_set(m_lcdBound, left, top, right, bottom);


if(left < m_lcdClip.left) left = m_lcdClip.left; // ClipRect


if(top < m_lcdClip.top) top = m_lcdClip.top;


if(right > m_lcdClip.right) right = m_lcdClip.right;


if(bottom > m_lcdClip.bottom) bottom = m_lcdClip.bottom;


}


if( left > right || top > bottom ) { // IsRectValid


// область не видна на дисплее, завершаем вывод


EndDraw();


return 0;


}


uint32_t count;


// Устанавливаем "виртуальные" границы вывода


LCD_command(0x2A); //LCD_command(CASETP);


count = right - left + 1;


left += displayOffsetX;


right += displayOffsetX;


LCD_data(left>>8);


LCD_data(left);


LCD_data(right>>8);


LCD_data(right);


// Диапозон строк


LCD_command(0x2B); //LCD_command(PASETP);


count *= (bottom - top + 1);


top += displayOffsetY;


bottom += displayOffsetY;


LCD_data(top>>8);


LCD_data(top);


LCD_data(bottom>>8);


LCD_data(bottom);


LCD_command(0x2C); //LCD_command(RAMWR);


// Возвращаем количество видимых пикселей


return count;


}



void EndDraw()


{


m_lcdClipOutput = 1;


m_lcdBound.right = m_lcdBound.left - 1; // SetRect


}



void NextPoint(uint32_t color)


{


// Надо ли проверять отсечения при выводе


if( m_lcdClipOutput ) {


int16_t x = m_lcdOutput.x;


int16_t y = m_lcdOutput.y;


// учит.отсеч.


//if(!m_lcdClip.width /* || !m_lcdClip.height */) return;


if(m_lcdBound.right < m_lcdBound.left) { // IsRectValid вывод недоступен


return;


}


// Смещение на следующую позицию вывода


if( m_lcdOutput.x >= m_lcdBound.right ) {


// Если в конце строки - переходим на следующую


m_lcdOutput.x = m_lcdBound.left;


if( m_lcdOutput.y >= m_lcdBound.bottom ) {


// Если последняя точка, переходим в начало (или можно завершить вывод вызовом EndDraw)


m_lcdOutput.y = m_lcdBound.top;


} else {


m_lcdOutput.y++;


}


} else {


m_lcdOutput.x++;


}


if(!(x >= m_lcdClip.left && x <= m_lcdClip.right && y >= m_lcdClip.top && y <= m_lcdClip.bottom) ) { // PtInRect


return;


}


}


// точка будет видимой


uint8_t r = color;


uint8_t g = color>>8;


uint8_t b = color>>16;


LCD_data((r&0xF8)|(g>>5));


LCD_data(((g<<3)&0xE0)|(b>>3));


}

Данные функции являются «дисплей ориентированными» и могут быть изменены для работы с другим дисплеем (естественно не забыв и про функцию инифиализации).


Код получился громадным исключительно из-за наличия програмного отсечения, без него всё получается в разы меньше и просто сводится к последовательному вызову функций записи комманд и данных.


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


Функция вывода очередной точки NextPoint должна выполнить некоторые проверки и расчеты, тут нам позволит хорошо ускорить процесс использование фонового вывода на дисплей: пока по SPI передаются данные, мы проводим свои проверки для следующей точки.


Ну а функция завершения вывода просто задает недействительную область. При желании и этого можно было не делать, но вдруг появится дисплей, которому требуется что-либо сказать по окончании? Не переписывать же потом весь код.


Ну и для завершения картины средства для работы с отсечениями:

typedef struct _tagPOINT {


int16_t x;


int16_t y;


} POINT, *PPOINT;



typedef struct _tagRECT {


int16_t left;


int16_t top;


int16_t right;


int16_t bottom;


} RECT, *PRECT;



void m_lcdSetClip(const RECT *r)


{


// Проверяем на видимость отсечения


RECT_set(m_lcdClip, r->left, r->top, r->right, r->bottom);


// Устанавливаем "абсолютное" ограничение для вывода c усечением до границ дисплея


if(m_lcdClip.left < 0) m_lcdClip.left = 0; // ClipRect


if(m_lcdClip.top < 0) m_lcdClip.top = 0;


if(m_lcdClip.right >= displayWidth) m_lcdClip.right = displayWidth - 1;


if(m_lcdClip.bottom >= displayHeight) m_lcdClip.bottom = displayHeight - 1;


// Is clip valid


if(m_lcdClip.bottom < m_lcdClip.top || m_lcdClip.right < m_lcdClip.left) { // IsRectValid


// invalid clip region


RECT_set(m_lcdClip, 0, 0, -1, -1);


}


}



void m_lcdResetClip()


{


RECT_set(m_lcdClip, 0, 0, displayWidth - 1, displayHeight - 1);


}

Примитивы


Самое простое пожалуй это закрасить область одним цветом.

void Fill(int16_t left, int16_t top, uint16_t width, uint16_t height, uint32_t color)


{


uint32_t count;


count = BeginDraw(left, top, width, height); // Функция возвращает количество видивых пикселей в установленной области вывода.


m_lcdClipOutput = 0; // Принудительно меняем функцию вывода, выводим только необходимое количество пикселей


while(count--) {


NextPoint(color);


}


EndDraw();


}



void Clear(uint32_t color)


{


Fill(0, 0, displayWidth, displayHeight, color);


}



void Pixel(int16_t x, int16_t y, uint32_t color)


{


Fill(x, y, 1, 1, color);


}

А проверяется всё это дело так:

SPI_init();


LCD_reset();


LCD_init();


Clear(0x00000000);


Fill(10, 20, 30, 40, 0x00FF00FF);

Показать полностью 2
Много букв Код Technobrother Lcd дисплей Nokia Avr Своими руками Длиннопост
22
43
Dionisnation
Dionisnation
9 лет назад

ДИСПЛЕЙ 3.7 дюйма ОТ ТЕЛ. HTC A8181 для DIY электроники⁠⁠

Всем привет) И так, я вернулся после 2-х недельного бана и принес немного полезной инфы.

ДИСПЛЕЙ 3.7 дюйма  ОТ ТЕЛ. HTC A8181 для DIY электроники Technobrother, Avr, Arduino, Микроконтроллеры, Дисплей, Своими руками, Длиннопост
Тем ребяткам которые очень хотят использовать нормальные дисплеи, предлагаю вам побаловать своего внутреннего перфекциониста: Дисплей от тел. HTC A8181 диагональ 3.7 » разрешение 480х800, есть два вида такого дисплея, как TFT так и AMOLED, отличаются глубиной цвета и немного питанием по тому пин то пин не совместимы. Намного дешевле чем брать какие то заводские по причине того что массовость играет серьезную роль в цене.

Купить TFT можно за $9.25
Предлагаю сопутствующие фото и .PDF

ДИСПЛЕЙ 3.7 дюйма  ОТ ТЕЛ. HTC A8181 для DIY электроники Technobrother, Avr, Arduino, Микроконтроллеры, Дисплей, Своими руками, Длиннопост
ДИСПЛЕЙ 3.7 дюйма  ОТ ТЕЛ. HTC A8181 для DIY электроники Technobrother, Avr, Arduino, Микроконтроллеры, Дисплей, Своими руками, Длиннопост
п.с. На фото два примера, отличаются TFT от AMOLED наличием дополнительного маленького шлейфа для питания светодиодной подсветки. Лично я себе купил TFT но у меня пока есть и рабочая лошадка с AMOLED, вскоре будет с чем поиграться.

AMS369FG03-002_Rev2_0_20090603_201210156706.pdf - https://vk.com/doc-50664262_437108999
ACX425AKM_Ver0_4_20100624_201306185709.pdf - https://vk.com/doc-50664262_437108998
Показать полностью 3
Technobrother Avr Arduino Микроконтроллеры Дисплей Своими руками Длиннопост
19
480
positroid
positroid
9 лет назад

Новогодняя елка из светодиодов⁠⁠

До нового года осталось меньше двух недель, а новогоднего настроения не наблюдается? Нужно срочно сделать что-то электронно-новогоднее, со светодиодами и ассемблером. Забегая вперед, вот что у меня вышло:

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

Как это все собиралось? Сначала в уме была продумана схема, соединение, размеры и прочее. В ближайшем магазине были куплены необходимые детали:

- микроконтроллер - Attiny24A;

- панель под микроконтроллер;

- светодиоды - 25 шт. (24 зеленых и 1 красный);

- MOSFET-транзисторы - 4 шт. - IRLML2502TR;

- резисторы 0.125 Вт (3 шт. - 1 кОм, 3 шт. - 1 Ом, 1 шт. - 220 Ом); 

- кнопки - 2 шт.;

- микропереключатель - 1 шт.;

- гнездо microUSB - 1 шт;

- односторонний фольгированный текстолит 11х5 - 1 шт.


Далее в программе Sprint Layout была разведена печатная плата:

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

Методом ЛУТ она была перенесена на текстолит:

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

Далее плата была протравлена в растворе лимонной кислоты и перекиси водорода, с добавлением соли как катализатора (100 мл  3% перекиси, 30 г лимонной кислоты, соль по вкусу). После лужения, просверливания отверстий и запайки основных компонентов плата стала выглядеть следующим образом:

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост
Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

Дело осталось за самым главным - светодиодами. Все оказалось не так сложно, как я предполагал. На листе бумаги была начерчена схема будущей елки, и по ней согнуты ножки светодиодов (плюс вниз, минус к центру):

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

Так как питание елки планировалось от USB (Напряжение 5В, как известно), светодиоды нужно было подключать последовательно по 2 штуки (падение напряжения на одном светодиоде ~2.5В), то есть всего 12 веток светодиодов, соединенных параллельно.

В высоту елка, не считая верхний - 4 светодиода. Поэтому разделил ее на 2 яруса - верхний и нижний.  Все светодиоды согнуты, обрезаны лишние ножки, для удобства пайки (из упаковки оригинальной arduino из Италии, на минуточку) была сделана такая приспособа:

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

Не знаю, насколько без нее бы затянулся весь процесс, но она в разы все ускорила. Собран первый ярус:

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

На заднем плане виден светодиод с прикрученным резистором - это такой пробник. Пока мне второй месяц идет тестер, обхожусь такой штукой). Ну и окончательно собрана вся конструкция:

Новогодняя елка из светодиодов Своими руками, Ёлки, Новый Год, Светодиоды, Avr, Микроконтроллеры, Длиннопост

Конструкция собрана, но чтобы заставить ее работать, нужна еще и программа. Программа писалась в Atmel Studio на ассемблере, получилось 4 группы светодиодов - верхний красный светодиод и 3 группы зеленых светодиодов. Запрограммировано несколько режимов мигания:

1. Все горят.

2. Все мигают.

3. Красный горит, группы загораются по часовой стрелке.

4. Все мигают 2 раза и меняются по часовой стрелке.

5. Красный горит, группы загораются против часовой стрелки.


Видео работы сего девайса пока могу только ссылкой.


Также была изготовлена подставка - из остатков ДСП от установки дверей и куска тонкого пенопласта (вырезан из подложки, в которую запаковывают в магазинах всякие развесные продукты).


В целом это мой первый опыт работы с микроконтроллерами (исключая мигание светодиодами), но результатом доволен. 

Не обошлось и без ошибок - в процессе пострадал 1 микроконтроллер, 1 микропереключатель (возможно, бракованный попался), 1 гнездо microUSB. Текстолит слишком тонкий (1мм) - повело винтом после нагрева. Неправильно  были подключены кнопки (пришлось фиксить разрезанием дорожек и пайки навесным монтажом), зачем-то поставил две, хотя используется только одна.


Все это было сделано меньше чем за неделю, по вечерам в свободное от работы время. Фоткал на старенький китайский Star S5, качество соответствующее.


Надеюсь получилось доступнее, чем рисовать сову, всех с Наступающим!


Код прошивки.

Сама прошивка (вдруг кто захочет повторить).

Показать полностью 9
[моё] Своими руками Ёлки Новый Год Светодиоды Avr Микроконтроллеры Длиннопост
129
Посты не найдены
О Нас
О Пикабу
Контакты
Реклама
Сообщить об ошибке
Сообщить о нарушении законодательства
Отзывы и предложения
Новости Пикабу
RSS
Информация
Помощь
Кодекс Пикабу
Награды
Команда Пикабу
Бан-лист
Конфиденциальность
Правила соцсети
О рекомендациях
Наши проекты
Блоги
Работа
Промокоды
Игры
Скидки
Курсы
Зал славы
Mobile
Мобильное приложение
Партнёры
Промокоды Biggeek
Промокоды Маркет Деливери
Промокоды Яндекс Путешествия
Промокоды М.Видео
Промокоды в Ленте Онлайн
Промокоды Тефаль
Промокоды Сбермаркет
Промокоды Спортмастер
Постила
Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии