每当提到 3D 第一人称射击游戏,大家很自然就会联想到高性能独显,以及几个G甚至几十G的硬盘存储空间,那么有没有可能在 STM32F103RC 这样一块只有 256KB Flash 的小板子上保存一个大型第一人称射击游戏呢? 当我们用 USB 线把这块开发板连接到电脑上,就可以看到出现了一个只有100多KB的U盘,这就是 STM32 的片上 Flash 了。 如果我们双击它就启动了一个 STM32 上的第一人称射击游戏。 3 j/ c4 @; J/ N5 n& q u" P3 h这是完整的演示视频:如果你也有兴趣把这个游戏保存在 STM32 上,可以跟着后面的教程,或者也可以在这个项目里直接找到编译好的固件、游戏和项目源码。6 d' j5 s7 j7 t; J. k/ D1 R 链接地址:http://github.com/wuhanstudio/stm32-ufun-3d-game 1. 运行 RT-ThreadRT-Thread 在 Github 上是开源的,源码可以在这里(链接:http://github.com/rt-Thread/rt-thread/)找到,官网文档也很丰富这里就不重复了,总结一下需要的工具:
如果觉得从 github 上面下载 RT-Thread 源码比较慢,可以先从 gitee 上面下载,然后修改项目地址。 1git clone https://gitee.com/rtthread/rt-thread$ o/ x2 [2 i2 H! Y% ~) s- y+ R2cd rt-thread* X% ^( f$ b4 q3 ~ U) F 3git remote rm origin 4git remote add origin https://github.com/RT-Thread/rt-thread 5git pull origin master ( e9 L) a& f- e+ c 2. 片上 Flash 文件系统准备好第一步里面的工具后,首先我们需要把 STM32 的片上 flash 挂载为文件系统,首先需要在 CubeMX 里使能 USB。 打开 USB 后在时钟配置里确认外部晶振和板子上的晶振是一致的,并且 USB 的时钟是 48MHz,就可以点击生成代码了。由于我们修改了时钟,需要把 board/CubeMX_Config/Src/main.c 里面的 void SystemClock_Config(void) 函数复制到 board/board.c 里面替换。 接下来修改 bsp 下 board 目录里的 Kconfig 文件。1config BSP_USING_ON_CHIP_FLASH9 V2 i x V' a4 x# y7 g2 bool "Enable on-chip FLASH"/ ~; [9 c$ ?; A' U( L, J; F 3 default n 5 L3 [* N5 K+ A6 a 4 5config BSP_USING_USBD_FS/ l; S M! v3 m6 `, T) ] 6 bool "Enable USBD as USB device" 7 select RT_USING_USB_DEVICE4 j( |! R7 z6 J& J) @. }/ I 8 default n8 K+ T5 [$ H- G8 _ 这样再在 bsp 目录下右键 ConEmu Here 就可以看到配置界面 (Env 教程:http://www.rt-thread.org/document/site/tutorial/env-video/),依次选中下面几个选项:
保存配置退出,在 env 里面输入命令就可以自动生成 Keil 项目了: 1pkgs --update E' O! x( F1 G- Q( j 2scons --target=mdk5 -s) f) Z. M u" { 28 x, J' `) U* N! ^( e( D 3#define FAL_FLASH_DEV_TABLE \ 4{ \ 5 &stm32_onchip_flash, \; h/ s- _" w* q 6} 7 8#define FAL_PART_TABLE \3 W6 v. `; q. q9 `3 Q' @ 9{ \' J* o+ g: `" a- V 10 {FAL_PART_MAGIC_WROD, "app", "onchip_flash", 0, 128*1024, 0}, \ 11 {FAL_PART_MAGIC_WROD, "flash0", "onchip_flash", 128*1024, 128*1024, 0}, \; l ?+ U) b. R, `& p 12}1 m9 B, A- l0 K4 ^6 | 2 D6 L6 z7 `3 _. I/ a# \5 H$ x" @ 再修改 main.c 挂载文件系统: 1#include <rtthread.h>2#include <rtdevice.h># T! m$ F# |) q 3#include <board.h>/ n. A0 ~ U3 [' I9 q, D 4#include <fal.h>1 R; ?; j, p3 b6 t7 v+ t# e& w 5#include <dfs_posix.h>$ z" ] U4 Q# E3 k+ N7 _ 6 7/* defined the LED0 pin: PC13 */" C1 c: i' [. G! P- G5 A 8#define LED0_PIN GET_PIN(C, 13)4 B( U% |2 w# E; u1 J- W! | 9: M: F# j" F5 }& y, f: i8 R 10#define FS_PARTITION_NAME "flash0" 11 12int main(void) 13{7 t$ i" A! m7 ]% Q9 O 14 int count = 1;* q3 G1 `) n/ ~3 E1 w) \ 15 /* set LED0 pin mode to output */$ T. ~& h- T/ p: Y# d# X 16 rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); 17! v% z; p, j" ~6 V+ J& g2 s; t% T 18 fal_init();, V% ], i+ }5 R4 l 19 20#ifdef RT_USB_DEVICE_MSTORAGE 21 struct rt_device *flash_dev = fal_blk_device_create(FS_PARTITION_NAME); 22#else 23 struct rt_device *flash_dev = fal_mtd_nor_device_create(FS_PARTITION_NAME);# Y6 L; x5 A+ X 24#endif 25) D% W* X* B0 Z& {; E9 D+ \8 ` 26 if (flash_dev == NULL) 27 {8 e7 V8 N, Z' w6 z8 I 28 rt_kprintf("Can't create a block device on '%s' partition.\n", FS_PARTITION_NAME); 29 }$ {& C! d! c5 |+ f8 m 30 else1 I L- C6 c( i 31 { 32 rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME); 33 }/ D, ~, n5 r1 f* k8 v5 A9 n. s 34' i. x n2 |) X; n* D 35 while (count++)2 A& c. J/ y( o- {6 I 36 {& H8 G1 I2 Y! W: m4 v5 a 37#ifndef RT_USB_DEVICE_MSTORAGE) n+ g7 w# K3 ] 38 if(rt_device_find(FS_PARTITION_NAME) != RT_NULL) 39 {' Y' D6 r- }5 Q- K' [* r 40 dfs_mkfs("lfs", FS_PARTITION_NAME); 41 42 if (dfs_mount(FS_PARTITION_NAME, "/", "lfs", 0, 0) == RT_EOK)3 p T- G2 `$ \2 g2 J: E/ B 43 {9 w4 N$ u+ q5 G( _ 44 rt_kprintf("sd card mount to '/'\n"); 45 break; 46 } 47 else; j) o9 g" ^6 @' S9 H9 K 48 { 49 rt_kprintf("sd card mount to '/' failed!\n");- l( J8 u \8 ~8 J# R2 P 50 }+ \$ ]: h) P# ?5 i# I0 u 51 } 52#endif' t8 R+ `) X5 A: t! N) P! v 53 rt_pin_write(LED0_PIN, PIN_HIGH);$ z x9 h4 l/ \6 e! j1 [. T0 d" X% C 54 rt_thread_mdelay(500); 55 rt_pin_write(LED0_PIN, PIN_LOW);3 ]; r9 F6 n% s) j% m. `5 m& B 56 rt_thread_mdelay(500);. L" q3 Q, f* Z: W' X9 x: h 57 }# Y5 ?' A( T8 H/ S8 g8 y/ m 58 59 return RT_EOK;6 y, Z" p2 V$ o8 O0 s 60}: R0 x# d6 h& c7 c2 E; W" K; } 项目编译下载到板子上,串口连接上去在 msh 里输入 fal probe 应当就可以看到分区表了: Linux 下常用的命令 ls ,cat,mkdir,cd 也都是支持的,这样我们就把 stm32 的片上 flash 挂载为文件系统了, 下一步就是让它识别为 U盘。 4 s; Y/ E6 i7 z3. 挂载片上 Flash 为 U盘同样的,我们在 env 的配置目录里面依次选中:
这样保存配置,在 env 下生成项目文件: 1scons --target=mdk5 -s编译上传到板子上,接上 USB 到电脑,例如 STM32F103 的 USB 引脚是 PA11 和 PA12,就可以看到电脑识别到一个新的 U盘了,第一次使用可能需要先格式化。 |
这不就是做了个U盘,跟游戏有毛线关系 |
我还以为能运行呢 |
STM32固件库分享,超全系列整理
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【MCU实战经验】+STM32F107的USB使用
基于STM32F103两轮平衡小车设计(开源)
STM32F107VCT6官方原理图和PCB
【福利】用STM32库的朋友有福了:STM32F10x_StdPeriph_Lib_V3.5.0chm...
基于STM32F10xx存储器和系统架构经验分享
基于STM32F1的CAN通信之BH1750
基于STM32F1的CAN通信之OLED
基于STM32F1的CAN通信之之串口IAP