- PVSM.RU - https://www.pvsm.ru -
Потребовалось мне как то прошить на необитаемом острове контроллер. Благо был под рукою ноутбук и я подумал, что просто кнопками щелкать [1] — это не метод настоящего джедая. Но это шутка. Девайс можно использовать и для описанных выше целей, но создавался он по другой причине. Иногда в обеденный перерыв очень хотелось что-либо поделать с исследуемыми устройствами (например LCD-дисплеем). Проблема состояла в том, что на компьютер невозможно установить какие-либо драйвера — нужно звать администратора и объяснять цель всех этих установок.
Но USB это не только поточные устройства (так называемые CDC [2]), но еще и HID и Mass Storage. А HID-драйвер установлен уже по умолчанию. Поэтому решено было сделать HID-устройство, с возможностью вывода и ввода через порты контроллера.
Вечер потратил, что бы составить схему.
Развязка именно такая. Пара диодов D1 и D4 понижают напряжение питания примерно 3.8 — 4 вольт. Это предусмотрено для конструкций, имеющих напряжение питания ниже 5ти вольт. Стабилитрончики D2 и D3 занимаются тем же, ограничивая агрессивное напряжение пятивольтовой шины. Больше в конструкции нет ничего интересного, на что следовало бы обратить внимание.
Я делаю это не для продажи, поэтому заморачиваться с травлением плат вообще не стал. Просто купил так называемую растровую плату с дырками и собрал не ней. Снизу сделал гребенку для возможности использования конструкции на breadboard. Их получил, раскурочив панельку для установки микросхемы. Все это заняло еще один вечер. Обратную сторону я прикрыл пластиковым мягким материалом, что бы исключить случайного касания с другими элементами на breadboard.

А вот написание кода уже заняло время… Изобретать велосипед я не стал, просто взяв за основу готовый проект реализации v-usb [3]. Но не каждый дескриптор будет работать, как задумывалось и тем более с ходу. Помучав пару программ для автоматического составления дескриптора и не получив нужного результата, пришлось изучать рекомендации форума исполнителей USB [4].
Через две недели я уже мигал светодиодами на доске и возил все это железо на работу.
А еще через пару дней уперся в неприятный момент: на компьютере не оказалось ни одной среды разработки. Зато имелась установленная Java (JRE). И перерыв в тот день потратил на то, чтобы найти описание как правильно писать нативную dll к Java для управления HID. И тут случайно я нашел один просто обалденный продукт. Точнее статью [1]. Но описание меня очень заинтересовало.
Вечером я уже экспериментировал с Java-классами, пытаясь мигать лампочками. Увы, библиотека позволяла работать только с фьючерами. А просто репорты выбрасывали исключения. Связался с разработчиком. Парень пообещал помочь. Но все те, кто говорит на русском, имеют плохую память. Поэтому подождав пару дней до наступления выходных, переписал firmware микроконтроллера на работу с фьючерами и приступил к конвертации с С++ кода для моего дисплейчика. Конечно, скорость оставляет желать лучшего, но это тоже интересный вариант. Ведь мне нужно только подобрать управляющие коды к дисплею, помигать лампочками, переключить пару релюшек или (если совсем плохо на необитаемом острове [1]) зашить случайно микроконтроллер. Тем более у меня не стоит задача управлять реактором, где за доли секунды можно проморгать цепную реакцию.
И так, что конкретно можно программно менять в контроллере:
Есть, правда, еще одна команда, но для единичного устройства она не потребуется.
Ну и далее представлен класс, который должен выполнять работу обмена.
public class DSHIDBr extends HIDCommunication {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
System.out.println("finalize");
if (isOpened())
CloseHIDDevice();
}
};
public static final String DATE_FORMAT_NOW = "HH:mm:ss.nnn";
public Calendar cal;
protected SimpleDateFormat sdf;
public DSHIDBr(){
cal = Calendar.getInstance();
sdf = new SimpleDateFormat("HH:mm:ss.SSS");
}
public final static byte DS_CMD_DEV_VERSION = (byte) 254;
public final static byte DS_CMD_PORTC = 0;
public final static byte DS_CMD_DDRC = 1;
public final static byte DS_CMD_PORTB = 2;
public final static byte DS_CMD_DDRB = 3;
public final static byte DS_CMD_UDR = 4;
public final static byte DS_CMD_BRRL = 5;
public final static byte DS_CMD_BRRH = 6;
public final static byte DS_CMD_UCSRA = 7;
public final static byte FOOT28C = 32;
public final static byte FOOT27C = 16;
public final static byte FOOT26C = 8;
public final static byte FOOT25C = 4;
public final static byte FOOT24C = 2;
public final static byte FOOT23C = 1;
public final static byte FOOT19B = 32;
public final static byte FOOT18B = 16;
public final static byte FOOT17B = 8;
public final static byte FOOT16B = 4;
public final static byte FOOT15B = 2;
public final static byte FOOT14B = 1;
public byte SendCommand(byte Command, byte Value) {
short /*MaxWriteLength,*/ FeatureReportLength;
/* Check if HID device opened */
if (isOpened() == false) {
return HID_DEVICE_NOT_OPENED;
}
/* Read the Feature Report Length this must be as mentioned in Hid Report descriptor + 1 (Report ID) */
FeatureReportLength = GetFeatureReportLength();
byte[] Outpacket = new byte[FeatureReportLength];
/* We don't use ReportID set it to '0' */
Outpacket[0] = 0;
/* Load the useful command number */
Outpacket[1] = Command;
Outpacket[2] = Value;
/* Write TX buffer via SetReport(Feature) requst */
byte Status = SetFeatureReport(Outpacket, FeatureReportLength);
return Status;
}
public byte readValue;
public byte ReadCommand(){
short /*MaxWriteLength,*/ FeatureReportLength;
/* Check if HID device opened */
if (isOpened() == false) {
return HID_DEVICE_NOT_OPENED;
}
/* Read the Feature Report Length this must be as mentioned in Hid Report descriptor + 1 (Report ID) */
FeatureReportLength = GetFeatureReportLength();
byte[] buffer = new byte[FeatureReportLength];
buffer[0] = 0;
byte Status = GetFeatureReport(buffer);
if (buffer.length > 0)
readValue = buffer[1];
return Status;
}
public String now() {
return sdf.format(cal.getTime());
}
}
Основных функций не много. Инизиализация, финализация, посылка байта и прием байта. Есть еще одна, вспомогательная. Возвращающая текущее время с точностью до миллисекунд. Зачем она? Для протоколирования. Самое главное в работе — это логи. А логи без точного времени могут помочь мало.
Ну и для самых терпеливых, кто умудрился добраться до конца, публикую ссылочку на фирмваре [5]. Она, правда, на рапиде. A в добавок сами проектики на Java [6].
Автор: svd71
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/diy-ili-sdelaj-sam/15951
Ссылки в тексте:
[1] просто кнопками щелкать: http://habrahabr.ru/post/152052/
[2] CDC: http://igorkov.org/?Statmzi:Rabota_s_samodelmznymi_USB_ustroistvami_bez_draiverov
[3] v-usb: http://www.obdev.at/products/vusb/index-de.html
[4] форума исполнителей USB: http://www.usb.org/developers/hidpage/
[5] фирмваре: http://www.rapidshare.ru/2893272
[6] проектики на Java: http://www.rapidshare.ru/2893281
Нажмите здесь для печати.