Možná jste se podivili při čtení nadpisu článku, vždyť USB Vituální sériový port jsme tu již měli. Ano, publikovali jsme zde zdrojové kódy pro STM32F4 Discovery kit, který jej změnil v dané USB zařízení. Ale kolega miran upravil můj zdrojový kód pro STM32F103, takže pokud máte tento mcu, tak zde je pro vás ověřená varianta zdrojového kódu ve verzi pro Atollic. Za zaslání kódu děkujeme!



VCP komunikace pro stm32F103


Když jsem si zakoupil desku stm32F103-Z/UET CORE BOARD, tak jsem potřeboval ověřit její připojení k PC přes USB.
Mard mi poskytl demo pro VCP (CDC) připojení, které sice bylo pro jiný typ procesoru, ale byl předpoklad, že bude fungovat po úpravě i na stm32F103. Původní demo přijímalo data přes USART a posílalo je zpět přes USB VCP a naopak. Protože potřebuji komunikaci pouze po USB, napsal jsem novou funkci, která zajišťuje poslání dat do PC přes USB.


/*******************************************************************************
* Function Name  : USB_To_USB_Send_Data.
* Description    : send the received data from USB to the USB.
* Input          : data_buffer: data address.
                   Nb_bytes: number of bytes to send.
* Return         : none.
*******************************************************************************/

void USB_To_USB_Send_Data(uint8_t* data_buffer, uint32_t Nb_bytes)
{

   /* Write the data to the USB endpoint */
  USB_SIL_Write(EP1_IN, data_buffer, Nb_bytes);

#ifndef STM32F10X_CL
  SetEPTxValid(ENDP1);
#endif /* STM32F10X_CL */

}



Funkce zasílá data z buferu přes USB. I když její název zní možná trochu nelogicky, ponechal jsem ho tak jak vznikl přepsáním z původní funkce (můžete si to přejmenovat, funkce se nachází souboru hw_config.c)

Další změnu jsem provedl na nastavení GPIO pinů pro ovládání LED. Na výše uvedeném boardu dojde při příjmu znaku k rozsvícení nebo zhasnutí LED. Nastavení konfigurace zajišťuje následující kód umístěný v hw_config.c.


/*******************************************************************************
* Function Name  : Init_GPIO_pins
* Description    : Configures GPIO
* Input          : None.
* Return         : None.
*******************************************************************************/

void Init_GPIO_pins(void)
{
        /* Configure the GPIO_LED pin */
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

  GPIO_Init(GPIOC,&GPIO_InitStructure)

}



Pro využití možností stm32F103 jsem provedl úpravu nastavení hodin na 72MHz úpravou následujících řádků kódu v hw_config.c

/* PCLK1 = HCLK/2 = 36 MHz */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PCLK2 = HCLK = 72 MHz */
    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);



Následně ještě bylo nutné upravit hodiny pro USB:

/* Select USBCLK source */
  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);



Hlavní programová smyčka v main.c zajišťuje při přijetí znaku přes USB jeho zaslání zpět. Pokud je přijat znak „t“ je zaslán zpět soubor 127 ASCII znaků začínající od čísla znaku 32 (mezera).

while (1)
  {
    if ((count_out != 0) && (bDeviceState == CONFIGURED))
    {
      if(buffer_out[0] == 't')       // Jestliže byl přijat znak t
        USB_To_USB_Send_Data(&buffer_pokus[0], 127);  // Pošli 127 znaků
      else
        USB_To_USB_Send_Data(&buffer_out[0], count_out);  // Pošli přijatý znak

      count_out = 0;
      if(LEDON)
        { GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);   // Zhasni LED
          LEDON = 0;
        }
      else
       {GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);      // Rozsvit LED
        LEDON = 1;
       }
    }
  }



Experimentálně ověřené zvýšení rychlosti přenosu

Při pokusech o zvýšení přenosové rychlosti jsem laboroval s velikostí bufferu a změnil jsem jeho nastavení v souboru usb_desc.h následovně

#define VIRTUAL_COM_PORT_DATA_SIZE 128
// #define VIRTUAL_COM_PORT_DATA_SIZE 64

Pokud by byl s komunikací problém, tak vraťte původní hodnotu 64 (do buferu pak nesmíte předávat více dat).
Pro velikost 128 byla komunikace rychlejší, po nějakém zdůvodnění jsem nepátral.


Závěr

Pro komunikaci s programem můžete využít PC hyperterminál jehož nastavení je popsáno v 4. dílu k STM32F4 Discovery kitu (zde).

Pro určité zpřehlednění programu jsem odstranil některé části kódu pro USART, program je však stále „prošpikován“ původním kódem v jehož odstraňování lze dále pokračovat.

Velkou výhodou VCP (CDC) komunikace je její jednoduchost, kdy se nemusíte zabývat žádnými endpointy, nebo enumerací a můžete používat na obou stranách funkce pro zasílání a příjem dat přes buffery.

K projektu přikládám schéma boardu na kterém jsem VCP komunikaci zkoušel. Programoval jsem pomocí ST-Linku z Discovery kitu.


Odkazy

Zdrojový projekt USB VCP je ke stažení zde.
PDF soubor se schématem boardu s STM32F103 je zde.

Autorem textu je miran.