Высказывания и цитаты:

С чего начинается Родина?
С окошек, горящих вдали,
Со старой отцовской будёновки,
Что где-то в шкафу мы нашли.
А может она начинается
Со стука вагонных колес
И с клятвы, которую в юности
Ты ей в своём сердце принёс.

  • 09Дек
    PIC

    Здравствуйте, дорогие друзья! )))

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

    Стенд выполнен на микроконтроллере PIC18F4550 в связке с микросхемами PCA9698 (расширители портов ввода-вывода) по i2c шине. Микроконтроллер подключается к USB порту компьютера (обнаруживается как usb-hid устройство), и управляется специально написанной на Microsoft Visual C++ для него программой… (все исходные коды с подробным описанием прилагаются).
    stend0

    stend2

     

    plate0

    Для ремонта таких плат стенд предназначался.

    prog1Так выглядит среда разработки Visual C++.

    prog0

    Так выглядит редактор создания тестового файла для платы.

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

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

    Одним подобных, но более продуманных стендов, был “ТЕСТ-Д”, замечательно зарекомендовавший себя в ремонте ЧПУ советских станков таких как 2Р22 и НЦ31… С него собственно и появилась идея написать что-нибудь свое.

    В качестве языка программирования на компьютере я выбрал Microsoft Visual Studio C++ (писал на Microsoft Visual C++ 2008 Express Edition, но проект будет совместим и с версией 2015 года). Многие предлагали мне писать на якобы более совершенном языке C Sharp, но Visual Studio С++ мне показался настолько функциональным, в нем было то, чего не было в C Sharp для создания моего стенда. Хотя примеров пользователей, которые пишут на нем, в интернете не много…

    В качестве USB микроконтроллера я взял PIC18F4550, так как он очень популярный микроконтроллер и на него есть в интернете множество примеров…  Среда разработки MPLAB IDE 8.10 (8.40) + компилятор C18. Хотя вышла среда MPLAB X,  в ней за поддержку языка си разработчики среды просят денег, а компилятор C18 в свободном доступе…

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

    Микросхема PCA9698 (pca9698.pdf) имеет 40 лапок, каждая из которых перестраивается на ввод или на вывод. При работе на вывод, ток логической единицы составляет 15мА, а логического нуля 25мА, что не очень здорово, ведь у микроконтроллера PIC18F4550 логические “1” и “0” имеют ток в 25мА.

    Микросхемы PCA9698  управляются по двум проводам шины i2c и могут быть подключены в количестве 8 штук на одну шину, при таких обстоятельствах можно получить до 320 лапок, если бы потребовалось. Адрес микросхемы задается тремя лапками, которые можно подключить в различной комбинации либо к плюсу питания либо к земле. Именно поэтому на одну i2c шину можно подключить не более восьми таких микросхем.

    PCA9698 в очень маленьком корпусе, расстояние между её лапками всего 0,5мм, плату для нее вытравить хлорным железом, а потом еще спаять, оказалось для меня нереально… Поэтому, плату под микросхему нарисовал в самой простой программе SlayOut (plats.rar)… Файл сохранил в формате gerber и отправил в фирму по изготовлению печатных плат Техносвязь http://www.techno-svyaz.ru/ в городе Екатеринбурге. Сделали ее очень дешево, мне так показалось (50 штук по цене 70р за штуку в апреле 2016 года) на одностороннем миллиметровом стеклотекстолите…

    USB – это достаточно сложный протокол обмена информацией, но для того, чтобы написать программу, знать как он работает не обязательно. Мы воспользуемся готовыми библиотеками для работы интерфейса USB.  Я долго решал, какой класс устройства выбрать: Hid или CDC. И тот и другой класс не требует написания драйвера, так как устройства этого класса являются стандартными для Windows (на самом деле стандартных устройств в Window довольно много). Оба класса устройств являются медленными, а так как большая скорость не нужна, подойдет любой. В  случае hid устройства хост опрашивает устройство с интервалом 1 миллисекунду и может передать 64 байта и принять 64 байта максимум за один опрос. CDC устройство может работать на разных скоростях, это своего рода виртуальный COM-порт… Я выбрал USB-hid класс (обычно его используют для USB клавиатуры или мыши).

    Для работы компьютерной программы и программы микроконтроллера в паре необходимо в обеих программах произвести одинаковые настройки…

    HID_Software.rar – архив с исходными кодами на Microsoft Visual C++.В файле About.txt написана инструкция по работе со стендом… В процессе испытаний выяснилось, что алгоритм перебора комбинаций нолей и единиц (как случайных чисел так и посредством инкремента и декремента), подающихся на плату является не эффективным, в результате был добавлен анализатор сигналов, но и он оказался не эффективным… можно было отследить только часть ошибок. В итоге я пришел к выводу, что необходимо писать под каждую плату определенный алгоритм тестирования…(эту программу я так и не стал делать).

    HID_Firmware.rar – архив с исходными кодами на PIC микроконтроллер в MPLAB И C18.

    Реле SRA-05VDC-CL подает питание на проверяемый блок/плату при нажатии соответствующей кнопки в программе на компьютере… Меню программы неактивно до тех пор, пока не будет обнаружено USB устройство…

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

    …………………………..

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

    Я не буду сейчас писать в какой части кода Software мы пишем следующие строки — просто посмотрите исходные коды и найдите их…

    private: System::ComponentModel::BackgroundWorker^  ReadWriteThread; // объявляем поток

    this->ReadWriteThread = (gcnew System::ComponentModel::BackgroundWorker()); // создаем

    this->ReadWriteThread->WorkerReportsProgress = true;
    this->ReadWriteThread->DoWork += gcnew System::ComponentModel::DoWorkEventHandler(this, &Form1::ReadWriteThread_DoWork);

    ReadWriteThread->RunWorkerAsync(); // запускаем поток, и он будет функционировать с этого момента

    private: System::Void ReadWriteThread_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {

    } // в этой функции пишем то, что в потоке должно происходить

    ………………..

    Процесс обмена по USB реализован просто: компьютер посылает запрос и ждет до тех пор, пока не придет ответ… Таким способом происходит потеря времени на ожидание ответа, зато ответы приходят последовательно в том порядке как их запрашивали.

    void function (void) // функция, в которой происходит обмен информацией по USB со стороны компьютера
    {
    unsigned char OUTBuffer[65]; //Allocate a memory buffer equal to the OUT endpoint size + 1
    unsigned char INBuffer[65]; //Allocate a memory buffer equal to the IN endpoint size + 1
    DWORD BytesWritten = 0;
    DWORD BytesRead = 0;

    if (AttachedState == TRUE) // если наше устройство подключено и распознано
    {
    OUTBuffer[0] = 0; // обязательно написать 0, нулевой байт буфера нельзя использовать
    OUTBuffer[1] = 0x11; // символизирует что данные содержат номер контакта и направление
    for(unsigned char qqq=0;qqq<30; qqq++)
    {
    OUTBuffer[qqq+2]=simbout[qqq]; // заполняем выходной буфер данными
    }
    for(unsigned char i = 32; i <65; i++) // не обязательно, стираем лишнее из выходного буфера
    OUTBuffer[i] = 0xFF;

    if(WriteFile(WriteHandleToUSBDevice, &OUTBuffer, 65, &BytesWritten, 0)) // передаем данные от компьютера в USB устройство
    {
    //Now get the response packet from the firmware.
    INBuffer[0] = 0;
    if(ReadFile(ReadHandleToUSBDevice, &INBuffer, 65, &BytesRead, 0)) //принимаем данный из устройства в компьютер
    {
    //INBuffer[0] is the report ID, which we don’t care about.
    //INBuffer[1] is an echo back of the command (see microcontroller firmware).
    //INBuffer[2] contains the I/O port pin value for the pushbutton (see microcontroller firmware).
    if (INBuffer[1] == 0x11)
    {
    // здесь что-то пишем если пришел нужный ответ
    }
    }
    } // конец if WriteFile
    } // конец if  (AttachedState == TRUE)
    } // конец function

    ……………………………………….

    Со стороны микроконтроллера считываем буфер и смотрим что в нем

    if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
    if(!HIDRxHandleBusy(USBOutHandle)) //Check if data was received from the host.
    {
    switch(ReceivedDataBuffer[0]) //Look at the data the host sent, to see what kind of application specific command it sent.

    {

    case 0x11: //функция simbout1 направление ввода/вывода
    {
    for (kkk=0; kkk<8; kkk++)
    {my_buffer[kkk] = ReceivedDataBuffer[kkk+1]; } // считали данные из буфера
    fr1();
    ToSendDataBuffer[0] = 0x11;
    if (err_to_pk==1) {ToSendDataBuffer[0] = 0x50; ToSendDataBuffer[1] = adr_oshibki; adr_oshibki=0; err_to_pk=0;} // отсылаем «ошибка i2c»
    if(!HIDTxHandleBusy(USBInHandle))
    {
    USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64);
    }
    }
    break;

    ///////

    }
    //Re-arm the OUT endpoint for the next packet
    USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
    }

    …………………………………………….

    Создание строкового массива, когда мы заранее не знаем сколько в каждой строке символов

    mass3 = gcnew array<String ^>(3); // в этом массиве три строки

    private: array<String^>^mass3; // а каждая строка имеет неизвестное кол-во символов

    mass3[0]=….

    ……………

     

Ваш ответ

Внимание: Модератор оставляет за собой право редактировать или удалять комментарии.

Подтвердите, что Вы не бот — выберите человечка с поднятой рукой: