Главная » Статьи » Полезная информация |
Организуем программный USB в Bascom-AVR на примере USB-вольтметра. Часть 3
автор Aleks8383: Что для этого нужно, конечно же PureBasic который нетрудно найти в сети и скачать, у меня установлена версия 4.51. Также понадобится библиотека HID_Lib предназначена для работы с USB HID устройствами, скачать можно тут. Скачиваем распаковываем и копируем по папкам в PureBasic. Также желательно скачать русский хелп, будет проще разбираться в компиляторе, скачать можно тут Теперь собственно можно писать программу, начнём! Для начала нужно создать окошко программы, делаем это так. OpenWindow(0, 497, 191, 565, 404,"USB Вольтметр", #PB_Window_MinimizeGadget | #PB_Window_SizeGadget) Repeat Event = WaitWindowEvent() Until Event=#PB_Event_CloseWindow Нажимаем F5 и смотрим что получилось Разберём что к чему команда OpenWindow(..) как видно из названия открывает окно. Далее в нутрии скобок 0, 497, 191, 565, 404, "USB Вольтметр", #PB_Window_MinimizeGadget | #PB_Window_SizeGadget, 0 это номер окна, идентификаторы по которому будет отслеживаться события в этом именно окне. Цифры 497, 191 определяют в каком месте экрана появится окошко(в пикселях), а цифры 565, 404 это размер окна по вертикали и горизонтали. "USB Вольтметр" тут и так всё понятно, это заголовок в верху окошка, далее идут #PB_Window_MinimizeGadget | #PB_Window_SizeGadget первый параметр позволяет свёртывать окошко, а второй позволяет изменять размер окна мышкой. Какие ещё параметры к окошку добавлять можно посмотреть в хелпе (надеюсь русский хелп скачали). Смотрим далее идёт цикл Repeat Until, для чего он, а для того чтобы окошко не закрылось, ведь выполнив команду OpenWindow(..) нечего будет больше исполнять и окошко закроется, для этого и вводится цикл в котором будем отслеживать события происходящие в окошке командой Event=WaitWindowEvent() и если произошло событие, в данном случае нажали «крестик» т.е. Event=#PB_Event_CloseWindow тем самым мы выполнили условие выхода из цикла и закроем окошко. Зайдём немного вперёд и рассмотрим как вообще устроен принцип обработки каких либо событий в PureBasic. В PureBasic`е окном называют собственно окно, как оно есть в понимании любого пользователя современной операционной системы. А гаджет - это любой элемент графического интерфейса пользователя (GUI), например кнопка, строка текста, гиперссылка, картинка и т.д. Все гаджеты должны располагается в окне, поэтому чтобы написать приложение с графическим интерфейсом сперва надо создать окно, а потом в них устанавливаем различные гаджеты. Чтобы отследить нажатие кнопок или каких ещё действий в окне нужно отслеживать события происходящих с ними для этого есть несколько команд, вот несколько из них #PB_Event_Gadget отслеживает события в гаджетах #PB_Event_Menu отслеживает события в меню окна #PB_Event_Timer отслеживает события таймера Можно сказать это что-то наподобие прерывания в контроллерах. Продолжим с написанием программы. Добавил кнопки переключения пределов и окошки в которых будет отображаться измеренное напряжение и предел измерения. ButtonGadget(10, 350, 40, 140, 100, "10") ButtonGadget(20, 350, 160, 140, 100, "20") ButtonGadget(30, 350, 280, 140, 100, "200") StringGadget(40, 40, 40, 100, 100, "", #PB_String_ReadOnly) SetGadgetFont(40,FontID(1)) StringGadget(50, 40, 160, 100, 100, "", #PB_String_ReadOnly) SetGadgetFont(50,FontID(1)) TextGadget(60,280,10,100,30,"") ButtonGadget - это гаджет кнопки, а StringGadget - гаджет окошка для текста TextGadget - гаджет для текста (будет выводить надпись если неподключено устройство) SetGadgetFont - устанавливает шрифт в гаджете,в данном случае в StringGadget. Его мы расмотрим попозже. Тут всё по аналогии с окошком, идентификатор по нему мы будем отслеживать нажатие именно этого гаджета, а не какого либо другого. Также как и в окошке определяется место где будет располагаться гаджет только уже не на экране, а внутри окошка, далее её размеры и наконец в скобочках то что будет написано внутри гаджета. Как видно большинство гаджетов сделано по одному принципу, идентификатор, место положения, размер, надпись и дополнительные флаги для каждого гаджета(какие именно смотрим хелп). Жмём F5 и смотрим, что у нас получилось. Теперь у нас есть кнопки и окошки для вывода информации, осталось сделать, чтобы они выполняли требуемые от них действия. Repeat Event=#PB_Event_Timer If EventTimer() FindDevice_Timer() EndIf Event=#PB_Event_Gadget Select EventGadget() Case 10 SetGadgetText(50,"10") OutBytes(1) = 3 OutBytes(2) = 10 SendDevice() Case 20 SetGadgetText(50,"20") OutBytes(1) = 3 OutBytes(2) = 20 SendDevice() Case 30 SetGadgetText(50,"200") OutBytes(1) = 3 OutBytes(2) = 200 SendDevice() EndSelect Event=WaitWindowEvent() Until Event=#PB_Event_CloseWindow Добавим эти строки в имеющийся у нас цикл. Рассмотрим поподробнее, здесь мы добавили строку Event=#PB_Event_Timer здесь мы при срабатывании таймера (о нём немного попозже) мы переходим в процедуру(о них тоже попозже) FindDevice_Timer(), а вот далее как раз идёт работа с кнопками. Event=#PB_Event_Gadget Select EventGadget() Case 10 SetGadgetText(50,"10") OutBytes(1) = 3 OutBytes(2) = 10 SendDevice() Case 20 SetGadgetText(50,"20") OutBytes(1) = 3 OutBytes(2) = 20 SendDevice() Case 30 SetGadgetText(50,"200") OutBytes(1) = 3 OutBytes(2) = 200 SendDevice() EndSelect Здесь при при нажатии на кнопку происходит событие гаджета и как только оно произошло мы при помощи Select EventGadget() (тоже самое что и Select Case в Баскоме) выбираем какое именно гаджет «сработал» те Case 10 это кнопка 10 вольт (10 это идентификатор кнопки ButtonGadget(10, 350, 40, 140, 100, "10"), кстати ставить цифры в идентификатор хоть и не запрещено но лучше не использовать, а использовать команду Enumeration, о чём можно почитать в небольшом учебнике Далее идёт команда SetGadgetText(50,"10") как видно из названия мы устанавливаем гаджете под номером 50 текст 10 те в нижнем окошке высветится цифра 10 это самым мы укажем текущий предел измерения. Смотрим дальше идут команды OutBytes(1) = 3 OutBytes(2) = 10 Это массив для передачи данных первый бит это цифра 3 для передачи в контроллер, а второй бит передаёт предел выбранный в программе в контроллер (о них я уже упоминал когда описывал программу контроллера), далее командой SendDevice() вызываем процедуру в которой мы передаём данные в контроллер. Вот в принципе и всё с обработкой нажатия кнопок. Теперь поговорим о процедурах, они сильно похожи на подпрограммы по подробнее о них можно прочитать в учебнике (ссылка выше по тексту). Процедур в программе у нас две это FindDevice_Timer() и SendDevice() в первой мы отслеживаем подключено у нас устройство компьютеру или нет, а во второй мы передаём данные в компьютер. Прежде чем приступить к их рассмотрению нужно сказать что они как и подпрограммы в Баскоме должны декларироваться в начале программы что мы и делаем
Declare FindDevice_Timer() Declare SendDevice() Начнём с FindDevice_Timer() эта процедура обрабатывается по срабатыванию таймера который включается вот этой командой AddWindowTimer(0, 1, 200) где 0 это номер окна в котором будет работать таймер, далее 1 это номер самого таймера, а 200 это время в миллисекундах через которое будет происходить срабатывание таймера. Procedure FindDevice_Timer() Static Old_Test Test=HID_Lib_DeviceTest(#USB_PID, #USB_VID) If Test<>Old_Test Old_Test=Test If Test HID_Lib_CloseDevice(R_DeviceHandle) : HID_Lib_CloseDevice(W_DeviceHandle) W_DeviceHandle=HID_Lib_OpenDevice(#USB_PID, #USB_VID) R_DeviceHandle=HID_Lib_OpenDevice(#USB_PID, #USB_VID) SetGadgetText(60,"") Else HID_Lib_CloseDevice(R_DeviceHandle) : HID_Lib_CloseDevice(W_DeviceHandle) R_DeviceHandle=0 : W_DeviceHandle=0 SetGadgetText(60,"Устройство неподключено") EndIf EndIf EndProcedure Сначала обратим внимание на #USB_PID, #USB_VID это индивидуальные идентификаторы вашего устройство, про них я писал в описании программы для контроллера. Можно их записать цифрами, а можно объявив их константами в начале программы и добавлять их по ходу программы. Добавим их в начале программы. #USB_PID=$EF01 #USB_VID=$AAAC Далее нужно объявить переменные чтобы они были доступны в разных процедурах W_DeviceHandle, R_DeviceHandle что мы и делаем. Global R_DeviceHandle, W_DeviceHandle Далее в процедуре HID_Lib_CloseDevice(R_DeviceHandle) : HID_Lib_CloseDevice(W_DeviceHandle) W_DeviceHandle=HID_Lib_OpenDevice(#USB_PID, #USB_VID) R_DeviceHandle=HID_Lib_OpenDevice(#USB_PID, #USB_VID) SetGadgetText(60,"") Здесь мы проверяем подключено устройство к компьютеру, если VID и PID идентификаторы соответствуют нашим значением то наше устройство подключено и мы ставим текст в текстовый гаджет под номером 60, а вернее убираем слово в окошке «Устройство не подключено». Ну а если VID и PID не совпадают переходим в другой кусок условия где мы обнуляем переменные VID и PID и выводим надпись «Устройство не подключено». Перейдём теперь к процедуре SendDevice() в которой мы передаём данные в контроллер. Она у нас вызывается в обработке нажатия кнопок командой SendDevice().Посмотрим на нашу процедуру Procedure SendDevice() Shared OutBytes() If W_DeviceHandle HID_Lib_WriteDevice(W_DeviceHandle, @OutBytes(), 9) EndIf EndProcedure Первым делом мы должны в этой процедуре объявить что мы будем работать с массивом OutBytes() (к стати нужно в начале этот массив объявить Dim OutBytes.c(8)) так как переменная или массив объявленный вне процедуры не будут в ней работать, и так объявляем массив в процедуре Shared OutBytes(). Ну а далее передаём данные в контроллер, стоит отметить, что нужно указывать на один больше байт чем нам нужно те в данном случае мы передаём 8 байт, а указываем 9. Специфика библиотеки. На этом с этой процедурой всё. Но как мы можем заметить что у нас есть ещё одна процедура ReadDevice_Thread; это процедура работающая с параллельном потоке или если попроще сказать в фоновом режиме. В ней мы принимаем данные от контроллера и выводим их на экране (в окошке). Сначало нужно создать этот поток что мы и делаем командой CreateThread(@ReadDevice_Thread(),0). Посмотрим поподробнее на эту процедуру
Procedure ReadDevice_Thread(*x) Dim InBytes.c(9) Repeat If R_DeviceHandle HID_Lib_ReadDevice(R_DeviceHandle, @InBytes(), 9) If InBytes(1)=1 SetGadgetText(40,Str( InBytes(2))) EndIf If InBytes(1)=2 SetGadgetText(50,Str( InBytes(2))) EndIf EndIf Delay(20) ForEver EndProcedure Первым делом мы объявляем массив Dim InBytes.c(9) в который мы будем принимать данные. Этот массив мы объявляем именно в процедуре потому что она будет работать только в ней. Далее мы принимаем 8 байт данных и смотрим если 1 байт равен 1 то второй байт (измеренное напряжение) выводим в окошко предварительно переведя число в строку командой Str, вот как это выглядит SetGadgetText(40,Str( InBytes(2))). А если 1 байт равен 2 то 2 байт мы по той же схеме выводим в другое окошко (предел измерения). Далее делаем небольшую задержку и добавляем команду ForEver чтобы поток повторялся бесконечно. Вот в принципе и вся программа, осталось сказать пару строк про шрифт. Global FontID1 FontID1 = LoadFont(1, "Times New Roman", 36) Так как мы будем использовать его в процедурах, объявим его, а далее собственно выбираем шрифт. Здесь 1 это идентификатор шрифта, далее собственно название шрифта и его размер. Чтобы поставить шрифт в какой не будь гаджет используем команду SetGadgetFont(40,FontID(1)) Где 40 это номер гаджета в который устанавливает шрифт, и сам шрифт (1 это идентификатор шрифта). Далее создаём приложение зайдя в пункт «компилятор»-«создать приложение», написав название вашей программы, нажимаем сохранить и всё ваша программа создана. Прежде чем создавать приложение можно войти в «настройки компилятора» и настроить параметры будущей программы, выбрать иконку и тд. На этом всё, подключаем устройство к компьютеру, если оно правильно собрано то сразу определится, установится в систему и будет измерять напряжение. Ниже можно скачать две версии скомпилированной программы Окно программы в режиме измерения в диапазоне 20 вольт, величина измеренного напряжения 18 вольт: В приложенном архиве схема, исходники и компилированная прошивка для контроллера и компьютера (2 программы для 32 и 64 разрядных систем). | |
Просмотров: 24364 | Комментарии: 51 | Рейтинг: 5.0/6 |
Всего комментариев: 51 | 1 2 » | |||||||||||||||||||||||||
| ||||||||||||||||||||||||||
1-30 31-51 | ||||||||||||||||||||||||||
авторизация
рубрики
Проекты [46] |
Как подключить [32] |
Инструменты [3] |
Полезная информация [18] |
Объявления [3] |
метки