STMCU小助手
发布时间:2023-1-7 11:58
|
STM32F103C8T6使用MDK 4.12中Custom_HID的修改方法' ?+ ~2 m* B9 x* a* y- h( R3 f, |3 B 目的,由上位机发送64字节,设备回应3个字节,功能自定。。 . F( ]0 X T+ h# J+ M* T( L; n/ ~8 ` 板子使用的是最小核心板,MCU为STM32F103C8T6。 USB的D-和D+分别接到PA11(USBDM)和PA12(USBDP)上,PA12(USBDP)即D+通过跳线使上拉1.5K电阻到VCC(3.3V)。 1:打开MDK4.12,打开 r$ q7 H; d7 l- w. ~ C:\Keil\ARM\Examples\ST\STM32F10xUSBLib\Demos\Custom_HID\project目录下的Custom_HID项目文件。& [* ^; q/ H, [' N9 { 2:选择菜单 Project->Options for Target 'STM3210E-EVAL': T8 h( Q7 U3 h3 F0 @ k 在Device选项卡里选择 STM32F103C8。/ m% W1 P3 b1 Q8 j: k. M/ H. h 在Output选项卡里把Create HEX File选上,取消Browse Information。! `( c2 P( D6 O' {0 z 在C/C++选项卡里的Preprocessor Symbols里的Define: USE_STM3210E_EVAL清除。% {, E2 u; V' u3 \2 Q; M- @! q# f 3:从Application files组中的文件由上而下逐个修改% r. \: b% Z. I! ?+ D7 S7 `( V 第一个是usb_pwr.c( L R4 w1 h5 L- K 把PowerOn和PowerOff()面里的USB_Cable_Config(ENABLE);和USB_Cable_Config(DISABLE);这两句删除,因为我的板子上没有这个控制电路, 而是通过跳线把USBDP通过1.5K电阻接通到VCC(3.3V)的。 接下来修改hw_config.c1 k, a1 A2 O i 把 #define ADC1_DR_Address ((u32)0x4001244C)) Q+ \( I9 r' L% W u32 ADC_ConvertedValueX = 0;: s0 {, L# K e9 y u32 ADC_ConvertedValueX_1 = 0;$ A0 E! A5 a3 G 这三句删除,因为我不用ADC,外部中断和DMA,只需要跟上位机通信点亮板上连接到PB0上的一个LED。3 ^4 L5 j: h3 `8 t: F; ` 所以还要把Set_System函数里的 EXTI_Configuration(); ADC_Configuration(); 这两句删除。 把USB_Interrupts_Config函数里的 ?" @( o3 A7 ?5 S' H- M8 w EXTI9_5 Interrupt; ?+ [; B$ a8 k1 \ \ EXTI15_10 Interrupt3 q& {: U) m5 ~/ X' L* |% c8 W2 P DMA1 Channel1 Interrupt/ B! e) i! t+ J 这三个相关的语句都删除。 ' v. H ~2 f! d9 O8 N 把USB_Cable_Config整个函数删除。- H r- x8 p4 n0 e' g& D# a& ^, [' k # V$ c$ z7 t- }0 G8 j2 R6 y 把GPIO_Configuration里面的& T, P- N. q' C9 u" B ?( M/ C( f KEY& ]9 O) I& w' [- X, Q# L/ x Tamper# l$ I( F+ o5 P& q) y- W) u Potentiometer 三个相关的配置语句都删除。, n: N! D( F0 }" X2 f4 F0 C/ G 下面的LED配置只配置LED1,用来指示上位机的指令,其它都删除。 1 K# z' s8 l# } 把- h8 \0 e" B6 G EXTI_Configuration ADC_Configuration 这两个函数整个删除。 加上这句RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); 别忘了开CRC电源。计算序列号要用到的,否则序列号就会变成42949-67295,是0xffffffff,是错误的。 把Get_SerialNum函数的功能改成如下" v* @/ Z, V4 N7 @0 U 目的是把96位ID作CRC运算后来做产品的序列号。4 X" Z4 ~ c) S, G q* P9 K$ v; h 可以不要这个函数,只在usb_desc.c里定义序列号。同时其它文件里用到这个函数的地方就要删除。 : c* d' v2 e% f8 d" r 增加RBIT这个函数,32位位倒置程序,CRC用到的。因为STM32的CRC计算结果跟一般的CRC校验工具计算结果不同,所以要特殊处理。 如0 R, Y$ n1 i( N3 z 原始序列号: 39006C0658343131496705431 b) Y: L+ m) }; K& s 分成三个32位数。每一个32位按位倒置,然后给STM32计算CRC,结果跟0xffffffff异或运算后,再把32位的结果按位倒置。就对了。1 z' w& [' R7 r0 C# s 39006C06=00111001000000000110110000000110 = 01100000001101100000000010011100 = 6036009C8 D* i* Q. P" o 58343131=01011000001101000011000100110001 = 10001100100011000010110000011010 = 8C8C2C1A% l7 X: j# `, ^9 g3 F' X3 g 49670543=01001001011001110000010101000011 = 11000010101000001110011010010010 = C2A0E692+ \! J0 h; w7 i$ d) h( r. p | STM32的CRC结果跟0xffffffff后为十进制4289354847=FFAA5C5F=11111111101010100101110001011111=倒过来11111010001110100101010111111111=FA3A55FF( d. E4 c& ]' m M$ Y( J, R $ S/ R9 B, q. u) u- e+ R6 Q
然后修改对应的 hw_config.h* \) ]7 ^8 [% k void USB_Cable_Config (FunctionalState NewState); void EXTI_Configuration(void);) R$ T7 u$ z; p( X3 L void ADC_Configuration(void);& o B% ]) ?2 Q. B+ k 把这三条删除。, x: V$ k4 T- q+ U) a Get_SerialNum也视情况决定要不要删除。 main.c不动。9 o5 t x0 } x' Q- z6 B, e 接下来修改 stm32f10x_it.c. u7 X* n! v6 q/ g: D1 @ X/ W* s 把u8 Send_Buffer[2]; 这句删除。9 F" e- k( ]6 G0 p' M + b9 O8 d% ?. h9 D; m 把 extern u32 ADC_ConvertedValueX; extern u32 ADC_ConvertedValueX_1; 删除。 把- Z( P8 W5 R. V0 Y DMA1_Channel1_IRQHandler EXTI9_5_IRQHandler EXTI15_10_IRQHandler 这三个函数清空,是清空里面的内容,保留一个空的函数。' v" M( Z: h% m2 j# r , ?" I) ?/ l( T9 h4 l! U6 @" R 接下来改 usb_desc.c 把报告描述符改成自已的:1 @* i) u5 M" @, D) d( k, a% _9 y' \
然后更改配置描述符中的输入输出端点的最大包数。输入端点改成3个字节,输出端点改成64字节。 ( m x% s. `7 Q/ v# p( o& e. ?) s( o 再来改下面三个字符串描述符,使用的是UNICODE格式的,用记事本写好保存为UNICODE格式文件,再用十六进制编辑器打开就看到了。/ P" c8 }% J& c8 ~; y- \7 H3 w' G; K+ A 改完以上的数据,还要更改usb_desc.h里的定义的大小。(注意字节数还包括描述符长度及标识),如上面的报告描述符大小应改成$ m" B Z0 ~) ?2 U #define CUSTOMHID_SIZ_REPORT_DESC 37 接下来改usb_endp.c 把! V/ x: l+ r9 m- H# N u8 Receive_Buffer[2]; 改成 u8 Receive_Buffer[64]; //因本例中要求上位机发来64字节。: x5 z0 Q2 Z& O' h; c7 V 然后是EP1_OUT_Callback这个函数的修改,根据上位机发来的数据,作出相应回应。7 N' ?. V! t- C3 o$ ` usb_istr.c不用改。 然后改usb_prop.c 把CustomHID_Reset函数里的 SetEPTxCount(ENDP1, 2);# j* }3 o0 r: W4 {, ?9 ?8 j SetEPRxCount(ENDP1, 2); t8 s% n* I: U 改成 SetEPTxCount(ENDP1, 3);# S( p& a% R q5 t SetEPRxCount(ENDP1, 64); CustomHID_init函数里调用了Get_SerialNum函数,如果使用usb_desc.c里定义的产品序列号,这里也不用了。。9 F9 @1 E& |6 ^. R1 y" s) G 还要修改platform_config.h; N1 E- a+ O9 ~8 }' ] 把修改LED引脚,USB引脚的定义。 & M( K1 y+ I( ^- R) H 终于改完了。。 以下是记录下来的发送程序段。+ a9 d: q/ V! z! _- @+ B u8 Send_Buffer[3];. n7 U' z( S S( M; ]$ [ Send_Buffer[0] = 0xxx; Send_Buffer[1] = 0xxx;9 w8 G# [+ s$ ~- h2 n0 F Send_Buffer[2] = 0xxx; UserToPMABufferCopy(Send_Buffer, ENDP1_TXADDR, 3);4 V% X0 p* r' Q) F9 q! ~ SetEPTxValid(ENDP1);8 d' U+ `6 \ F/ ~) ~- E/ o " W$ }9 p/ _% w: V 最后要还说一说跟上位机通信要注意的地方,上位机程序要限制只能用运行一个实例,可以用互斥量。运行多个程序会导致USB不知应该跟哪个- e% J: e; S0 t9 ` 2 j- j! ^! |( c$ z! s* J7 U3 a2 h 程序通信,数据会错误。$ S( I) J; |5 A( S3 O9 W 注意程序关闭再打开后要获得设备的状态。而设备复位后也要通知上位机,以保证两者状态一致。& ?, r$ H# h. |: ?0 e2 n 上位机程序的读写缓冲都要比设备定义的大一个字节(开始位置,0x00)。这个字节由电脑发到设备中会被去掉,所以设备端不用管。8 q' F* l3 `& d- u+ x 电脑接收到的数据也比设备发来的多一个字节,也要处理掉。。。 还有ANSI跟UNICODE的处理,要清楚。如字符串描述符中的字符串的显示等。6 D3 d, P! B. ^ $ X* B }& V8 P6 e/ s , u) `) X& u6 k$ E5 I 转载自:xqhrs232 9 `3 |9 F1 G7 `0 K6 S |
DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
【福利三:雨露均沾·逢7狂欢】之五:STM32系统时钟PLL故障排除1例
【福利三:雨露均沾·逢7狂欢】之三:AI帮我查BUG
福利三:雨露均沾·逢7狂欢】之二:STM32F407VG串口通信乱码故障的排除
基于STM32F103的I2C主从机通信
OpenBLT移植到STM32F103战舰开发板上适用于所有STM32F103系列的Bootloader
TFT LCD 与 FSMC 的硬件连接大容量 STM32F10xxx FSMC 接口
单片机:初学者该了解的STM32F103基础知识
2025软件工具兔哥知道
STM32之继电器模块
微信公众号
手机版