이글의 전부 또는 일부, 사진, 소스프로그램 등은 저작자의 동의 없이는 상업적인 사용을 금지합니다. 또한, 비상업적인 목적이라하더라도 출처를 밝히지 않고 게시하는 것은 금지합니다.

이번 글에서는 STM32F103C8T6의 USB 포트를 CDC(Communication Device Class)로 사용해 보기로 합니다. STM32F 시리즈에서 USB를 CDC로 사용하면 PC측에서는 serial 포트로 인식합니다. MCU측 디바이스 드라이버는 HAL 라이브러리에서 다 처리하고, PC측 드라이버는 ST사에서 제공해 주기 때문에 사용자는 별로 할 일이 없습니다.

1. 프로젝트 만들기

앞의 글 STM32F103으로 ESP8266 제어하기 - USART 프로그래밍에서 만들었던 프로젝트에 CDC 기능을 추가하겠습니다.

 

STM32CubeMX로 STM32F103AIT.ioc 파일을 열어 위의 그림에서와 같이 [Connectivity]에서 [USB]를 선택하고, [USB Mode and Configuration]에서 Device(FS) 앞에 체크합니다.


 



[Middleware]를 선택한 다음에 [USB_DEVICE]를 선택한 다음에, 오른쪽의 [USB_DEVICE Mode and Configuration]에서 [Class For FS IP] 항목에서 Communication Device Class를 선택합니다.
위 그림에는 없지만, 화면의 파란색 메뉴의 [Clock Configuration]에 조그맣게 빨간 표시가 붙어 있습니다. USB를 FS(Full Speed)로 사용하려면 USB 클럭이 48MHz로 설정해야 하는데, 현재 그렇게 설정되어 있지 않아서 나타나는 경고입니다. [Configuration Clock] 메뉴를 클릭하면 다음과 같은 팝업 상자가 나옵니다. [Yes] 버튼을 클릭합니다.



위 작업의 결과 몇군데 값이 달라집니다. HCLK를 다시 72MHz로 입력하고 APB1 prescaler와 APB2 prescaler의 값을 다음 그림과 같게 맞추어 줍니다. APB1 버스에는 TIM2~7, USART2, USART3, SPI2, SPI3, I2C 등이 연결되어 있고, APB2 버스에는 모든 GPIO 포트들과 USART1, SPI1, TIM1, TIM8 등이 연결되어 있습니다.

 

 

 

[GENERATE CODE] 버튼을 눌러 코드를 생성합니다.>



 

2. 코딩 하기


코드를 생성하고 True Studio를 실행하여 프로젝트를 열면 다음 그림에 붉은 사각형으로 표시한 바와 같이 많은 소스프로그램들이 추가됩니다.




코드는 미세먼지 센서 SDS011 사용하기(개선편)의 맨 마지막에 첨부한 STM32F130AIR.zip 파일에 있는 것을 기본으로 합니다. 그 소스프로그램들을 STM32F103으로 ESP8266 제어하기 - USART 프로그래밍에서 ESP8266을 다루기 위해서 uart.h와 uart.c 등을 약간 수정하였습니다. STM32F103으로 ESP8266 제어하기 - USART 프로그래밍에서 수정한 소스프로그램을 사용합니다.

CDC를 시리얼 통신으로 다루기 때문에, USART3가 사용한 것과 같은 queue를 CDC에서도 사용하도록 queue를 하나 더 추가합니다. USART3는 WIFI 모듈에서 사용하기 때문에 queue 이름을 WifiQueue라 붙였습니다. CDC에서 사용할 queue는 CDCQueue로 이름을 붙이겠습니다. uart.h와 uart.c에 각각 CDCQueue를 다음과 같이 선언 및 정의합니다. uart.h와 uart.c 모두 WifiQueue는 이미 존재하고 있는 것이지만, 입력하는 위치를 알리고자 같이 나열한 것입니다. 실제로는 CDCQueue가 있는 행만 추가로 입력합니다.

/* uart.h */
extern UARTQUEUE WifiQueue;
extern UARTQUEUE CDCQueue;

 

/* uart.c */
UARTQUEUE WifiQueue;
UARTQUEUE CDCQueue;

 


CDC로부터 데이터가 들어오면 인터럽트가 걸리면서 CDC_Receive_FS() 함수가 호출됩니다. 이 함수는 [Src] 폴더 안에 있는 usdb_cdc_if.c 파일 안에 있습니다. 이 함수를 다음과 같이 수정합니다. 실제로 입력하는 내용은 주석 ①, ②, ③이 달려 있는 세 행입니다. ① 행은 컴파일할 때에 에러가 발생하지 않도록 헤더 파일을 포함시키기 위함입니다. ②행과 ③행은 CDC로 전달된 데이터들을 CDCQueue로 집어 넣는 역할을 합니다.

