Параллельный интерфейс на CH341.

Тема в разделе "MASM", создана пользователем Devasya, 22 авг 2023.

  1. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    Поставлена задача, организовать параллельный интерфейс с внешним устройством в режиме EPP.
    Для CH341 вся информация на Си и это проблема которую пытаюсь решить. А проблема в следующем:
    При попытке получить статус выводов-приложение закрывается.
    Это небольшая часть кода для проверки связи с микроконтроллером
    Код (ASM):
    1. .elseif ax==IDM_WRITE
    2.                  
    3.                                     mov CH341_MAX_NUMBER, 16
    4.                             metka1:
    5.                                     invoke   CH341OpenDevice, CH341_MAX_NUMBER ;0        ; Открывает устройство с заданным номером.
    6.                             .if eax!=INVALID_HANDLE_VALUE
    7.                                     mov iIndex, eax                    ; получили дескриптор устройства
    8.                                  
    9.                                     invoke CH341SetExclusive, CH341_MAX_NUMBER, 1; установили эксклюзивное использование
    10.                                     invoke CH341SetParaMode,CH341_MAX_NUMBER, 1 ; режим ЕРР 1.9 возвращает (успех - 1)
    11.                                     cmp  eax, 0
    12.                                     ;jz metka3
    13.                                     jz metka2
    14.                                     invoke CH341ResetDevice, iIndex   ; здесь всё хорошо PIC видит комп и наоборот
    15.                                     ; Reset не нуждается в подтверждении
    16.                                      
    17.                                         mov al, 7                                    ; iIndex - не канает
    18.                                         invoke CH341EppSetAddr, CH341_MAX_NUMBER, al ; передача, всё хорошо PIC видит, выводит 7
    19.                                         mov eax, 0
    20.                                         mov iStatus, eax
    21.                             stat:   invoke CH341GetStatus, iIndex, iStatus       ; с этого места программа закрывается
    22.                                     cmp eax, 0
    23.                                     jz metka3
    24.  
    25.                                         ;mov eax, iStatus
    26.                                         ;bt eax, 10    ; проверка бита INT
    27.                                         ;jc meka1  ; переход если CF=1
    28.                                         ;jnc stat ; переход если CF=0
    29.                                     ;cmp eax, 0
    30.                                     ;jz metka3
    31.                                  
    32.                             meka1:
    33.                                     invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION ;"УСПЕШНОЕ ПОДКЛЮЧЕНИЕ!"
    34.                                     invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION  ;"ОТКЛЮЧИТЬ?"
    35.                                     invoke CloseHandle, iIndex
    36.                                     invoke CH341CloseDevice, CH341_MAX_NUMBER
    37.                                  
    38.                     invoke EnableMenuItem,hMenu,IDM_OPEN,MF_GRAYED
    39.                     invoke EnableMenuItem,hMenu,IDM_SAVE,MF_GRAYED
    40.                     invoke EnableMenuItem,hMenu,IDM_WRITE,MF_ENABLED
    41.                     invoke EnableMenuItem,hMenu,IDM_READ,MF_GRAYED
    42.                     ret
    43.                     jmp meka
    44.                             .else
    45.                                     mov eax, CH341_MAX_NUMBER
    46.                                     dec eax
    47.                                     cmp  eax, -1
    48.                                     jle  metka2
    49.                                     mov  CH341_MAX_NUMBER, eax
    50.                                     jnl  metka1
    51.                             metka2:
    52.                                     invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR   ;"ПОДКЛЮЧИТЕ УСТРОЙСТВО."
    53.                                     invoke CloseHandle, iIndex
    54.                                     invoke CH341CloseDevice, CH341_MAX_NUMBER
    55.                                      ;invoke CloseHandle, iIndex
    56.                                      ret
    57.                                      jmp meka
    58.                                 metka3:
    59.                                         invoke MessageBox,NULL,addr Falure,NULL,MB_OK+MB_ICONERROR   ; "УСТРОЙСТВО НЕ ОТВЕЧАЕТ!"
    60.                                         invoke CloseHandle, iIndex
    61.                                     invoke CH341CloseDevice, CH341_MAX_NUMBER
    62.                                     ret
    63.                                         jmp meka
    64.                                      
    65.                                 sosb1:
    66.                                         invoke MessageBox,NULL,addr Filure,NULL,MB_OK+MB_ICONERROR ; "ОШИБКА ЧТЕНИЯ!"
    67.                                         invoke CloseHandle,hMapFile
    68.                                         mov    hMapFile,0
    69.                                         invoke CloseHandle,hFileRead
    70.                                         ret
    71.  
    72.                 .endif
    Если я правильно понял, то нужно организовать процедуру обратного вызова, но как это сделать ума не приложу. Помогите разобраться и не судите строго ученика.
     

    Вложения:

    • PrintR.asm
      Размер файла:
      18,1 КБ
      Просмотров:
      149
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Открой для себя такую штуковину как отладчик.
     
  3. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    Это не решает проблему. Пробовал-осталось разобраться что и о чём в нём идёт речь. В общем не очень помогло.
     
  4. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    И о чем в нем идет речь? На какой инструкции исключение, какой код ошибки?
     
  5. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    f13nd, Уважаемый мне не отлаживать нужно. Программа ещё не готова, там ошибок море (я в этом не сомневаюсь). Меня интересует процедура обратного вызова которой у меня в тексте нет.
     
  6. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    А, я понял: "проблема в следующем: приложение закрывается, но это не проблема и вообще надо какую-нибудь процедуру обратного вызова реализовать хз зачем".

    Судя по апи, процедур обратного вызова там всего две:
    Код (Text):
    1. typedef        VOID    ( CALLBACK    * mPCH341_INT_ROUTINE ) ( ULONG    iStatus );
    2. BOOL    WINAPI    CH341SetIntRoutine( ULONG iIndex, mPCH341_INT_ROUTINE iIntRoutine );
    3.  
    4. typedef        VOID    ( CALLBACK    * mPCH341_NOTIFY_ROUTINE ) ( ULONG iEventStatus );
    5. BOOL    WINAPI    CH341SetDeviceNotify( ULONG    iIndex, PCHAR iDeviceID, mPCH341_NOTIFY_ROUTINE    iNotifyRoutine );
    Создаешь процедуру (скорей всего stdcall), аргумент всего один (iStatus/iEventStatus), указатель на нее передаешь CH341SetIntRoutine/CH341SetDeviceNotify.
     
  7. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    И как это всё записать на Ассемблере. (Я же не профи). Даже программу пришлось сочинять самому ибо желающих помочь даже за деньги не нашлось. Извини ,я только учусь программированию.
    Код (ASM):
    1. invoke CH341SetIntRoutine,   iIndex,  iIntRoutine     ;
    2. invoke CH341SetDeviceNotify,    iIndex,  iDeviceID,   iNotifyRoutine ;
    Я правильно себе представляю вызов функций API?
     
  8. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Наверное "addr iIntRoutine" надо в масмовском синтаксисе. Адрес процедуры передается как аргумент.
    --- Сообщение объединено, 22 авг 2023 ---
    ЗЫ:
    Код (Text):
    1. invoke CH341GetStatus, iIndex, iStatus
    Код (Text):
    1. BOOL    WINAPI    CH341GetStatus( ULONG iIndex, PULONG iStatus );
    Приложение закрывается потому что ты вместо указателя на переменную, куда статус должен быть помещен, передаешь содержимое переменной. Отладчик мог бы об этом поведать, если бы это было проблемой.
     
  9. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    То есть так ?
    Код (C):
    1. invoke CH341SetIntRoutine,  iIndex,  ADDR  iIntRoutine    ;
    Сборку провожу с помощью bat. файла. А проверку на реальном железе.
    А что значит - Определите процедуру обработки прерывания ?
    Код (C):
    1. BOOL WINAPI CH341SetIntRoutine(        // Установите процедуру обработки прерывания
    2. ULONG iIndex,    // Определите порядковый номер устройства CH341
    3. mPCH341_INT_ROUTINE iIntRoutine );  // Определите процедуру обработки прерывания,
    4.  если это будет НУЛЬ, сервис прерывания будет отменен, иначе стандартную программу назовут, когда прервано
    Вопросов океан.
     
  10. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Означает "впиши сюда адрес обработчика, либо подставь нуль чтобы отключить уже зарегистрированный обработчик". Обработчик прерывания в некотором смысле тоже процедура обратного вызова. Ну назвали так и назвали, не академики из академий видимо комментарий писали.

    ЗЫ: "иначе стандартную программу назовут, когда прервано" - да это ж перевод с китайского в стиле алиэкспресс.
     
    Последнее редактирование: 22 авг 2023
  11. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    Вот именно PROMT переводчик плюс ручная редакция , чтобы хоть что то понять.
    Уже опробовано. Работает! :
    Что же Вы, батенька, раньше-то молчали?
    invoke CH341GetStatus, iIndex, ADDR iStatus

    P.S. ЗЫ - знакомое, потому как в инете много инфы собираю и на форумах в том числе
    --- Сообщение объединено, 22 авг 2023 ---
    Спасибо огромное.
     
  12. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    Проверил сегодня передачу данных и облом
    mov eax, 7
    mov iBuffer, eax
    invoke CH341EppWriteData, iIndex, ADDR iBuffer, ioLength

    Вроде всё как положено, но на выходе ни WR ни DS не отработали вообще.
    Что опять не так?
     
  13. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Код (Text):
    1. BOOL    WINAPI    CH341EppWriteData( ULONG iIndex, PVOID iBuffer, PULONG ioLength );
    Указатель на ioLength передается, не значение.
     
  14. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    Вроде бы правильно
    BOOL WINAPI CH341EppWriteData( // Запишите данные в режиме EPP: WR# = 0 запись в, DS# = 0 передача, AS# = 1 приём, D0-D7=output
    ULONG iIndex, // Specify the serial number of the CH341 device
    PVOID iBuffer, // Указатель на буфер, куда данные, которые будут записаны, помещаются
    PULONG ioLength ); // Точки к единице длины, длина, которая будет выписана, когда введенный длина, которая будет выписана, и длина, на самом деле выписанная после возврата
    Пробовал и так
    invoke CH341EppWriteData, iIndex, ADDR iBuffer, ADDR ioLength
    результат тот-же
    --- Сообщение объединено, 23 авг 2023 ---
    Может со структурами перемудрил?
    Код (Text):
    1. USB_SETUP_PKT     STRUCT                                     ;; Передача управления USB фазы установления структуры пакета запроса данных
    2.         mUspReqType    BYTE   ?        ;; 00H   Тип запроса
    3.         mUspRequest    BYTE   ?        ;; 01H   Код запроса
    4.     union                                            ;;
    5.     ;;    struct  
    6.         mUspValueLow    BYTE   ?        ;; 02H Младшие байты параметра, передаваемого по значению
    7.         mUspValueHigh    BYTE   ?        ;; 03H Параметр, передаваемый по значению высокие байты
    8.         mUspValue       WORD   ?        ;; 02H-03H Параметр, передаваемый по значению  union1
    9.     ends
    10.     union                                            ;;
    11.     ;;    struct  
    12.         mUspIndexLow    BYTE   ?        ;; 04H Индексные младшие байты параметра
    13.         mUspIndexHigh    BYTE   ?        ;; 05H Индексный параметр высокие байты
    14.  
    15.         mUspIndex       WORD   ?        ;; 04H-05H Индексный параметр  union2
    16.         ends
    17.         mLength         WORD   ?        ;; 06H-07H Длина данных - фазы данных
    18. USB_SETUP_PKT ENDS
    19.  
    20. ;;;=====================================================================================================
    21.  
    22. WIN32_COMMAND    STRUCT                                  ;; Определение структуры интерфейса команды WIN32
    23.     union                                            ;;
    24.         mFunction       DWORD  ?                ;; Определите функциональный код или передайте число по каналу при вводе union1
    25.         mStatus         DWORD  ?                ;; Операционное состояние возвратов на выводе
    26.         mLength         DWORD  ?                ;; Продолжительность доступа, возвращает длину последующих данных
    27.     ends
    28.     union                                            ;;
    29.                 mUSB_SETUP_PKT  DWORD  ?                ;; Управление USB передача данных запрашивает во время фазы установки    mSetupPkt          
    30.         mBuffer         DWORD  ?                ;; Буфер данных, от 0 до 255B в длине union2
    31.     ends
    32. WIN32_COMMAND ENDS
    33.  
    34. ;;;=========================================================================================================
    35.  
    Писал самостоятельно, а правильно или нет не у кого спросить.
    --- Сообщение объединено, 23 авг 2023 ---
    Мне кажется, что что то с буфером не так всё просто. Чего-то в нём не достаток. PVOID -это функция так-же?
    А какая? А как её расписать? А аргументы какие? А где она должна быть расположена в программе?
    А в буфер как её воткнуть? На Си пример есть, но он не годится для MASM32, а как переделать под ассемблер?
    Даже : stdcall mPCH341_NOTIFY_ROUTINE iStatus - синтаксис компилятору не нравится.
    --- Сообщение объединено, 23 авг 2023 ---
    К стати ОляДБГ выдаёт код ошибки 00000006
    Не верный дескриптор если верить инету. Но как так?
     
    Последнее редактирование: 23 авг 2023
  15. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    В доках pdf всё расписание-же, вы читали их?
    Нотификация вам не нужна - если посмотреть на описание функции CH341SetDeviceNotify(),
    то её колбэк просто возвращает статус устройства в порту: подключено или удалено.
    Код (Text):
    1. CH341SetDeviceNotify (iIndex, iDeviceID, pCH341_NOTIFY_ROUTINE);
    2. pCH341_NOTIFY_ROUTINE (iEventStatus);
    3. const  CH341_DEVICE_REMOVE      =  0 ;
    4.        CH341_DEVICE_REMOVE_PEND =  1 ;
    5.        CH341_DEVICE_ARRIVAL     =  3 ;
    Если в теории пролистав доки, то ваш алго должен быть примерно таким..
    (все аргументы с префиксом(i) являются непосредственным значением, а префикс(р) - это указатель на память):

    1. Подключаем девайс в порт USB и в диспетчере смотрим, в каком порту оно появилось. Номер порта и будет значением iIndex для всех функций в коде. Вроде была какая-то API, которая авто-возвращала этот номер.. не помню. В дебаг-версии пусть юзер сам предоставляет "iIndex" программе.
    Код (Text):
    1. // *********************
    2. // General routines
    3. // *********************
    4. // CH341A is addressed with ‘iIndex':
    5. // iIndex=0 => 1st CH341 @USB
    6. // iIndex=1 => 2nd CH341 @USB
    7. // iIndex=2 => 3rd ...
    2. CH341OpenDevice (iIndex) для открытия девайса. Ошибка, если в EAX получим(-1).
    3. CH341ResetDevice (iIndex), сбросить настройки чипа в дефолт.
    4. CH341SetExclusive (iIndex, 1), чтобы никто больше не пользовался портом.
    5. CH341InitParallel (iIndex, 1), перевести чип в режим EPP, iMode=1.
    6. CH341SetParaMode (iIndex, 1), видимо свойства порта (константы iMode указаны на скрине ниже).
    7. CH341GetDeviceDescr(iIndex, pBuffer, pLength), считаем в буфер дескриптор девайса (хз какого он размера).
    Буфер должен быть в памяти, а размер "pLength" там-же в переменной.
    Код (ASM):
    1. .data
    2. pLength  dd  128
    3. pBuffer  db  128 dup(0)
    8. CH341GetDeviceName(iIndex), в регистре EAX получим указатель на имя где-то в памяти.
    9. CH341EppReadData(iIndex, pBuffer, pLength), читаем с порта в буфер (Write пишет в порт из буфера).
    10. CH341EppSetAddr (iIndex, iAddr), если читаем из адреса, то указываем его.
    11. CH341EppReadAddr(iIndex, pBuffer, pLength)
    12. CH341CloseDevice(iIndex).

    Это все функции для работы с парпортом в режиме EPP.
    В доках указано, что CH341GetStatus() используется только при работе с шиной i2c.

    ch341.png
     
    Mikl___ нравится это.
  16. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    Вот небольшой пример для работы с девайсом CH341.
    Поскольку у меня нет его физически, то код писал в слепую, просто вызывая функции.

    1. Как и говорилось выше, значение "iIndex" смотри в диспетчере устройств - на входе, код запросит его. Кстати, чтобы программно поймать "iIndex", можно обратиться к диспетчеру конфигурации Win, функции которого сосредоточены в либе "setupapi.dll" - они имеют префикс CM_xx от "ConfigManager".

    Но это длинная история, и можно пойти другим путём. В хидере ch341.h есть константа "mCH341_MAX_NUMBER=16" - это макс.значение "iIndex". Достаточно просто организовать цикл на входе в программу, и перебирать "iIndex" в диапазоне 0-15. Как-только fn. CH341ResetDevice() вернёт нуль, значит ей попался валидный "iIndex".

    2. CH341GetVersion() возвращает версию юзер-либы "ch341dll.dll", а CH341GetDrvVersion() должна возвратить версию драйвера "ch341wdm.sys". Походу дров загружается только при обнаружении физ.девайса, т.к. я получил dll v3.3, а в sys пусто (должно быть v3.4).

    3. Код чекает ошибки, по которым можно сделать выводы. В скрепке EXE и инклуд для FASM'a "ch341header.inc".
    Код (ASM):
    1. format   pe console
    2. include 'win32ax.inc'
    3. include 'equates\ch341header.inc'
    4. entry    start
    5. ;//----------
    6. .data
    7. iIndex   dd  0
    8. errMes   rb  256
    9. pLength  dd  mDEFAULT_BUFFER_LEN   ;// размер буфера 1024 byte
    10. pBuffer  rb  mDEFAULT_BUFFER_LEN   ;// сам буфер
    11. ;//----------
    12. .code
    13. start:
    14. ;// Запрашиваем номер порта USB, куда подключен 'CH341'
    15.         cinvoke  printf,<10,' CH341 chip EPP-mode',\
    16.                          10,' max iIndex value = %d dec',\
    17.                          10,' -------------------------------',10,\
    18.                          10,' Type USB/COM iIndex:  ',0>,mCH341_MAX_NUMBER
    19.         cinvoke  scanf,<'%d',0>,iIndex
    20.          dec     [iIndex]
    21.  
    22. ;// Открываем девайс, сбрасываем его в дефолт, и ставим режимы
    23.          invoke  CH341OpenDevice,[iIndex]
    24.         cinvoke  printf,<   '         Open device:  ',0>
    25.          call    LastError
    26.          invoke  CH341ResetDevice, [iIndex]
    27.          invoke  CH341SetExclusive,[iIndex],1
    28.          invoke  CH341InitParallel,[iIndex],mCH341_PARA_MODE_EPP19
    29.          invoke  CH341SetParaMode, [iIndex],mCH341_PARA_MODE_EPP19
    30.         cinvoke  printf,<   '   Set EPP-mode v1.9:  ',0>
    31.          call    LastError
    32.  
    33. ;// Выводим различную инфу о девайсе
    34.          invoke  CH341GetDeviceDescr,[iIndex],pBuffer,pLength
    35.         cinvoke  printf,<10,' Device descriptor..:  %08x%08x',0>,dword[pBuffer],dword[pBuffer+4]
    36.          mov     [pLength],256
    37.          invoke  CH341GetConfigDescr,[iIndex],pBuffer,pLength
    38.         cinvoke  printf,<10,' Config descriptor..:  %08x%08x',0>,dword[pBuffer],dword[pBuffer+4]
    39.          invoke  CH341GetDeviceName, [iIndex]
    40.          push    eax
    41.          invoke  CH341GetVersion
    42.          push    eax
    43.          invoke  CH341GetDrvVersion
    44.          pop     ebx ecx
    45.         cinvoke  printf,<10,' Device name........:  %s',\
    46.                          10,' Library version....:  %02d',\
    47.                          10,' Driver  version....:  %02d',10,0>,\
    48.                          ecx,ebx,eax
    49.  
    50. ;// Очистим буфер, и пробуем что-нибудь считать в него из порта
    51.         stdcall  ClearBuffer
    52.          invoke  CH341EppReadData,[iIndex],pBuffer,[pLength]
    53.         cinvoke  printf,<10,' Port read data.....:  %08x%08x',10,0>,dword[pBuffer],dword[pBuffer+4]
    54.         cinvoke  printf,<   '      Read lastError:  ',0>
    55.         stdcall  LastError
    56.  
    57. ;// Очистим буфер, введём в него строку, и пробуем записать её в порт
    58.         stdcall  ClearBuffer
    59.         cinvoke  printf,<10,' String for write...:  ',0>
    60.         cinvoke  scanf,<'%s',0>,pBuffer
    61.          mov     [pLength],64
    62.          invoke  CH341EppWriteData,[iIndex],pBuffer,[pLength]
    63.         cinvoke  printf,<   '     Write lastError:  ',0>
    64.         stdcall  LastError
    65.  
    66. ;// Прихлопнуть девайс
    67.          invoke  CH341CloseDevice,[iIndex]
    68.         cinvoke  printf,<   '     Close lastError:  ',0>
    69.         stdcall  LastError
    70. @exit:  cinvoke  _getch
    71.         cinvoke  exit,0
    72. ;//----------
    73. proc     ClearBuffer
    74.          mov     edi,pBuffer
    75.          xor     eax,eax
    76.          mov     ecx,128/4
    77.          rep     stosd
    78.          ret
    79. endp
    80. proc     LastError
    81.          invoke  GetLastError
    82.          invoke  FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,0,eax,0,errMes,256,0
    83.          invoke  CharToOem,errMes,errMes
    84.         cinvoke  printf,<'%s',0>,errMes
    85.          ret
    86. endp
    87. ;//----------
    88. section '.idata' import data readable
    89. library  msvcrt,'msvcrt.dll', kernel32,'kernel32.dll',\
    90.          user32,'user32.dll', ch341dll,'ch341dll.dll'
    91. include 'api\kernel32.inc'
    92. include 'api\user32.inc'
    93. include 'api\msvcrt.inc'
    94. include 'api\ch341dll.inc'
    ch341.png
     
  17. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    Marylin, благодарю за исчерпывающий ответ. Но меня смущает следующее :
    HANDLE WINAPI CH341OpenDevice( ULONG iIndex )
    Согласно правила определения функции API запись слева направо и в начале ставится возвращаемое значение затем название и затем следуют аргументы.
    Если я не ошибаюсь ,то возвращаемое значение есть HANDLE , то есть некий дескриптор или описатель (тут кто как говорит) может его лучше называть INTEGER-некоторое целое число, а то возникает вопрос что с ним дальше делать и нужно ли его сохранять или используется только для идентификации? MASM и FASM несколько отличаются и, для ученика вроде меня, это существенно:
    Код (ASM):
    1. .elseif ax==IDM_WRITE
    2.                             metka1:
    3.                                     invoke   CH341OpenDevice, CH341_MAX_NUMBER ;0        ; Открывает устройство с заданным номером.
    4.                             .if eax!=INVALID_HANDLE_VALUE
    5.                                     invoke CH341SetExclusive, CH341_MAX_NUMBER, 1; установили эксклюзивное использование
    6.                                     invoke CH341SetParaMode,CH341_MAX_NUMBER, 1 ; режим ЕРР 1.9 возвращает (успех - 1)
    7.                                     cmp  eax, 0
    8.                                     jz metka2
    9.                                     invoke CH341ResetDevice, iIndex   ; здесь всё хорошо PIC видит комп и наоборот
    10.                                     ; Reset не нуждается в подтверждении
    11.                                      
    12.                                         mov al, 7
    13.                                         invoke CH341EppSetAddr, CH341_MAX_NUMBER, al ; передача, всё хорошо видит
    14.                             stat:   invoke CH341GetStatus, iIndex, ADDR iStatus       ;
    15. ; iStatus
    16. ; данные состояния прерывания чтения, посмотрите ниже
    17. ; Разряды соответствуют контактам D7-D0 CH341
    18. ; Бит 8 соответствует ERR# , бит 9 - PEMP, бит 10 - INT# и бит 11 - SLCT
    19.                                         mov eax, iStatus
    20.                                         bt eax, 10    ; проверка бита INT
    21.                                         jc stat  ; переход если CF=1
    22.                                     mov al, 7
    23.                                     mov iBuffer, al  ; запись в буфер числа =7
    24.                                     mov al, 1
    25.                                     mov ioLength, al ; количество байт=1
    26.                                     invoke CH341EppWriteData, CH341_MAX_NUMBER, ADDR iBuffer, ioLength
    27.                                  
    28.                             meka1:
    29.                                     invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION ;"УСПЕШНОЕ ПОДКЛЮЧЕНИЕ!"
    30.                                     invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION  ;"ОТКЛЮЧИТЬ?"
    31.                                     invoke CH341CloseDevice, CH341_MAX_NUMBER
    32.                                    
    33.                                      invoke EnableMenuItem,hMenu,IDM_OPEN,MF_GRAYED
    34.                                      invoke EnableMenuItem,hMenu,IDM_SAVE,MF_GRAYED
    35.                                      invoke EnableMenuItem,hMenu,IDM_WRITE,MF_ENABLED
    36.                                      invoke EnableMenuItem,hMenu,IDM_READ,MF_GRAYED
    37.                                      ret
    38.                                      jmp meka
    39.                             .else
    40.                                     mov eax, CH341_MAX_NUMBER
    41.                                     dec eax
    42.                                     cmp  eax, -1
    43.                                     jle  metka2
    44.                                     mov  CH341_MAX_NUMBER, eax
    45.                                     jnl  metka1
    В документе ch341a_datasheet_code CH341GetStatus и CH341GetInput относятся к информационным запросам независимо от режима и нет ограничений на комбинирование команд, исключением являются команды прямого ввода/вывода- с осторожностью.
    Конечно код программы зависит от программы самого устройства и в данном случае подтверждение приходит от устройства на вывод INT.
    --- Сообщение объединено, 26 авг 2023 ---
    А ещё вопрос О существовании какой-нибудь программы которая сама пишет инклуды и прототипы (МЕЧТА).
     
  18. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    Посмотрите, что возвращает программа в скрепке.
     

    Вложения:

    • CH341.ZIP
      Размер файла:
      3,7 КБ
      Просмотров:
      145
  19. Devasya

    Devasya New Member

    Публикаций:
    0
    Регистрация:
    18 апр 2023
    Сообщения:
    19
    А можно небольшую инструкцию пользователю для этой программки?
     
  20. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    нельзя.. мозгами шевели