你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103C8T6使用MDK 4.12中Custom_HID的修改方法

[复制链接]
STMCU小助手 发布时间:2023-1-7 11:58
STM32F103C8T6使用MDK 4.12中Custom_HID的修改方法
目的,由上位机发送64字节,设备回应3个字节,功能自定。。

板子使用的是最小核心板,MCU为STM32F103C8T6。
USB的D-和D+分别接到PA11(USBDM)和PA12(USBDP)上,PA12(USBDP)即D+通过跳线使上拉1.5K电阻到VCC(3.3V)。
1:打开MDK4.12,打开
C:\Keil\ARM\Examples\ST\STM32F10xUSBLib\Demos\Custom_HID\project目录下的Custom_HID项目文件。

2:选择菜单 Project->Options for Target 'STM3210E-EVAL'
在Device选项卡里选择 STM32F103C8。
在Output选项卡里把Create HEX File选上,取消Browse Information。
在C/C++选项卡里的Preprocessor Symbols里的Define: USE_STM3210E_EVAL清除。

3:从Application files组中的文件由上而下逐个修改
第一个是usb_pwr.c
把PowerOn和PowerOff()面里的USB_Cable_Config(ENABLE);和USB_Cable_Config(DISABLE);这两句删除,因为我的板子上没有这个控制电路,
而是通过跳线把USBDP通过1.5K电阻接通到VCC(3.3V)的。
接下来修改hw_config.c

#define ADC1_DR_Address    ((u32)0x4001244C)
u32 ADC_ConvertedValueX = 0;
u32 ADC_ConvertedValueX_1 = 0;
这三句删除,因为我不用ADC,外部中断和DMA,只需要跟上位机通信点亮板上连接到PB0上的一个LED。

所以还要把Set_System函数里的
EXTI_Configuration();
ADC_Configuration();
这两句删除。

把USB_Interrupts_Config函数里的
EXTI9_5 Interrupt
EXTI15_10 Interrupt
DMA1 Channel1 Interrupt
这三个相关的语句都删除。

把USB_Cable_Config整个函数删除。

把GPIO_Configuration里面的
KEY
Tamper
Potentiometer
三个相关的配置语句都删除。
下面的LED配置只配置LED1,用来指示上位机的指令,其它都删除。


EXTI_Configuration
ADC_Configuration
这两个函数整个删除。

加上这句RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); 别忘了开CRC电源。计算序列号要用到的,否则序列号就会变成42949-67295,是0xffffffff,是错误的。

把Get_SerialNum函数的功能改成如下
目的是把96位ID作CRC运算后来做产品的序列号。
可以不要这个函数,只在usb_desc.c里定义序列号。同时其它文件里用到这个函数的地方就要删除。

增加RBIT这个函数,32位位倒置程序,CRC用到的。因为STM32的CRC计算结果跟一般的CRC校验工具计算结果不同,所以要特殊处理。

原始序列号: 39006C065834313149670543
分成三个32位数。每一个32位按位倒置,然后给STM32计算CRC,结果跟0xffffffff异或运算后,再把32位的结果按位倒置。就对了。
39006C06=00111001000000000110110000000110 = 01100000001101100000000010011100 = 6036009C
58343131=01011000001101000011000100110001 = 10001100100011000010110000011010 = 8C8C2C1A
49670543=01001001011001110000010101000011 = 11000010101000001110011010010010 = C2A0E692

STM32的CRC结果跟0xffffffff后为十进制4289354847=FFAA5C5F=11111111101010100101110001011111=倒过来11111010001110100101010111111111=FA3A55FF

  1. __asm u32 RBIT(u32 value)
  2. {
  3.     rbit r0, r0
  4.     bx lr
  5. }


  6. void Get_SerialNum(void)
  7. {
  8.   u32 Device_Serial, Device_Serial0, Device_Serial1, Device_Serial2;


  9.   Device_Serial0 = *(u32*)(0x1FFFF7E8);
  10.   Device_Serial0 = RBIT(Device_Serial0);


  11.   Device_Serial1 = *(u32*)(0x1FFFF7EC);
  12.   Device_Serial1 = RBIT(Device_Serial1);


  13.   Device_Serial2 = *(u32*)(0x1FFFF7F0);
  14.   Device_Serial2 = RBIT(Device_Serial2);




  15.   CRC_ResetDR();
  16.   Device_Serial = CRC_CalcCRC(Device_Serial0);
  17.   Device_Serial = CRC_CalcCRC(Device_Serial1);
  18.   Device_Serial = CRC_CalcCRC(Device_Serial2);


  19.   Device_Serial ^= 0xFFFFFFFF;
  20.   Device_Serial = RBIT(Device_Serial);


  21.   if(Device_Serial != 0)
  22.   {
  23.   CustomHID_StringSerial[0] = CUSTOMHID_SIZ_STRING_SERIAL;
  24.   CustomHID_StringSerial[1] = USB_STRING_DESCRIPTOR_TYPE;
  25.   CustomHID_StringSerial[2] = (u8)(Device_Serial/(u32)1000000000)+0x30;
  26.   CustomHID_StringSerial[3] = 0x00;
  27.   CustomHID_StringSerial[4] = (u8)((Device_Serial%(u32)1000000000)/(u32)100000000)+0x30;
  28.   CustomHID_StringSerial[5] = 0x00;
  29.   CustomHID_StringSerial[6] = (u8)((Device_Serial%(u32)100000000)/(u32)10000000)+0x30;
  30.   CustomHID_StringSerial[7] = 0x00;
  31.   CustomHID_StringSerial[8] = (u8)((Device_Serial%(u32)10000000)/(u32)1000000)+0x30;
  32.   CustomHID_StringSerial[9] = 0x00;
  33.   CustomHID_StringSerial[10] = (u8)((Device_Serial%(u32)1000000)/(u32)100000)+0x30;
  34.   CustomHID_StringSerial[11] = 0x00;
  35.   CustomHID_StringSerial[12] = '-';
  36.   CustomHID_StringSerial[13] = 0x00;


  37.   CustomHID_StringSerial[14] = (u8)((Device_Serial%(u32)100000)/(u32)10000)+0x30;
  38.   CustomHID_StringSerial[15] = 0x00;
  39.   CustomHID_StringSerial[16] = (u8)((Device_Serial%(u32)10000)/(u32)1000)+0x30;
  40.   CustomHID_StringSerial[17] = 0x00;
  41.   CustomHID_StringSerial[18] = (u8)((Device_Serial%(u32)1000)/(u32)100)+0x30;
  42.   CustomHID_StringSerial[19] = 0x00;
  43.   CustomHID_StringSerial[20] = (u8)((Device_Serial%(u32)100)/(u32)10)+0x30;
  44.   CustomHID_StringSerial[21] = 0x00;
  45.   CustomHID_StringSerial[22] = (u8)((Device_Serial%(u32)10)/(u32)1)+0x30;
  46.   CustomHID_StringSerial[23] = 0x00;
  47.   }   
  48. }
复制代码

然后修改对应的 hw_config.h
void USB_Cable_Config (FunctionalState NewState);
void EXTI_Configuration(void);
void ADC_Configuration(void);
把这三条删除。
Get_SerialNum也视情况决定要不要删除。

main.c不动。

接下来修改 stm32f10x_it.c
把u8 Send_Buffer[2]; 这句删除。


extern u32 ADC_ConvertedValueX;
extern u32 ADC_ConvertedValueX_1;
删除。


DMA1_Channel1_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
这三个函数清空,是清空里面的内容,保留一个空的函数。

接下来改 usb_desc.c
把报告描述符改成自已的:
  1. /* CustomHID_ConfigDescriptor */
  2. const u8 CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =
  3.   {   
  4.     0x05, 0x01,                    // USAGE_PAGE(User define)
  5.     0x09, 0x00,                    // USAGE(User define)
  6.     0xa1, 0x01,                    // COLLECTION (Application)
  7.     0x19, 0x00,                    //   USAGE_MINIMUM(0)
  8.     0x29, 0xFF,                    //   USAGE_MAXIMUM(255)
  9.     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
  10.     0x25, 0xFF,                    //   LOGICAL_MAXIMUM (255)
  11.     0x75, 0x08,                    //   REPORT_SIZE (8)
  12.     0x95, 0x03,                    //   REPORT_COUNT (3)
  13.     0x81, 0x02,                    //   INPUT (Data,Var,Abs)


  14.     0x05, 0x02,                    // USAGE_PAGE(2)
  15.     0x19, 0x00,                    //   USAGE_MINIMUM (0)
  16.     0x29, 0xFF,                    //   USAGE_MAXIMUM (255)
  17.     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
  18.     0x25, 0xFF,                    //   LOGICAL_MAXIMUM (255)
  19.     0x95, 0x40,                    //   REPORT_COUNT (8)
  20.     0x75, 0x08,                    //   REPORT_SIZE (64)
  21.     0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)


  22.     0xc0            /*     END_COLLECTION              */


  23.   }; /* CustomHID_ReportDescriptor */
复制代码

然后更改配置描述符中的输入输出端点的最大包数。输入端点改成3个字节,输出端点改成64字节。

再来改下面三个字符串描述符,使用的是UNICODE格式的,用记事本写好保存为UNICODE格式文件,再用十六进制编辑器打开就看到了。

改完以上的数据,还要更改usb_desc.h里的定义的大小。(注意字节数还包括描述符长度及标识),如上面的报告描述符大小应改成
#define CUSTOMHID_SIZ_REPORT_DESC 37

接下来改usb_endp.c

u8 Receive_Buffer[2];
改成
u8 Receive_Buffer[64]; //因本例中要求上位机发来64字节。

然后是EP1_OUT_Callback这个函数的修改,根据上位机发来的数据,作出相应回应。

usb_istr.c不用改。


然后改usb_prop.c
把CustomHID_Reset函数里的
  SetEPTxCount(ENDP1, 2);
  SetEPRxCount(ENDP1, 2);
改成
  SetEPTxCount(ENDP1, 3);
  SetEPRxCount(ENDP1, 64);

CustomHID_init函数里调用了Get_SerialNum函数,如果使用usb_desc.c里定义的产品序列号,这里也不用了。。

还要修改platform_config.h
把修改LED引脚,USB引脚的定义。

终于改完了。。

以下是记录下来的发送程序段。
u8 Send_Buffer[3];
Send_Buffer[0] = 0xxx;
Send_Buffer[1] = 0xxx;
Send_Buffer[2] = 0xxx;
UserToPMABufferCopy(Send_Buffer, ENDP1_TXADDR, 3);
SetEPTxValid(ENDP1);

最后要还说一说跟上位机通信要注意的地方,上位机程序要限制只能用运行一个实例,可以用互斥量。运行多个程序会导致USB不知应该跟哪个

程序通信,数据会错误。
注意程序关闭再打开后要获得设备的状态。而设备复位后也要通知上位机,以保证两者状态一致。
上位机程序的读写缓冲都要比设备定义的大一个字节(开始位置,0x00)。这个字节由电脑发到设备中会被去掉,所以设备端不用管。
电脑接收到的数据也比设备发来的多一个字节,也要处理掉。。。
还有ANSI跟UNICODE的处理,要清楚。如字符串描述符中的字符串的显示等。


转载自:xqhrs232


收藏 评论0 发布时间:2023-1-7 11:58

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版