/* USER CODE BEGIN INCLUDE */
#include "uart.h"                                       // ①

/* USER CODE END INCLUDE */

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  for(int16_t i = 0;i < *Len;i++)                      // ②
    PutDataToUartQueue(&CDCQueue, Buf[i]);             // ③
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

 



마지막으로 main.c에 다음의 내용들을 추가합니다. 주석에 ① 기호가 있는 행만 입력합니다. 다른 코드들은 입력할 위치를 알리기 위해 같이 서술한 것입니다.

 

/* USER CODE BEGIN Includes */
#include "M19264Display.h"
#include "GlcdDisplay.h"
#include "AM2302.h"
#include "uart.h"
#include "usbd_cdc_if.h"                                       // ①

/* USER CODE END Includes */
  GlcdInitialize();
  InitUartQueue(&WifiQueue);
  InitUartQueue(&CDCQueue);                                       // ①
  HAL_UART_Receive_IT(&SDS011, SDS011Msg, 1);
  HAL_UART_Receive_IT(&WIFI, WifiQueue.Buffer, 1);



다음은 main.c의 main() 함수 안의 while() 문 안에 들어 가는 내용입니다. 이 코드는 if(intFlag & INT_UART_SDS011) 문이 끝나는 곳에 이어서 추가합니다.

    if(CDCQueue.data > 0)            // if data exist in CDCQueue, send them to ESP8266(USART3)
    {
    	ret = GetDataFromUartQueue(&CDCQueue);
    	HAL_UART_Transmit(&WIFI, &ret, 1, 10);
    }
    if(WifiQueue.data > 0)            // if data arrived from ESP8266, send them to CDC.
    {
    	ret = GetDataFromUartQueue(&WifiQueue);
    	CDC_Transmit_FS(&ret, 1);
    }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */


위 소스 코드에 간단히 주석을 붙였습니다. CDCQueue에 데이터가 있으면, GetDataFromUartQueue() 함수를 호출해서 데이터를 꺼내옵니다. 이 데이터를 HAL 드라이버가 제공하는 HAL_UART_Transmit() 함수를 이용해서 WIFI 포트로 전송합니다.


같은 방법으로 WifiQueue에 데이터가 있으면, GetDataFromUartQueue() 함수로 데이터 하나를 가져와서 CDC로 전송합니다. CDC로 전송하는 함수는 CDC_Transmit_FS()로 [Src] 폴더 안의 usbd_cdc_if.c 파일 안에 있습니다.



ST-LINK/V2를 이용해서 프로그램을 기록한 후에 전원을 완전히 제거했다가 다시 연결하면, 특별한 조치를 하지 않아도 CDC를 윈도우 장치 관리자에서 시리얼 포트로 인식합니다. 제 기억으로는 True Studio를 설치할 때에 CDC 디바이스 드라이버를 설치할 것인지를 물었던 것 같습니다. STLINK Utility를 설치할 때에도 ST-LINK/V2와 시리얼 드라이버를 설치했던 것 같습니다.



필자의 컴퓨터에서는 USB 직렬 장치(COM3)로 잡혔습니다. 만약 시리얼 포트로 잡히지 않으면 디바이스 드라이버를 설치하면 됩니다. ST Microelectronics 홈페이지의 CDC 디바이스 드라이버 페이지를 링크합니다. 저곳에서 드라이버를 다운받아 설치하면 STMicroelectronics Virtual COM Port(COM3) 이런 형태의 이름을 가진 시리얼 포트로 설정될 것입니다.


이번 글도 그림이 많아서 길어졌습니다만, USB CDC 드라이버의 거의 모든 작업을 ST에서 제공해주기 때문에 실제 코딩은 20행도 안되는 것 같습니다.


OBS 프로그램으로 간단히 캡쳐한 동영상 첨부합니다. 터미널 프로그램에서 AT, AT+CWLAP 명령을 보내 봤습니다. 중간에 잘못 명령을 보내서 ERROR 한 번 나옵니다.

동영상 편집하기가 귀찮아서 앞뒤의 불필요한 부분도 그냥 올립니다.

 

 

 

 


동작하는 소스프로그래을 zip 파일로 압축하여 첨부합니다.

STM32F103AIR.zip










블로그 이미지

엠쿠스

Microprocessor(STM32, AVR)로 무엇인가를 만들어 보고자 학습 중입니다.

,