一、项目要求:7 T% |2 U$ z! {: Q1 U5 n) b
硬件驱动+软件工具类项目
1 ~3 g' S5 M, T+ D- b
% `( j8 v2 Y( {& \8 E项目需要的技术:) g) R+ a ?! u2 |
; w$ X8 }( n1 s& o, e2 }
UCOSIII2 ^0 J! {9 z+ } E7 e
GUI显示, x. q! h _: G' _' k6 K
IIS协议
$ m9 y" t6 g, X! E+ Q+ m" ]声卡驱动----资料及参考代码提供
* D6 ?, w4 l. u, j) P6 dSD卡驱动—资料及参考代码提供
+ h2 v4 D1 c- D$ i6 EFatfs文件系统* j$ u% `7 f! u. ~
IIC/SPI 及W25Q128驱动* N' `9 O% H. n( h
字库在MCU屏的使用
: a# ~" g5 U1 T1 ]mp3、WAV解码库的移植及使用–资料及参考代码提供
- b' X; K+ V$ ~' ~* _4 ~JPG、BMP解码库的移植及使用–资料及参考代码提供( z) j, N' a, k+ G8 p
DMA使用! r, c/ s# b" H# F8 I$ Y7 v% a
功能基本和现在的MP3设备一样: ~8 T- `' u- V( v G( Q* f3 Z1 k
: u3 d T% }8 X* d. _' q7 x" P
①能够通过SD卡驱动嵌入文件系统实现对SD卡目录的扫描获取音乐文件(.mp3 .wav等)4 Y/ `5 Y4 W6 B, x: w3 z a
& F5 H/ V# c5 R8 q
②驱动WM8978声卡芯片 使用IIS实现对SD卡读取的音频数据后的向声卡传输 并控制声卡播放音乐4 ?) [/ T) \; J8 R+ S# W. T1 W
0 I. o3 t. c4 K7 X) N③能够自己在mcu屏中显示MP3播放器相关信息" }$ b1 b- z) F0 S( s, N( x9 m
歌曲名。。。。/ u# J0 S2 B% j% k
: N( Y, x" d4 G* f, B可以使用字库显示相关中文* @, L2 ^4 @; _/ O4 F5 N
# @' e# c' Y6 T- x' B; m, |8 r二、材料准备# `( S2 `9 @$ o
1、STM32F4开发板一块(需要音频接口支持)(我用的GEC M4)
. J, u/ p+ r1 J4 }1 q6 s7 v(注意要买能插LCD屏的、最好有板载wm8978,没有的话可以外接音频驱动模块)) q' z$ x( S/ E: A9 D5 H# p1 _( O3 a
作用:主控芯片、处理各种数据
& Z$ g' ~4 B6 P0 G5 |* C5 V) F# Y0 |
+ k# B( c$ s$ A7 Z% d
- P+ H1 f2 t" k" J3 V( @% d
( C/ @& C1 F1 j! C j+ W& s% l
. j- L5 _& k; t' E2、800*480 4.3寸电容触摸LCD屏(我用的正点原子的屏)
, b. D2 W3 D; B d6 {$ C9 R. C(注意不兼容其他分辨率的屏)
- x) Y/ x( C. m9 W j; A! i作用:显示与触摸控制
0 H. A' M3 Q T" m* A R9 P
4 P- O% X7 R- }! ]
3 g: A. k9 f+ F3 D
) L, j# p9 d* _& [+ x3、一张32G以下的SD卡和一个读卡器' H0 y M& D6 K" L5 f/ B
, }9 P7 `7 Q, `, I9 h9 ?3 W, }
作用:存储mp3、wav 文件、图片文件等必要文件4 B( P, ^+ h6 D- H
6 E) N2 }" |+ f; h9 K7 }
# F' q2 T( p7 X1 C l& O
) ]7 s2 ?: E: [/ O) r二、硬件连接
$ d7 d4 Z" j8 N* g# L6 s1、把屏幕插到开发板上即可
% ~, @, \6 P6 w( ~1 d0 H
8 y S/ X4 s. @2 j三、下载调试- C2 M# H! m: c# c# u! p
1、下载好相关资料
$ V" u8 W- ~8 v% w1 i* {" `) V2 L8 S
Z2 C( M1 t3 x, ~) S5 ]4 y* A5 j
# U. T& a6 M( a$ o4 `" N5 ^; ?/ K. `: H! f$ M; |: m. w! s
2、下载源代码到单片机% m4 v6 ^: Y6 ]; f: ]+ P
3、将SD卡根目录文件拷贝到SD卡根目录下/ Z% N+ v. y/ E2 Q
* K, [6 ?( @! c% T
C1 `( d3 F9 {
; _% E, V2 A. q9 `, ^7 w+ q4、上电启动系统,供电要足,不然屏幕半亮、声卡驱动异常。
4 p9 ~1 \' `6 b* e- ^8 A. t+ @能正常显示图片、按钮控件即移植成功。
: ?/ y: L6 {1 g+ U. U6 \2 E$ a# `6 g J8 F
四、相关知识点
' ]* H, o6 x: C* {3 [(一)、FATFS文件系统(就是个用来读写SD卡文件的)/ h+ Y, f8 p' [" n( _' o
1、FATFS 是一个完全免费开源的 FAT 文件系统模块,专门为小型的嵌入式系统而设计。它完全用标准 C 语言编写,所以具有良好的硬件平台独立性,可以移植到 8051、PIC、AVR、SH、Z80、H8、ARM 等系列单片机上而只需做简单的修改。它支持 FATl2、FATl6 和 FAT32,支持多个存储媒介;
+ ?7 S \% q) z. c) c! a$ _5 Y! R$ r
2、为什么需要文件系统?
. W Z! q; P# A- `因为SD卡只是一种存储器,普通的读写操作只能是针对地址进行读取,读取出来的数据都是一些字符数据,并没有文件的概念,加入了文件系统的SD卡可以利用FATFS文件系统进行管理,比如说要存储一张图片只需要以文件的形式存储,而普通的读写只能是把图片数据一个字节一个字节地存到一块指定内存中,读取也要严格根据地址位置读取( \9 m% Y1 g" V0 I7 d4 [$ j- W, T
1 D0 ~. ~+ ~0 ^% {( F+ Z* O3、正点原子提供了比较好用的FATFS源码可以直接移植使用
; U+ V; n$ a- k1 D0 B. I代码文件可以到正点原子官网下载. k. ?. K4 K3 B6 t
下面是主要API函数: 进行对文件的读取、写入等一系列操作,与C语言文件IO差不多相似,看文件名应该知道大概的用途$ A# m. C" s5 L& p/ e+ g7 J0 j
( i2 c3 A8 Z. x+ e& I, o
/ O: q- A5 Y3 ^" N9 i! V2 P' I) c1 a3 L: @/ p3 j$ ^2 E+ U5 y
: i& B7 S$ L6 h# a; k+ }& d
五、程序展示
- F/ M& s P( A) Q0 ^展示部分关键代码:2 P+ e8 @# `% ^, X
% w6 a" B3 D& Q: E7 e- #include "stm32f4xx.h"
, T' Y8 ~! j* f, I) j# `0 g
9 d3 n2 h# L. c: x
, ]- I1 J7 j f; }% c- ~- /* 开始任务 */
7 X* \ J( z \ P) C - //任务优先级
' h6 |0 U( u8 f- s4 N- |, A - #define START_TASK_PRIO 3
) g. [; G3 z3 v) E - //任务堆栈大小
$ F! }( I2 R* |0 ^* }* v - #define START_STK_SIZE 128
+ n! ]8 y+ p8 q0 t - //任务控制块
# L5 G& M" C6 B6 g4 r - OS_TCB StartTaskTCB;
4 x% t3 u/ y" i4 T i" T - //任务堆栈 ) C; U9 ] ]. G5 L6 ~" ~4 m
- CPU_STK START_TASK_STK[START_STK_SIZE];
]1 n# ^+ a8 h - //任务函数
$ N# }$ _0 b# h - void start_task(void *p_arg);
* u# {- l' y j0 P& O1 n - 6 m0 E- M- q0 V- N; E
- /* 主任务 */
( ^! }- t8 V- d! W c7 ~( Z8 L0 v - //任务优先级
+ j5 }+ h/ g0 a- x: D# W8 [3 D - #define MAIN_TASK_PRIO 6
: r( E+ G1 p' n+ ? - //任务堆栈大小
0 ?( z& }6 p0 d" r - #define MAIN_STK_SIZE 512: U/ r7 e, w1 q6 E. f# Y
- //任务控制块
, ]7 T2 v1 O/ Z7 ]% \3 I - OS_TCB MainTaskTCB;
3 V3 h$ D- O0 h- {% }/ w7 S - //任务堆栈 4 N+ h: q. S# g
- CPU_STK MAIN_TASK_STK[MAIN_STK_SIZE];
; g& S. }1 {- [. y - //任务函数& P( | r: h# @& t
- void main_task(void *p_arg);; w6 @1 o: k9 n
9 h$ k u. y* u- R& ?
9 _4 W+ f" \! @% t- 1 G/ B7 D; w8 ]3 E5 g
- //系统初始化6 n) G! H8 m; p) \/ d
- void sys_init(void)
6 b( U4 c z% f1 m - {
6 r( J+ R8 u& T - u8 key;
2 T# C8 }3 _! R: K" L - $ w' U) V+ O u* ?
- uart_init(115200); //串口初始化
# _5 J p+ e6 m, T6 ?1 `, S) D - LED_Init(); //LED初始化5 C) g# B7 P5 {) a, ` C
- KEY_Init();
/ _! l& j+ t. m" d) z& I - LCD_Init(); //LCD初始化
! U5 K1 N0 a! k, T* B - 0 t$ R0 m' V. |( @$ {4 p
- FSMC_SRAM_Init(); //SRAM/ y; }+ X$ y9 r$ U2 j
- tp_dev.init(); //触摸初始化
+ Q. [6 P$ M: H+ L - W25QXX_Init(); //初始化W25Q128
1 D" S" {$ [7 m( o9 R: w, h - gui_init(); //gui初始化
0 i& g [2 f, G' R -
! w! t& [) `& `9 f1 K) t) e" i$ o! | - my_mem_init(SRAMIN); //初始化内部内存池
; u) P" H: k" U/ @; ? - my_mem_init(SRAMEX); //初始化外部内存池
) [+ M: c' {/ o/ A, x8 m0 v - my_mem_init(SRAMCCM); //初始化CCM内存池 7 Q/ j7 S: g/ j/ C& \
- exfuns_init(); //为fatfs相关变量申请内存 % ?# ]) w: K, D- E: c8 b- l5 g. n5 f
- f_mount(fs[0],"0:",1); //挂载SD卡
2 t2 _4 |/ ?) ^4 q0 z2 a - f_mount(fs[1],"1:",1); //挂载FLASH.- Z8 ?! r* j& I4 U
- piclib_init(); //初始化画图
, d$ d) H1 `- Z+ y6 i - . E' Q( b. F3 E! J4 H
- while(font_init()) ; //检查字库
5 Y" y# X; k- Z - while(WM8978_Init());//检查音频芯片是否正常
- b i2 o4 f4 q - }
) Z. d- D' X2 t3 E, T
; L% z( D( Z. E/ i( ~# ~- int main(void)+ S& I' O* s8 P+ ]
- {6 y( t- Q- u7 K7 C; b1 l
- OS_ERR err;; w+ k! f t1 c( v& {% U
- CPU_SR_ALLOC();
5 n+ Z: a% W! L3 ^ -
5 ?/ W" h3 [6 S" e/ i - delay_init(168); //时钟初始化" W4 N- D0 }! F6 J- t
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
9 L2 f0 i% g- d. G5 q, z9 S - ) h# Z7 c" K& G- S4 Y. a" Q2 Q& y
- sys_init(); //系统初始化
4 h# }% w$ d" \4 T" d" V - delay_ms(150);
. z4 B) T! y$ n* X# f* U - LCD_Clear(GRAY);//清屏4 L3 e0 \8 t# n% P& w0 n! ?: e
-
5 G$ R" O5 D7 }' b3 _, v - " T2 G7 r$ N* f1 w" u
- OSInit(&err); //初始化UCOSIII/ F: F3 [$ `2 z+ \7 T
- OS_CRITICAL_ENTER();//进入临界区. k A' _1 z6 ]; F* b0 Q' C# d) v
- //创建开始任务
; u2 J8 t9 \8 w) _6 D* D - OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块
: H3 B$ N% j3 W [ - (CPU_CHAR * )"start task", //任务名字2 ?5 V& Q k# H% U- V; u0 A6 Q
- (OS_TASK_PTR )start_task, //任务函数9 L8 B, p! e+ }5 P! [: [
- (void * )0, //传递给任务函数的参数, Q7 J' j) c6 h# ~8 t. e8 L
- (OS_PRIO )START_TASK_PRIO, //任务优先级
) k% `" A# r' l* R2 t - (CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址' p5 G( M, y7 k' [% w; K
- (CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
" c3 J4 S# B3 v- m8 x8 r. H i2 \5 k - (CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
/ r: g8 B: P5 ^( B. S4 e* N - (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息3 S" t% W# P* I2 o7 ^
- (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
; P5 _8 W2 X/ _3 \, r2 E - (void * )0, //用户补充的存储区/ b" @. Y9 r! ?8 b2 U( _; b
- (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
5 S8 u- n7 l0 p5 _. j3 p+ n* } - (OS_ERR * )&err); //存放该函数错误时的返回值$ l& z% V5 _/ `% t0 a$ r# l& I8 [
- OS_CRITICAL_EXIT(); //退出临界区 : O+ @- w1 O6 j. k; F2 V, H; Q! e
- OSStart(&err); //开启UCOSIII
* [# H) [6 f# ?( q$ a7 k. V, r7 j - while(1);
- q4 s _5 \( q2 [; f* n - }
7 p4 _, y& u0 k0 p) e
4 |# z' @+ a# \) o' `- //主任务) d: K9 V6 w4 X7 w/ g2 F/ b# n
- void main_task(void *pdata)# @0 l ~ d9 N! r% ?
- {
* H# X0 T' W. F - while(1)+ E6 h6 K% ?: `, p x# P& j/ a4 E5 D
- {
, B( g8 S( _) ?) P. ^ - audio_play();//音乐播放器
$ A3 Y1 F$ b& o - LCD_Clear(WHITE);
* N% i& I" T% V4 d( _ - delay_ms(1000);
! g% x: W. W; k2 O2 [6 K+ w - }* B: Q+ C1 T8 T1 o2 E8 E4 r2 W
- } / Q, j( i- o+ _
- V& X5 U2 b& p0 _5 B+ Y. I- H
复制代码
: d9 c9 C- b( n) S. b! u3 Z! F; ]8 A* V4 }) C
|