Понедельник, Май 25, 2020

Кнопка вкл.светодиода

В microchip_solutions_v2013-02-15 есть пример программы написанной в Visual Studio 2005 на С++ CLR .net, с ним будем разбираться. Чтобы удобней было работать и оставить исходные файлы без изменения ,скопируем в c:\Program Files\Labcenter Electronics\Proteus 7 Professional\SAMPLES папку c:\microchip_solutions_v2013-02-15\Microchip ,а в папку c:\Program Files\Labcenter Electronics\Proteus 7 Professional\SAMPLES\VSM for USB\PICDEM FS USB\ скопируем папки c:\microchip_solutions_v2013-02-15\USB\Device - MCHPUSB - Generic Driver Demo\Firmware и c:\microchip_solutions_v2013-02-15\USB\Device - MCHPUSB - Generic Driver Demo\PC Software\Visual C++ 2005 Express\Code.

Можно купить PIC18F4550 и спаять схему как в Proteus ,у меня она работает.

Рекомендую прочитать книгу "Агуров П. Практика программирования USB.2006",правда там про Atmel ,но знать ,что такое дескрипторы и конечные точки нужно. На торренте скачайте Visual Studio 2005,но у мнея прога нормально скомпилировалась в Visual Studio 2012.

Итак,у нас есть проект ,который написалив Microchip и писать свой очень долго,а зачем изобретать велосипед :),если уже все есть. Открываем файл main.c и видим там кучу кода и комментариев. Больше всего там кода для других контроллеров.

Нас интересует структуры типа:

 

extern DATA_PACKET INPacket;
extern DATA_PACKET OUTPacket;

и функция:

