主機(jī)環(huán)境:Windows 7 SP1
開發(fā)環(huán)境:MDK5.14
目標(biāo)板:STM32F103C8T6
開發(fā)庫:STM32F1Cube庫和STM32_USB_Device_Library
現(xiàn)在開始分析VCP示例代碼,從最簡單的usbd_desc開始。USB設(shè)備使用描述符來報告其功能特性,描述符是一個已知格式的數(shù)據(jù)結(jié)構(gòu),USB規(guī)范中定義了以下幾種描述符:Device(設(shè)備)、Device_Qualifier(設(shè)備限定)、Configuration(配置)、Other_Speed_Configuration(其他速度配置)、Interface(接口)、Endpoint(端點(diǎn))、String(字符串)。usbd_desc文件主要提供USB字符串描述符,字符串描述符對于設(shè)備來說是可選的,是對其他描述符的文字說明,且字符串描述符使用UNICODE編碼,同時字符串描述符支持多國語言,當(dāng)請求字符串描述符時需要使用16禁止的LANGID來指定所期望的語言。使用字符串索引0來獲取設(shè)備所支持的語言。字符串描述的數(shù)據(jù)結(jié)構(gòu)如下所示:
第一個字節(jié)是該數(shù)據(jù)結(jié)構(gòu)的字節(jié)長度,第二個字節(jié)是字符串描述符類型,后面的字節(jié)是字符串內(nèi)容。有關(guān)字符串描述符類型值的定義在USB2.0規(guī)范的9.4章節(jié)的表9-5中,如下:
可以看到字符串描述符類型的值為常量3,與之相符的在usbd_def.h文件中95行有如下定義:
#define USB_DESC_TYPE_DEVICE 1
#define USB_DESC_TYPE_CONFIGURATION 2
#define USB_DESC_TYPE_STRING 3
#define USB_DESC_TYPE_INTERFACE 4
#define USB_DESC_TYPE_ENDPOINT 5
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
#define USB_DESC_TYPE_BOS 0x0F
查看usbd_desc.h頭文件,內(nèi)容很簡單
/**
******************************************************************************
* @file USB_Device/CDC_Standalone/Inc/usbd_desc.h
* @author MCD Application Team
* @version V1.2.0
* @date 31-July-2015
* @brief Header for usbd_desc.c module
******************************************************************************
* @attention
*
*
? COPYRIGHT(c) 2015 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC_H
#define __USBD_DESC_H
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define DEVICE_ID1 (0x1FFFF7E8)
#define DEVICE_ID2 (0x1FFFF7EC)
#define DEVICE_ID3 (0x1FFFF7F0)
#define USB_SIZ_STRING_SERIAL 0x1A
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
extern USBD_DescriptorsTypeDef VCP_Desc;
#endif /* __USBD_DESC_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
這里有三個宏定義DEVICE_ID1、DEVICE_ID2、DEVICE_ID3,這三個值是STM32芯片產(chǎn)品唯一身份標(biāo)識,可以用作USB字符序列號(96位),該寄存器是只讀的。詳情參考STM32參考手冊的設(shè)備電子簽名章節(jié)。此外,該文件還引用了一個數(shù)據(jù)結(jié)構(gòu)USBD_DescriptorsTypeDef,該結(jié)構(gòu)是一個函數(shù)指針集合。
/* USB Device descriptors structure */
typedef struct
{
uint8_t *(*GetDeviceDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetLangIDStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetManufacturerStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetProductStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetSerialStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetConfigurationStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
uint8_t *(*GetInterfaceStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
#if (USBD_LPM_ENABLED == 1)
uint8_t *(*GetBOSDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length);
#endif
} USBD_DescriptorsTypeDef;
用于獲取各種描述符,主要是獲取字符串描述符,與之對應(yīng)的下標(biāo)在usbd_def.h的66行
#define USBD_IDX_LANGID_STR 0x00
#define USBD_IDX_MFC_STR 0x01
#define USBD_IDX_PRODUCT_STR 0x02
#define USBD_IDX_SERIAL_STR 0x03
#define USBD_IDX_CONFIG_STR 0x04
#define USBD_IDX_INTERFACE_STR 0x05
注意USBD_DescripotrsTypeDef結(jié)構(gòu)中的GetDeviceDescriptor不是獲取字符串描述符,同時前面提到使用索引號0來獲取設(shè)備所支持的語言,因此這里定義USBD_IDX_LANGID_STR為0,至于其他索引號值是否有標(biāo)準(zhǔn)定義,暫時為找到出處。該結(jié)構(gòu)實體定義在usbd_desc.c文件中如下
USBD_DescriptorsTypeDef VCP_Desc = {
USBD_VCP_DeviceDescriptor,
USBD_VCP_LangIDStrDescriptor,
USBD_VCP_ManufacturerStrDescriptor,
USBD_VCP_ProductStrDescriptor,
USBD_VCP_SerialStrDescriptor,
USBD_VCP_ConfigStrDescriptor,
USBD_VCP_InterfaceStrDescriptor,
};
稍后來看各個函數(shù),在usbd_desc.c文件的前面有如下定義
#define USBD_VID 0x0483
#define USBD_PID 0x5740
#define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#define USBD_PRODUCT_FS_STRING "STM32 Virtual ComPort in FS Mode"
#define USBD_CONFIGURATION_FS_STRING "VCP Config"
#define USBD_INTERFACE_FS_STRING "VCP Interface"
USBD_VID和USBD_PID分別是廠商ID、產(chǎn)品ID,這兩個ID需要向USB組織申請,不是免費(fèi)的,當(dāng)前該ID列表可以在以下網(wǎng)址查看http://www.linux-usb.org/usb.ids,通過查看可知0x0483是STMicroelectronics申請的,0x5740對應(yīng)的產(chǎn)品是STM32F407,ST完整列表如下:
語言ID0x409指的是English(United States),該值可以在USB_LANGIDs.pdf文檔中找到,如下:
現(xiàn)在來分析獲取描述符函數(shù),首先從獲取語言ID開始,將代碼整合一下,方便查看,如下:
#define USB_LEN_LANGID_STR_DESC 0x04
/* USB Standard Device Descriptor */
const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC]=
{
USB_LEN_LANGID_STR_DESC,
USB_DESC_TYPE_STRING,
LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING),
};
/**
* @brief Returns the LangID string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_VCP_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_LangIDDesc);
return (uint8_t*)USBD_LangIDDesc;
}
USBD_VCP_LangIDStrDescriptor函數(shù)最終是要返回一個語言ID數(shù)組結(jié)構(gòu),且以UNICODE編碼,如下:
由于這里只支持英文,因此這里bLength為4,bDescriptorType為3,LANGID為0x409。產(chǎn)品、廠商、配置、接口字符串描述符所對應(yīng)的函數(shù)是同一種結(jié)構(gòu),說明一個即可
/**
* @brief Returns the manufacturer string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_VCP_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
這里是將ASCII編碼的字符串轉(zhuǎn)成UNICODE編碼的字符串,同時UNICODE編碼的字符串不是以NULL作為結(jié)束。USBD_GetString()方法定義在usbd_ctlreq.c文件中,如下:
/**
* @brief USBD_GetString
* Convert Ascii string into unicode one
* @param desc : descriptor buffer
* @param unicode : Formatted string buffer (unicode)
* @param len : descriptor length
* @retval None
*/
void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len)
{
uint8_t idx = 0;
if (desc != NULL)
{
*len = USBD_GetLen(desc) * 2 + 2;
unicode[idx++] = *len;
unicode[idx++] = USB_DESC_TYPE_STRING;
while (*desc != '\0')
{
unicode[idx++] = *desc++;
unicode[idx++] = 0x00;
}
}
}
/**
* @brief USBD_GetLen
* return the string length
* @param buf : pointer to the ascii string buffer
* @retval string length
*/
static uint8_t USBD_GetLen(uint8_t *buf)
{
uint8_t len = 0;
while (*buf != '\0')
{
len++;
buf++;
}
return len;
}
接著分析獲取序列號字符串描述符方法,整理如下:
/**
* @brief Returns the serial number string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_VCP_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique ID*/
Get_SerialNum();
return USBD_StringSerial;
}
/**
* @brief Create the serial number string descriptor
* @param None
* @retval None
*/
static void Get_SerialNum(void)
{
uint32_t deviceserial0, deviceserial1, deviceserial2;
deviceserial0 = *(uint32_t*)DEVICE_ID1;
deviceserial1 = *(uint32_t*)DEVICE_ID2;
deviceserial2 = *(uint32_t*)DEVICE_ID3;
deviceserial0 += deviceserial2;
if (deviceserial0 != 0)
{
IntToUnicode (deviceserial0, &USBD_StringSerial[2] ,8);
IntToUnicode (deviceserial1, &USBD_StringSerial[18] ,4);
}
}
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)
{
uint8_t idx = 0;
for( idx = 0 ; idx < len ; idx ++)
{
if( ((value >> 28)) < 0xA )
{
pbuf[2* idx] = (value >> 28) + '0';
}
else
{
pbuf[2* idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2* idx + 1] = 0;
}
}
這里取序列號只取了48位,取了deviceserial0的32位和deviceserial1的高16位,注意IntToUnicode()方法即可,以16進(jìn)制進(jìn)行轉(zhuǎn)換,從高位開始,序列號字符串描述符字節(jié)長度為0x1A=12*2(序列號內(nèi)容)+2(前面兩個字節(jié))。至此,字符串描述符的獲取分析完畢,還剩下一個設(shè)備描述符的獲取,如下:
/* USB Standard Device Descriptor */
const uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC]= {
0x12, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
0x00, /* bcdUSB */
0x02, /* USB2.0 spec*/
0x00, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
LOBYTE(USBD_VID), /* idVendor */
HIBYTE(USBD_VID), /* idVendor */
LOBYTE(USBD_PID), /* idVendor */
HIBYTE(USBD_PID), /* idVendor */
0x00, /* bcdDevice rel. 2.00 */
0x02,
USBD_IDX_MFC_STR, /* Index of manufacturer string */
USBD_IDX_PRODUCT_STR, /* Index of product string */
USBD_IDX_SERIAL_STR, /* Index of serial number string */
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
}; /* USB_DeviceDescriptor */
/**
* @brief Returns the device descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_VCP_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(hUSBDDeviceDesc);
return (uint8_t*)hUSBDDeviceDesc;
}
設(shè)備描述符的獲取主要看hUSBDDeviceDesc數(shù)組結(jié)構(gòu),該數(shù)組長度為18個字節(jié),與之對應(yīng)的數(shù)據(jù)結(jié)構(gòu)在USB2.0規(guī)范的9.6章節(jié)有說明,一個設(shè)備只有一個設(shè)備描述符,設(shè)備描述符數(shù)據(jù)結(jié)構(gòu)如下:
根據(jù)此結(jié)構(gòu)來分析hUSBDDeviceDesc內(nèi)容的含義,符合USB2.0規(guī)范,bDeviceClass置0,表明一個配置里每個接口指定其各自的類信息同時不同的接口獨(dú)立地操作。由于bDeviceClass字段置0,因此bDeviceSubClass字段同樣置0。bDeviceProtocol置0,設(shè)備不使用特定類協(xié)議。端點(diǎn)0最大包大小為64字節(jié),接著填充廠商ID和產(chǎn)品ID,bcdDevice標(biāo)記設(shè)備穩(wěn)定版本,這里為2.0版本,當(dāng)然可以修改該值。iManufacturer、iProduct、iSerialNumber分別是在字符串描述符中各自的索引號,前面有提到。最后標(biāo)記配置數(shù)為1。USB設(shè)備可以有一個或多個配置,每個配置有一個或多個接口,每個接口有一個或多個端點(diǎn)。至此,usbd_desc文件分析完畢。主要為各個描述符的獲取。
上一篇:STM32 USB學(xué)習(xí)筆記4
下一篇:STM32 USB學(xué)習(xí)筆記2
推薦閱讀
史海拾趣
ECS-B公司是一家以生產(chǎn)高端電子產(chǎn)品為主的企業(yè)。在競爭激烈的電子行業(yè)中,ECS-B公司深知品質(zhì)是企業(yè)生存和發(fā)展的關(guān)鍵。因此,公司非常重視品質(zhì)管理,從原材料采購、生產(chǎn)過程到成品檢驗,都實行嚴(yán)格的質(zhì)量控制。ECS-B公司還建立了完善的品質(zhì)管理體系,通過持續(xù)改進(jìn)和優(yōu)化生產(chǎn)流程,提升產(chǎn)品的品質(zhì)水平。正是憑借卓越的品質(zhì)和可靠的性能,ECS-B公司的產(chǎn)品在市場上贏得了良好的口碑和廣泛的認(rèn)可。
進(jìn)入新世紀(jì),Bytesonic Corporation面臨著新的挑戰(zhàn)和機(jī)遇。為了更好地適應(yīng)市場變化和提升競爭力,公司在1999年11月進(jìn)行了改制,資本增加至5700萬新臺幣。這一改制不僅增強(qiáng)了公司的財務(wù)實力,也為其在未來的發(fā)展中注入了新的活力。
以上是基于已知信息對Bytesonic Corporation公司發(fā)展故事的概述。如需更詳細(xì)、具體的故事內(nèi)容,建議查閱公司官方資料、新聞報道或行業(yè)分析報告,以獲取更全面、準(zhǔn)確的信息。
隨著臺灣本土市場的逐漸飽和,Bytesonic Corporation開始將目光投向更廣闊的大陸市場。1996年7月,公司在中國廣東省東莞市石街鎮(zhèn)成立了分公司,邁出了進(jìn)軍大陸市場的第一步。這一決策不僅為公司帶來了更多的商機(jī),也為其在亞洲乃至全球市場的布局打下了堅實的基礎(chǔ)。
為了進(jìn)一步加強(qiáng)對大陸市場的投資和管控,Bytesonic Corporation在1998年5月在英屬維爾京群島成立了控股公司——劍橋電子有限公司。這一舉措不僅提升了公司的資本運(yùn)作能力,也為其在全球范圍內(nèi)的業(yè)務(wù)拓展提供了更多的便利。
隨著通信技術(shù)的不斷進(jìn)步,對微波器件的性能要求也越來越高。Analog Microwave Design公司敏銳地捕捉到了這一市場變化,開始致力于研發(fā)更高性能的微波器件。經(jīng)過多次試驗和改進(jìn),公司成功開發(fā)出了一款具有低損耗、高穩(wěn)定性的微波放大器,這一創(chuàng)新產(chǎn)品在市場上引起了熱烈反響。公司憑借這一技術(shù)突破,迅速擴(kuò)大了市場份額,并樹立了行業(yè)內(nèi)的技術(shù)領(lǐng)先地位。
Embedded Planet公司深知人才是企業(yè)發(fā)展的核心驅(qū)動力。因此,公司一直致力于培養(yǎng)和吸引優(yōu)秀人才,建立了一支高效、專業(yè)的團(tuán)隊。公司為員工提供豐富的培訓(xùn)和發(fā)展機(jī)會,鼓勵員工不斷學(xué)習(xí)和創(chuàng)新。同時,公司還注重團(tuán)隊建設(shè)和文化塑造,營造了一個積極向上、團(tuán)結(jié)協(xié)作的工作氛圍。這些努力使得Embedded Planet公司成為了一個充滿活力和創(chuàng)造力的企業(yè)。
若干高功率微波(HPM)技術(shù)已走向成熟,它們正在從工程與制造階段向戰(zhàn)術(shù)武器階段過渡,目前很可能在進(jìn)攻伊拉克的戰(zhàn)斗中看到首次使用微波武器.本文簡要介紹美、英、俄三國發(fā)展HPM武器技術(shù)的計劃,評述了幾種典型HPM武器研究的重大進(jìn)展,最后討論了HPM武器 ...… 查看全部問答∨ |
如果設(shè)計稍顯復(fù)雜,那么對底層細(xì)節(jié)的過多關(guān)注就會成為一種累贅。 試想我們平時在電腦上編寫C程序,比如在顯示器上輸出一行字,我們只用一句printf()即可完成,至于打印命令怎么傳到顯示芯片上,哪個芯片管腳怎么 變化,又怎么傳到顯 ...… 查看全部問答∨ |
113586004 已開通了《智能家居系統(tǒng)》討論群 希望參加《智能家居系統(tǒng)》的網(wǎng)友添加113586004群,在群內(nèi)討論問題。 [ 本帖最后由 zhaojun_xf 于 2010-7-31 10:28 編輯 ]… 查看全部問答∨ |
我使用串口與模塊進(jìn)行通信,來收發(fā)中文短信,并將串口InputMode屬性設(shè)為文本方式。 當(dāng)通過串口,來接收CDMA模塊發(fā)送的漢字Unicode碼時,發(fā)現(xiàn),串口已將Unicode碼以字節(jié)為單位轉(zhuǎn)換為ASCII字符。 現(xiàn)在,我想要恢復(fù)這一過程,將ASCII字符還原為Unico ...… 查看全部問答∨ |
2440學(xué)習(xí)(六)ADC與蜂鳴器驅(qū)動 本帖最后由 lonerzf 于 2014-7-23 10:14 編輯 字符驅(qū)動學(xué)習(xí)了幾天也差不多大概知道怎么寫了。 但是,如果和外設(shè)模塊打交道,又會遇到問題,其中就有地址空間的轉(zhuǎn)換。 主要參考文章: www.360doc.com/content/10/1011/07/1317564_60018145.shtml ...… 查看全部問答∨ |
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- API調(diào)用小記(Touchdesigner和ESP32)
- 關(guān)于ESP32/8266使用async-mqtt-client庫的一些基本介紹
- 座椅、天窗、電動尾門應(yīng)用 國產(chǎn)車規(guī)級高壓霍爾效應(yīng)傳感器推薦
- 突發(fā)!又一車企車機(jī)“崩了”
- 寧德時代為陳立泉院士頒發(fā)“卓越貢獻(xiàn)獎”
- 一文速覽吉利雷神 AI 電混 2.0 發(fā)布會重點(diǎn)
- 2025年1-4月ADAS供應(yīng)商裝機(jī)量排行榜:頭部集中與國產(chǎn)突圍并存
- 國內(nèi)飛行汽車無線通信測試成功,通信安全新突破
- SPAD席卷車載激光雷達(dá)市場
- 大聯(lián)大品佳集團(tuán)推出基于Microchip和ams OSRAM產(chǎn)品的10Base-T1S萬級像素大燈方案
- 哈曼推出采用三星Neo QLED技術(shù)的全新顯示屏
- Syntiant推出超低功耗汽車AI創(chuàng)新技術(shù) 提升車輛安全性和用戶體驗
- 王傳福:中國自主品牌電動車技術(shù)已超越外資
- 恩智浦將嵌入式AI環(huán)境延伸至邊緣處理應(yīng)用
- 上汽乘用車與京東方精電簽訂協(xié)議,推進(jìn)智能座艙顯示技術(shù)落地應(yīng)用
- 發(fā)展集成電路 IC Park如何做到取勢明道優(yōu)術(shù)?
- 王瑀:用戶需求導(dǎo)向下的三種動力電池解決方案
- Google的AI預(yù)訂服務(wù)Duplex仍需經(jīng)常受到人工干預(yù)
- 無人機(jī)大疆的美國往事
- 大疆將從2020年開始為無人機(jī)裝配飛機(jī)與直升機(jī)探測器
- 華南展(IARS)現(xiàn)場直擊:多款機(jī)器人創(chuàng)新方案同場競技
- 繼清華、北大,又一高校宣布增設(shè)機(jī)器人相關(guān)本科專業(yè)