STM32F103 USB固件开发-移植Custom_HID
1.功能介绍
Custom_HID是ST官方提供的一个USB HID例程代码,可以在电脑端通过HID接口控制硬件端的LED灯。
2.硬件电路
LED阳极接高电平,采用阴极驱动,低电平点亮,高电平熄灭,电路下图:
3.移植Custom_HID例程
2.1 把STM32_USB-FS-Device_Lib_V4.1.0这个目录拷贝出来
2.2 把拷贝出来的STM32_USB-FS-Device_Lib_V4.1.0修改为Custom_HID
2.3 进入Projects目录,将Custom_HID以外的代码全部删除
整理后的目录结构如下:
2.4 进入Projects\Custom_HID\MDK-ARM目录,打开keil工程文件Project.uvprojx
2.5 删除不用的代码,删除后如下图:
2.6 配置魔术棒-Device,选择芯片方案为STM32F103ZE
2.7 配置魔术棒-C/C++,STM32F10X_MD修改为STM32F10X_HD。全部内容是:USE_STDPERIPH_DRIVER,STM32F10X_HD,USE_STM3210B_EVAL
2.8 编译,我这里是可以正常编译通过,并且可以生成HEX文件。
2.9 使用烧录工具将HEX文件烧录到开发板上。
2.10 将USB2.0连接到电脑,电脑可以识别到HID设备,说明基本的USB固件已经运行正常。
4.代码修改
\Custom_HID\Utilities\STM32_EVAL\STM3210B_EVAL\stm3210b_eval.h
/** @addtogroup STM3210B_EVAL_LOW_LEVEL_LED
* @修改为实际使用的IO口
*/
#define LEDn 4
#define LED1_PIN GPIO_Pin_0 // GPIO_Pin_6
#define LED1_GPIO_PORT GPIOC
#define LED1_GPIO_CLK RCC_APB2Periph_GPIOC
#define LED2_PIN GPIO_Pin_1 // GPIO_Pin_7
#define LED2_GPIO_PORT GPIOC
#define LED2_GPIO_CLK RCC_APB2Periph_GPIOC
#define LED3_PIN GPIO_Pin_2 // GPIO_Pin_8
#define LED3_GPIO_PORT GPIOC
#define LED3_GPIO_CLK RCC_APB2Periph_GPIOC
#define LED4_PIN GPIO_Pin_3 // GPIO_Pin_9
#define LED4_GPIO_PORT GPIOC
#define LED4_GPIO_CLK RCC_APB2Periph_GPIOC
\Custom_HID\Utilities\STM32_EVAL\STM3210B_EVAL\stm3210b_eval.c
void STM_EVAL_LEDInit(Led_TypeDef Led)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable the GPIO_LED Clock */
RCC_APB2PeriphClockCmd(GPIO_CLK[Led], ENABLE);
/* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = GPIO_PIN[Led];
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIO_PORT[Led], &GPIO_InitStructure);
// 添加的代码,初始化时输出高电平,将灯熄灭
GPIO_SetBits(GPIO_PORT[Led], GPIO_PIN[Led]);
}
由于灯的状态是反的,所以修改如下文件:
\Custom_HID\Projects\Custom_HID\src\usb_endp.c
/* 修改后如下 */
void EP1_OUT_Callback(void)
{
BitAction Led_State;
/* Read received data (2 bytes) */
USB_SIL_Read(EP1_OUT, Receive_Buffer);
if (Receive_Buffer[1] == 0)
{
Led_State = Bit_RESET;
}
else
{
Led_State = Bit_SET;
}
switch (Receive_Buffer[0])
{
case 1: /* Led 1 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOff(LED1);
else
STM_EVAL_LEDOn(LED1);
break;
case 2: /* Led 2 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOff(LED2);
else
STM_EVAL_LEDOn(LED2);
break;
case 3: /* Led 3 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOff(LED3);
else
STM_EVAL_LEDOn(LED3);
break;
case 4: /* Led 4 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOff(LED4);
else
STM_EVAL_LEDOn(LED4);
break;
default:
STM_EVAL_LEDOn(LED1);
STM_EVAL_LEDOn(LED2);
STM_EVAL_LEDOn(LED3);
STM_EVAL_LEDOn(LED4);
break;
}
SetEPRxStatus(ENDP1, EP_RX_VALID);
}
\Custom_HID\Projects\Custom_HID\src\usb_prop.c
修改后如下:
void CustomHID_Status_In(void)
{
BitAction Led_State;
if (Report_Buf[1] == 0)
Led_State = Bit_RESET;
else
Led_State = Bit_SET;
switch (Report_Buf[0])
{
/*Change LED's status according to the host report*/
case 1: /* Led 1 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOn(LED1);
else
STM_EVAL_LEDOff(LED1);
break;
case 2: /* Led 2 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOn(LED2);
else
STM_EVAL_LEDOff(LED2);
break;
case 3:/* Led 3 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOn(LED3);
else
STM_EVAL_LEDOff(LED3);
break;
case 4:/* Led 4 */
if (Led_State != Bit_RESET)
STM_EVAL_LEDOn(LED4);
else
STM_EVAL_LEDOff(LED4);
break;
default:
STM_EVAL_LEDOn(LED1);
STM_EVAL_LEDOn(LED2);
STM_EVAL_LEDOn(LED3);
STM_EVAL_LEDOn(LED4);
break;
}
}
5.使用SimpleHIDWrite.exe测试LED灯
查看HID报告描述符LED灯部分如下:
/* Led 1 */
0x85, 0x01, /* REPORT_ID (1) */
0x09, 0x01, /* USAGE (LED 1) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x95, 0x01, /* REPORT_COUNT (1) */
0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */
0x85, 0x01, /* REPORT_ID (1) */
0x09, 0x01, /* USAGE (LED 1) */
0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */
/* 26 */
/* Led 2 */
0x85, 0x02, /* REPORT_ID 2 */
0x09, 0x02, /* USAGE (LED 2) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x95, 0x01, /* REPORT_COUNT (1) */
0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */
0x85, 0x02, /* REPORT_ID (2) */
0x09, 0x02, /* USAGE (LED 2) */
0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */
/* 46 */
/* Led 3 */
0x85, 0x03, /* REPORT_ID (3) */
0x09, 0x03, /* USAGE (LED 3) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x95, 0x01, /* REPORT_COUNT (1) */
0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */
0x85, 0x03, /* REPORT_ID (3) */
0x09, 0x03, /* USAGE (LED 3) */
0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */
/* 66 */
/* Led 4 */
0x85, 0x04, /* REPORT_ID 4) */
0x09, 0x04, /* USAGE (LED 4) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x95, 0x01, /* REPORT_COUNT (1) */
0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */
0x85, 0x04, /* REPORT_ID (4) */
0x09, 0x04, /* USAGE (LED 4) */
0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */
分析,如果要点亮LED需要如下发送报告:
REPORT ID=0x1, DATA=0x1点亮LED1,DATA=0x0熄灭LED1
REPORT ID=0x2, DATA=0x1点亮LED1,DATA=0x0熄灭LED2
REPORT ID=0x3, DATA=0x1点亮LED1,DATA=0x0熄灭LED3
REPORT ID=0x4, DATA=0x1点亮LED1,DATA=0x0熄灭LED4
使用SimpleHIDWrite验证上面的参数设置正确,截图如下:
验证可以正常的点亮LED灯,说明移植成功。
6.备注
工程下载:
链接:https://pan.baidu.com/s/1h_Kjw2TJXkwaEMRsvFSQ7A
提取码:sppz
目录:标准函数库\扩展实验\USB实验\USB设备\Custom_HID.rar