void USBCBInitEP(void)
{
    //Enable the appplication data endpoint(s)
    USBEnableEndpoint(USBGEN_EP_NUM,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
    //Prepare the OUT endpoint for the next packet that the host might try to send
    USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
}

Сами структуры находятся в файле user.h :

typedef enum
{
    READ_VERSION    = 0x00,
    /*
    READ_FLASH      = 0x01,
    WRITE_FLASH     = 0x02,
    ERASE_FLASH     = 0x03,
    READ_EEDATA     = 0x04,
    WRITE_EEDATA    = 0x05,
    READ_CONFIG     = 0x06,
    WRITE_CONFIG    = 0x07,
    */
    ID_BOARD        = 0x31,
    UPDATE_LED      = 0x32,
    SET_TEMP_REAL   = 0x33,
    RD_TEMP         = 0x34,
    SET_TEMP_LOGGING= 0x35,
    RD_TEMP_LOGGING = 0x36,
    RD_POT          = 0x37,
    RESET           = 0xFF
}TYPE_CMD;

 

/** S T R U C T U R E S ******************************************************/
typedef union DATA_PACKET
{
    BYTE _byte[USBGEN_EP_SIZE];  //For byte access
    WORD _word[USBGEN_EP_SIZE/2];//For word access(USBGEN_EP_SIZE msut be even)
    struct
    {
        BYTE CMD;
        BYTE len;
    };
    struct
    {
        unsigned :8;
        BYTE ID;
    };
    struct
    {
        unsigned :8;
        BYTE led_num;
        BYTE led_status;
    };
    struct
    {
        unsigned :8;
        WORD word_data;
    };
} DATA_PACKET;

Далее открываем файл user.c-главная функция :

 

void ProcessIO(void)
{   
    //Blink the LEDs according to the USB device status
    if(blinkStatusValid)
    {
        BlinkUSBStatus();//мигание светодиодов - статус USB
    }

 

    // User Application USB tasks
    if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;

 

    //respond to any USB commands that might have come over the bus
    PollTempOnHPCExplorer();            
    ServiceRequests();

Далее основная функция этого проекта,в которой мы все и делаем:

 

void ServiceRequests(void)
{
    BYTE index;
    
    //Check to see if data has arrived
    if(!USBHandleBusy(USBGenericOutHandle))
    {        
        //if the handle is no longer busy then the last
        //transmission is complete
       
        counter = 0;

 

        INPacket.CMD=OUTPacket.CMD;
        INPacket.len=OUTPacket.len;

 

        //process the command
        switch(OUTPacket.CMD)
        {
            case READ_VERSION:
                //dataPacket._byte[1] is len
                INPacket._byte[2] = MINOR_VERSION;
                INPacket._byte[3] = MAJOR_VERSION;
                counter=0x04;
                break;

 

            case ID_BOARD:
                counter = 0x01;
                if(OUTPacket.ID == 0)
                {
                    mLED_3_Off();mLED_4_Off();
                }
                else if(OUTPacket.ID == 1)
                {
                    mLED_3_Off();mLED_4_On();
                }
                else if(OUTPacket.ID == 2)
                {
                    mLED_3_On();mLED_4_Off();
                }
                else if(OUTPacket.ID == 3)
                {
                    mLED_3_On();mLED_4_On();
                }
                else
                    counter = 0x00;
                break;

 

            case UPDATE_LED:
                // LED1 & LED2 are used as USB event indicators.
                if(OUTPacket.led_num == 3)
                {
                    if(OUTPacket.led_status)
                    {
                        mLED_3_On();
                    }
                    else
                    {
                        mLED_3_Off();
                    }
                    counter = 0x01;
                }//end if
                else if(OUTPacket.led_num == 4)
                {
                    if(OUTPacket.led_status)
                    {
                        mLED_4_On();
                    }
                    else
                    {
                        mLED_4_Off();
                    }
                    counter = 0x01;
                }//end if else
                break;
                
            case SET_TEMP_REAL:
                temp_mode = TEMP_REAL_TIME;
                ResetTempLog();
                counter = 0x01;
                break;

 

            case RD_TEMP:
                if(AcquireTemperature())
                {
                    INPacket._byte[1] = temperature.v[0];
                    INPacket._byte[2] = temperature.v[1];
                    counter=0x03;
                }//end if

 

                break;

 

            case SET_TEMP_LOGGING:
                temp_mode = TEMP_LOGGING;
                ResetTempLog();
                counter=0x01;
                break;

 

            case RD_TEMP_LOGGING:
                counter = (valid_temp<<1)+2;  // Update count in byte
                INPacket.len = (valid_temp<<1);

 

                for(index = valid_temp; index > 0; index--)
                {
                    if(pTemp == 0)
                        pTemp = 29;
                    else
                        pTemp--;
                    INPacket._word[index] = temp_data[pTemp];
                }//end for
                
                ResetTempLog();             // Once read, log will restart
                break;

 

            case RD_POT:
                {
                    WORD_VAL w;

 

                    mInitPOT();
                    w = ReadPOT();

 

                    INPacket._byte[1] = w.v[0];
                    INPacket._byte[2] = w.v[1];

 

                    counter=0x03;
                }
                break;
                
            case RESET:
                Reset();
                break;
                
            default:
                break;
        }//end switch()
        if(counter != 0)
        {
            if(!USBHandleBusy(USBGenericInHandle))
            {
                USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,counter);
            }
        }//end if
        
        //Re-arm the OUT endpoint for the next packet
        USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
    }//end if

 

}//end ServiceRequests


Открываем проект ,который в Visual Studio. Открываем файл Form.h и видим там функцию :

 

private: System::Void ReadWriteThread_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {
            //Объявление Buffer[64] и AttacheState перенес в глобальные переменные

 

            while(true)
            {
                Buffer[0] = 0x37; //Это байт который отправляем по USB, т.е. контроллер его будет принемать в OUTPacket
                if(AttachedState == TRUE)
                {

//Функция которая отправляет пакеты по USB 1-й параметр конечная точка,2-й наш буффер,3-й сколько байт из буффера отправить,4-й сколько байт зпишит функция,5-й задержка
                    if(MPUSBWrite(EP1OUTHandle, Buffer, 1, &ActualLength, 1000))
                    {

//Функция приема данных через USB,параметры теже ,что и у предыдущей
                        if(MPUSBRead(EP1INHandle, Buffer, 3, &ActualLength, 1000))
                        {

//Принятые значения АЦП после измерения переменного резака
                            ADCValue = (Buffer[2] << 8) + Buffer[1];
                        }
                    }
                }
                else
                {
                    ADCValue = 0;
                }
                Sleep(4);    //задержка.  Otherwise, this while(true) loop executes at warp speed and can cause
                            //tangible CPU utilization increase, with no particular benefit to the application.
            }
        }

Теперь со знанием этим добавим на форму 4 кнопки,нажав 2 раза на кнопку Visual Studio создаст сама функции:

 

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
             Buffer[0] = 0x31;
             Buffer[1] = 0x00;
             if(AttachedState == TRUE)
                    MPUSBWrite(EP1OUTHandle, Buffer, 2, &ActualLength, 1000);
             Sleep(100);
         }
private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
             Buffer[0] = 0x31;
             Buffer[1] = 0x01;
             if(AttachedState == TRUE)
                    MPUSBWrite(EP1OUTHandle, Buffer, 2, &ActualLength, 1000);
             Sleep(100);
         }
private: System::Void button4_Click(System::Object^  sender, System::EventArgs^  e) {
             Buffer[0] = 0x31;
             Buffer[1] = 0x02;
             if(AttachedState == TRUE)
                    MPUSBWrite(EP1OUTHandle, Buffer, 2, &ActualLength, 1000);
             Sleep(100);
         }
private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {
             Buffer[0] = 0x31;
             Buffer[1] = 0x03;
             if(AttachedState == TRUE)
                    MPUSBWrite(EP1OUTHandle, Buffer, 2, &ActualLength, 1000);
             Sleep(100);
         }
};

Одна кнопка:

char i=0;

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
             Buffer[0] = 0x31;
             Buffer[1]=i++;
             if(AttachedState == TRUE)
                MPUSBWrite(EP1OUTHandle, Buffer, 2, &ActualLength, 1000);
             if(i>=4)
                 i=0;
             Sleep(10);
         }




Back to Top