STM32 keyboard USB HID鍵盤功能的實現
相關文章
下面編寫下USB鍵盤的程式,依然在CustomHID工程上修改。
依舊最先修改的是usb_desc.c檔案。我們從裝置描述符開始講述。
裝置描述符需要修改下bMaxPacketSize(最大包長度)域為0x08,因為被本次的工程最大通訊長度就是8位元組,正好符合USB規範,所以這裡改成0x08,還要注意在usb_prop.c的DEVICE_PROP Device_Property結構體裡註冊的最大長度也要是0x08,與裝置描述符的要相同(我們在下文說到)。這裡最好還要修改下PID和VID的域的值,以防該PID和VID對應的裝置已經在電腦裡有了驅動而導致功能不正常。
/* USB
const uint8_t Keyboard_DeviceDescriptor[KEYBOARD_SIZ_DEVICE_DESC] =
{
0x12, /*bLength:長度,裝置描述符的長度為18位元組*/
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType:型別,裝置描述符的編號是0x01*/
0x00, /*bcdUSB:所使用的USB版本為2.0*/
0x02,
0x00, /*bDeviceClass
0x00, /*bDeviceSubClass:裝置所使用的子類程式碼*/
0x00, /*bDeviceProtocol:裝置所使用的協議*/
0x08, /*bMaxPacketSize:最大包長度為8位元組*/
0x78, /*idVendor:廠商ID為0x7788*/
0x67,
0x12, /*idProduct
0x01,
0x00, /*bcdDevice:裝置的版本號為2.00*/
0x02,
1, /*iManufacturer:廠商字串的索引*/
2, /*iProduct:產品字串的索引*/
3, /*iSerialNumber:裝置的序列號字串索引*/
0x01 /*bNumConfiguration:裝置有1種配置*/
}; /* keyboard裝置描述符 */
接下去修改下配置描述符。找到介面的描述符的bNumEndpoints(該介面所使用的端點數)域,不用修改,但需要提下,還是0x02,表示使用2個端點。修改下介面描述符的nInterfaceProtocol (該介面使用的協議)域為0x01,表示是鍵盤。在輸入端點描述符中端點設定端點1為為中斷傳輸的輸入端點,設定 wMaxPacketSize:(該端點支援的最大包長度)域的值為0x08,因為本次鍵盤的工程需要向USB主機發送8位元組。在輸出端點描述符設定端點1為中斷傳輸的輸出端點,設定為中斷傳輸設定 wMaxPacketSize:(該端點支援的最大包長度)域的值為0x01,因為USB主機只會向USB從裝置傳送1個位元組。
/* USB配置描述符集合(配置、介面、端點、類、廠商)(Configuration, Interface, Endpoint, Class, Vendor */
const uint8_t Keyboard_ConfigDescriptor[KEYBOARD_SIZ_CONFIG_DESC] =
{
0x09, /*bLength:長度,裝置字串的長度為9位元組*/
USB_CONFIGURATION_DESCRIPTOR_TYPE, /*bDescriptorType:型別,配置描述符的型別編號為0x2*/
KEYBOARD_SIZ_CONFIG_DESC, /*wTotalLength:配置描述符的總長度為41位元組*/
0x00,
0x01, /*bNumInterfaces:配置所支援的介面數量1個*/
0x01, /*bConfigurationValue:該配置的值*/
0x00, /*iConfiguration:該配置的字串的索引值,該值為0表示沒有字串*/
0xC0, /* bmAttributes:裝置的一些特性,0xc0表示自供電,不支援遠端喚醒
D7:保留必須為1,D6:是否自供電,D5:是否支援遠端喚醒,D4~D0:保留設定為0*/
0x32, /*從總線上獲得的最大電流為100mA */
// 0x96, /*MaxPower:裝置需要從總線上獲取多少電流,單位為2mA,0x96表示300mA*/
/************** 介面描述符****************/
/* 09 */
0x09, /*bLength:長度,介面描述符的長度為9位元組 */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType:介面描述符的型別為0x4 */
0x00, /*bInterfaceNumber:該介面的編號*/
0x00, /*bAlternateSetting:該介面的備用編號 */
0x02, /*bNumEndpoints:該介面所使用的端點數*/
0x03, /*bInterfaceClass該介面所使用的類為HID*/
0x01, /*bInterfaceSubClass:該介面所用的子類 1=BOOT, 0=no boot */
0x01, /*nInterfaceProtocol :該介面使用的協議0=none, 1=keyboard, 2=mouse */
0, /*iInterface: 該介面字串的索引 */
/*****************HID描述符 ********************/
/* 18 */
0x09, /*bLength: HID描述符的長度為9位元組 */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID的描述符型別為0x21 */
0x10, /*bcdHID: HID協議的版本為1.1 */
0x01,
0x21, /*bCountryCode: 國家代號 */
0x01, /*bNumDescriptors: 下級描述符的數量*/
0x22, /*bDescriptorType:下級描述符的型別*/
KEYBOARD_SIZ_REPORT_DESC,/* wItemLength: 下一集描述符的長度*/
0x00,
/********************輸入端點描述符******************/
/* 27 */
0x07, /* bLength: 端點描述符的長度為7位元組*/
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: 端點描述符的型別為0x05*/
0x81, /* bEndpointAddress: 該端點(輸入)的地址,D7:0(OUT),1(IN),D6~D4:保留,D3~D0:端點號*/
0x03, /* bmAttributes: 端點的屬性為為中斷端點.
D0~D1表示傳輸型別:0(控制傳輸),1(等時傳輸),2(批量傳輸),3(中斷傳輸)
非等時傳輸端點:D2~D7:保留為0
等時傳輸端點:
D2~D3表示同步的型別:0(無同步),1(非同步),2(適配),3(同步)
D4~D5表示用途:0(資料端點),1(反饋端點),2(暗含反饋的資料端點),3(保留),D6~D7:保留,*/
0x08, /* wMaxPacketSize: 該端點支援的最大包長度為8位元組*/
0x00,
0x0A, /* bInterval: 輪詢間隔(32ms) */
/********************輸出端點描述符*******************/
/* 34 */
0x07, /* bLength: 端點描述符的長度為7位元組*/
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: 端點描述符的型別為0x05*/
0x01, /* bEndpointAddress: 該端點(輸入)的地址,D7:0(OUT),1(IN),D6~D4:保留,D3~D0:端點號*/
0x03, /* bmAttributes: 端點的屬性為為中斷端點.
D0~D1表示傳輸型別:0(控制傳輸),1(等時傳輸),2(批量傳輸),3(中斷傳輸)
非等時傳輸端點:D2~D7:保留為0
等時傳輸端點:
D2~D3表示同步的型別:0(無同步),1(非同步),2(適配),3(同步)
D4~D5表示用途:0(資料端點),1(反饋端點),2(暗含反饋的資料端點),3(保留),D6~D7:保留,*/
0x01, /* wMaxPacketSize: 該端點支援的最大包長度為位元組*/
0x00,
0x0A, /* bInterval: 輪詢間隔(32ms) */
/* 41 */
};
講到報告描述符,得將報告描述符的整個替換掉。該報告描述符定義了8位元組的輸入域,第一個位元組表示特殊件是否按下,鍵盤的特殊鍵包括:ctrl,shift,alt鍵等,該位元組D0表示Ctrl鍵,D1表示Shift鍵,D2表示Alt鍵,其他位保留。第二個位元組保留,固定值為0。第三個位元組到第八個位元組用來儲存按鍵值,如果只有一個按鍵按下,則按鍵值儲存在第三個位元組,如果有兩個或兩個以上的按鍵按下,則依次儲存在從第三位元組開始的位元組中,當然最多隻能6個按鍵同時按下,超過6個鍵值,則不響應。報告描述符還定義了一個位元組的輸出域,該位元組是是用來控制LED燈的,我們都知道鍵盤的上有幾個LED燈,比如說大小寫鍵的LED燈等,該位元組的定義:D0:Num Lock D1:Cap Lock D2:Scroll Lock D3:Compose D4:Kana,由於我一直用膝上型電腦的鍵盤,所以我也只認識前三個鍵。在這個工程,我只做了Ctrl鍵、Shift鍵、Num Lock鍵,以及A鍵。
/* HID的報告描述符*/
/*定義了8位元組傳送:
** 第一位元組表示特殊件是否按下:D0:Ctrl D1:Shift D2:Alt
** 第二位元組保留,值為0
** 第三~第八位元組:普通鍵鍵值的陣列,最多能同時按下6個鍵
**定義了1位元組接收:對應鍵盤上的LED燈,這裡只用了兩個位。
** D0:Num Lock D1:Cap Lock D2:Scroll Lock D3:Compose D4:Kana*/
const uint8_t Keyboard_ReportDescriptor[KEYBOARD_SIZ_REPORT_DESC] =
{
/*short Item D7~D4:bTag;D3~D2:bType;D1~D0:bSize
**bTag ---主條目 1000:輸入(Input) 1001:輸出(Output) 1011:特性(Feature) 1010:集合(Collection) 1100:關集合(End Collection)
** 全域性條目 0000:用途頁(Usage Page) 0001:邏輯最小值(Logical Minimum) 0010:邏輯最大值(Logical Maximum) 0011:物理最小值(Physical Minimum)
** 0100:物理最大值(Physical Maximum) 0101:單元指數(Unit Exponet) 0110:單元(Unit) 0111:資料域大小(Report Size)
** 1000:報告ID(Report ID) 1001:資料域數量(Report Count) 1010:壓棧(Push) 1011:出棧(Pop) 1100~1111:保留(Reserved)
** 區域性條目 0000:用途(Usage) 0001:用途最小值(Usage Minimum) 0010:用途最大值(Usage Maximum) 0011:識別符號索引(Designator Index)
** 0100:識別符號最小值(Designator Minimum) 0101:識別符號最大值(Designator Maximum) 0111:字串索引(String Index) 1000:字串最小值(String Minimum)
** 1001:字串最大值(String Maximum) 1010:分隔符(Delimiter) 其他:保留(Reserved)
**bType---00:主條目(main) 01:全域性條目(globle) 10:區域性條目(local) 11:保留(reserved)
**bSize---00:0位元組 01:1位元組 10:2位元組 11:4位元組*/
//0x05:0000 01 01 這是個全域性條目,用途頁選擇為普通桌面頁
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
//0x09:0000 10 01 這是個全域性條目,用途選擇為鍵盤
0x09, 0x06, // USAGE (Keyboard)
//0xa1:1010 00 01 這是個主條目,選擇為應用集合,
0xa1, 0x01, // COLLECTION (Application)
//0x05:0000 01 11 這是個全域性條目,用途頁選擇為鍵盤/按鍵
0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)
//0x19:0001 10 01 這是個區域性條目,用途的最小值為0xe0,對應鍵盤上的左ctrl鍵
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
//0x29:0010 10 01 這是個區域性條目,用途的最大值為0xe7,對應鍵盤上的有GUI(WIN)鍵
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
//0x15:0001 01 01 這是個全域性條目,說明資料的邏輯值最小值為0
0x15, 0x00, // LOGICAL_MINIMUM (0)
//0x25:0010 01 01 這是個全域性條目,說明資料的邏輯值最大值為1
0x25, 0x01, // LOGICAL_MAXIMUM (1)
//0x95:1001 01 01 這是個全域性條目,資料域的數量為8個
0x95, 0x08, // REPORT_COUNT (8)
//0x75:0111 01 01 這是個全域性條目,每個資料域的長度為1位
0x75, 0x01, // REPORT_SIZE (1)
//0x81:1000 00 01 這是個主條目,有8*1bit資料域作為輸入,屬性為:Data,Var,Abs
0x81, 0x02, // INPUT (Data,Var,Abs)
//0x95:1001 01 01 這是個全域性條目,資料域的數量為1個
0x95, 0x01, // REPORT_COUNT (1)
//0x75:0111 01 01 這是個全域性條目,每個資料域的長度為8位
0x75, 0x08, // REPORT_SIZE (8)
//0x81:1000 00 01 這是個主條目,有1*8bit資料域作為輸入,屬性為:Cnst,Var,Abs
0x81, 0x03, // INPUT (Cnst,Var,Abs)
//0x95:1001 01 01 這是個全域性條目,資料域的數量為6個
0x95, 0x06, // REPORT_COUNT (6)
//0x75:0111 01 01 這是個全域性條目,每個資料域的長度為8位
0x75, 0x08, // REPORT_SIZE (8)
//0x25:0010 01 01 這是個全域性條目,邏輯最大值為255
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
//0x19:0001 10 01 這是個區域性條目,用途的最小值為0
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
//0x29:0010 10 01 這是個區域性條目,用途的最大值為0x65
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
//0x81:1000 00 01 這是個主條目,有6*8bit的資料域作為輸入,屬相為屬性為:Data,Var,Abs
0x81, 0x00, // INPUT (Data,Ary,Abs)
//0x25:0010 01 01 這是個全域性條目,邏輯的最大值為1
0x25, 0x01, // LOGICAL_MAXIMUM (1)
//0x95:1001 01 01 這是個全域性條目,資料域的數量為2
0x95, 0x02, // REPORT_COUNT (2)
//0x75:0111 01 01 這是個全域性條目,每個資料域的長度為1位
0x75, 0x01, // REPORT_SIZE (1)
//0x05:0000 01 01 這是個全域性條目,用途頁選擇為LED頁
0x05, 0x08, // USAGE_PAGE (LEDs)
//0x19:0001 10 01 這是個區域性條目,用途的最小值為0x01,對應鍵盤上的Num Lock
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
//0x29:0010 10 01 這是個區域性條目,用途的最大值為0x02,對應鍵盤上的Caps Lock
0x29, 0x02, // USAGE_MAXIMUM (Caps Lock)
//0x91:1001 00 01 這是個主條目,有2*1bit的資料域作為輸出,屬性為:Data,Var,Abs
0x91, 0x02, // OUTPUT (Data,Var,Abs)
//0x95:1001 01 01 這是個全域性條目,資料域的數量為1個
0x95, 0x01, // REPORT_COUNT (1)
//0x75:0111 01 01 這是個全域性條目,每個資料域的長度為6bit,正好與前面的2bit組成1位元組
0x75, 0x06, // REPORT_SIZE (6)
//0x91:1001 00 01 這是個主條目,有1*6bit資料域最為輸出,屬性為:Cnst,Var,Abs
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0xc0 // END_COLLECTION
};
說到按鍵的鍵值的定義,那就要參考HID用途表(從54頁開始),截個開始的功能表吧,湊夠途中可以看到A鍵的鍵值是4。
其他的一些描述符,這裡也貼出來:
/* 語言ID描述符 */
const uint8_t Keyboard_StringLangID[KEYBOARD_SIZ_STRING_LANGID] =
{
KEYBOARD_SIZ_STRING_LANGID, /*bLength:本描述符的長度為4位元組*/
USB_STRING_DESCRIPTOR_TYPE, /*bDescriptorType:字串描述符的型別為0x03*/
0x09, /*bString:語言ID為0x0409,表示美式英語*/
0x04
}; /* LangID = 0x0409: U.S. English*/
/*廠商字串描述符*/
const uint8_t Keyboard_StringVendor[KEYBOARD_SIZ_STRING_VENDOR] =
{
KEYBOARD_SIZ_STRING_VENDOR, /*bLength:廠商字串描述符的長度*/
USB_STRING_DESCRIPTOR_TYPE, /*bDescriptorType:字串描述符的型別為0x03*/
'B' , 0, 'y', 0, ':' , 0, 'z' , 0, 'i', 0, 'y', 0,'e', 0,'3', 0, '3', 0, '4', 0 /*自定義*/
};
/*產品的字串描述符*/
const uint8_t Keyboard_StringProduct[KEYBOARD_SIZ_STRING_PRODUCT] =
{
KEYBOARD_SIZ_STRING_PRODUCT, /* bLength:產品的字串描述符*/
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType:字串描述符的型別為0x03*/
'z', 0, 'i', 0, 'y',
相關文章
下面編寫下USB鍵盤的程式,依然在CustomHID工程上修改。
依舊最先修改的是usb_desc.c檔案。我們從裝置描述符開始講述。
裝置描述符需要修改下bMaxPacketSize(最大包長度)域為0x08,因為被本次的工程最大通訊長度 rec span input div mce keil file color 事件 I.STM32 DWT時間戳功能實現 1.m3、m4實測可用。 2.精度:1/內核頻率(s)。 3.實現流程: a.先使能DWT外設,由內核調試寄存器DEM_CR的位24
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
 
最近需要使用STM32開發一個裝置通過HID協議與主機通訊,於是開始學習USB,發現USB這個體系實在太龐大了,直接看USB的例程根本看不懂,完全找不到突破口,最後在網上找到一本不錯的書《圈圈教你玩USB》,這本書能夠很好地帶你入門。列舉過程,請求,令牌,資料包,端點,描述符,這些知識都講的很清
/* USB標準裝置描述符*/
constuint8_tVirtual_Com_Port_DeviceDescriptor[VIRTUAL_COM_PORT_SIZ_DEVICE_DESC]=
{
0x12,/*bLength:長度,裝置描述符的長度為18位元組*/
USB_DEVICE_DESC
由於在報告描述符中使用了兩個Report ID,分別是0x01和0x02,前者是鍵盤的報告描述符的報告ID,後者是滑鼠的報告ID,HID的鍵盤和滑鼠傳送的資料格式參考文件:
根據文件編寫鍵盤和滑鼠的 aps ron blog 學習 隨著 cap 檢測端口 pos 文件中 HID鍵盤程序
1. 特別註意
需要特別註意,各個例程中的設備描述符,配置描述符等各種描述符都是已經配置好了的,我們需要做的只是在例程中將代碼修改為自己需要的部分即可,一般情況下是不可以串搭配的。
2. *MOS0101000000# 滑鼠左鍵按下
*MOS0102000000# 滑鼠右鍵按下
*MOS0103000000# 滑鼠中鍵按下
*MOS0100000000# 滑鼠擡起
*MOS01000a0000# 滑鼠向+X移動0x0a
*MOS01008a0000# 滑鼠向-X移動0x0a補數
*
最近用到USB,後來發現了STM32F103可以程式實現DFU,在網上搜到程式碼對比官方檔案發現是大容量FLASH的DFU,我用的是STM32F103C8T6,屬於中容量。自己對著官方例程修改了網友的程式碼,改成中容量後可以使用DFU更新韌體。修改過程中要注意幾點
1.在庫函式“void S
一個GPIO口可以 複用成內部外設的功能引腳,這裡我們利用PA9\PA10設定為UART1來舉例。
IO口對應的複用功能需要查表來確定。這個表在晶片手冊
下面這個圖講解了GPIO口的複用原理
上圖右邊左圖是複用器(AFRL(31:0)、AFRH(31:0)),要
f103的usb例程與f205的例程,內容完全不同,但究其本質萬變不離其宗
作為一個新手,我只用到了端點1 的收發,在開發時,根據例程從描述符開始下手,參考《圈圈叫我學usb》這本書,逐字理解每個描述符的含義,然後修改成自己需要的內容,之後逐個函式去理解例程的處理流程,這個時候可以試著畫一個流程 STM32USB HID class的一部分 BarCodeScanner(條碼槍)不相容的解決
硬體構成
STM32F479-EVAL 評價板 型號為FFTAA10AP條碼槍
現象
最近用CubeMX生成的USB庫做條形碼槍的USB驅動,用的是HID協議。有的條形碼槍,用標準的USB庫一次就能成功。
/*MAIN.C*/
/* Includes ------------------------------------------------------------------*/#inclu
libusb 介紹
libusb是開源的C庫,使用該庫是的使用者可以在應用程式中直接訪問 USB 裝置,無需為 USB 裝置編寫核心驅動。libusb支援多個平臺
(Linux, window, iOS),所以可以很方便地將應用程式移植到其他平臺。
linux li
1,可從官網下載STM32_USB-FS-Device_Lib_V4.0,裡面有Custom_HID例子參考。可從Custom_HID修改得到。時刻記住“自己是STM32F10X_MD系列”以及“自己不是官方demo板”即可將無用的程式碼去掉,譬如去掉ADC等等相關程式碼。2
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX 作 者:ZHS(文化人)
XX 聯絡方式:文章末尾Chat快問(或進群:471144274)
一、檢查HW原理圖,確認是否支援OTG功能(vbus是否供上電,IDDIG pin連線是否正確)二、若HW確認支援OTG功能,則按照以下方法分別開啟USB OTG功能及實現掛載:如何開啟USB OTG功能:1).在alps/mediatek/config/[project]/a 這篇文章是3個網友的文章,不過有些東西我也沒有嘗試,所以就還是把他們的方法給分別列開了!首先先回答大家的幾個疑問:1. 既然我的滑鼠都能夠在虛擬機器系統下面執行起來,還要這個破爛HID幹什麼? 不一樣的,這個是真正的HID,在裝置管理器中可以找到它們的裝置。並且是以真正的HID驅動來動起來的。我以前就是為了 逆地理編碼 地圖矢量數據 地圖地物搜索 地圖範圍搜索 地圖框選搜索 地理編碼和逆地理編碼概述地理編碼,是指將大家熟悉的地址文字描述,轉換為經緯度,如輸入某某省、某某市、某某路,在地圖上根據經緯度定位到輸入的地圖上的某個點,直觀的顯示所在位置。逆地理編碼是指將經緯度轉化為大家都能看懂文字描述 集成 sha har sse 分享 功能 秘鑰 步驟 過去 參考mob官網(http://www.mob.com/)
分享實現步驟:1.mob官網賬號註冊登錄2.進入後臺,進入ShareSDK,添加應用,生成秘鑰3.參照mob官網集成文檔,下載SDK,進入ShareSDK 相關推薦
STM32 keyboard USB HID鍵盤功能的實現
STM32 的ITM、DWT功能實現
Net Micro Framework - USB Mass Storage功能實現
STM32 自定義HID USB裝置的實現
STM32 USB Virtual COM USB轉串列埠的功能實現
基於STM32處理器的USB HID模擬滑鼠鍵盤(2)
USB小白學習之路(4)HID鍵盤程序
STM32 USB 滑鼠+鍵盤 串列埠控制
STM32 USB的DFU功能
STM32(9) GPIO口複用功能實現(正點原子) QQ群860099671
stm32 usb hid類
STM32 USB HID BarCodeReader不相容問題的解決
STM32通用定時器的基本定時器功能實現燈閃爍
STM32 USB 上位機程式實現
STM32F103C8T6的USB HID複合裝置的實現要點
MFC學習筆記 — 看小白如何實現音樂播放器(USB-HID 音效卡 wav播放)
android USB OTG功能實現
VMware直接使用主機USB HID(包含USB鍵盤滑鼠)的方法
基於矢量數據的逆地理編碼功能實現
Android開發分享功能實現步驟