半主机机制的作用% F3 {" c; |3 G- {
& w- I( Y, J' @4 ~2 r4 R
1 N9 J4 p# m0 z5 d$ e5 O 半主机是用于ARM目标的一种机制,可将来自STM32单片机应用程序的输入输出请求传送至运行仿真器的PC主机。使用此机制可以启用C库中的函数,如printf()和scanf(),来使用PC主机的屏幕和键盘。这样就可以看到单片机的输入输出,方便进行调试。注意:种机制的运行需要仿真器,否则无法运行。
, s l6 }" }( t9 T% d2 H4 {" S5 G0 K/ Q
, @, ^+ q# s4 ? 简单的来说,半主机模式就是通过仿真器实现开发板在电脑上的输入和输出。
) k3 x. S; {/ C# ?8 z% D3 s; O 开发时单片机需要独立运行,开发者就应该去掉仿真器,把printf函数通过单片机的外设来实现,例如通过开发板的串口。% M9 d" e" ^% F4 y" i
7 E7 T9 H& h) G3 k/ O; h; p+ Z: o* k' s3 {1 S5 q
非半主机机制下printf函数的实现方法
- J6 A; f" { w1 S1 h C5 [* Z( H
6 p ~1 i% q+ c
2 W0 i, D8 j* Z0 X/ o( Q, _4 aUse MicroLIB(微库)
0 B3 W+ k& B( C7 K) g
3 h$ A/ }% x) E' y) v5 K6 a# z7 P
因为使用微库的话,不会使用半主机模式。9 S+ j" W. F& B8 @+ j, ?8 w2 J
如下图,在点开MDK软件的魔术棒,勾选Target选项卡中的“Use MicroLIB”。这样就可以使用printf()函数,通过USART输出数据到电脑串口助手。
% c$ \+ {3 k1 L: m在主程序中添加代码9 M Y, L8 j# S
4 a/ H2 ?6 O) l! u' O6 T4 `1 M7 S1 r/ z/ Y f. I1 R, T/ t" x- v4 f
不使用Use MicroLIB(微库),就要在工程中加入以下代码, 以支持printf函数 。代码是写在USART的初始化文件中,记得修改USARTx,换成你要输出的USART端口号。
3 y# Q" R! ?3 B7 g5 O) P
. v) q& E7 p8 H4 T s% p5 A' s- /******************************************************************************* O& s7 ~! K5 O2 a6 P+ s5 U3 f
- * 【功 能】 printf函数重定向支持代码+ r/ ?$ y8 j+ a2 I
- * 加入以下代码, 使用printf函数时, 不再需要选择use MicroLIB ' v& f3 e1 v3 n( K
- * 参 数:
& o6 r! ?+ O$ k3 O2 V% y1 P- ~ - * 返回值:
/ L4 f7 ]2 A9 Z5 z2 b - ******************************************************************************/ 7 ~# u* v5 `. X0 S! ]) R7 n$ i' ~
- #pragma import(__use_no_semihosting) //为确保没有从C库链接使用半主机的函数
( H/ y+ l8 e C - struct __FILE { int handle; }; // 标准库需要的支持函数
7 {1 _2 F8 b% j8 G l% | - FILE __stdout; // FILE 在stdio.h文件
* G+ s+ R9 J5 e: N. b1 {! y - void _sys_exit(int x) // 定义_sys_exit()以避免使用半主机模式
1 G7 L( s7 `7 G' ? - { x = x; }
* l9 `- W0 b, ?
/ c3 E' x" x7 v" \- h2 O- int fputc(int ch, FILE *f) // 重定向fputc函数,使printf的输出,由fputc输出到UART, 这里使用串口1(USART1). L7 t9 E, \' H. ?2 G( K) P
- {
* w- o# \! M1 l. o7 u - //if(xFlag.PrintfOK == 0) return 0; // 判断USART是否已配置,防止在配置前调用printf被卡死/ t3 y. j* T" k, x2 _* ?9 r
- % o5 C# p3 Q7 c s K& x F
- while((USARTx ->SR&0X40)==0); // 等待上一次串口数据发送完成
& ~* s3 o# ~+ k H) A& C6 W - USARTx ->DR = (u8) ch; // 写DR,串口1将发送数据 e& X* u: k+ c$ y8 F
- return ch;9 v R! x* A6 I- ?" O* v% E7 N
- }
复制代码
) R) z6 x- e+ Q" Y) {2 t+ a1 d. L( O& r* ?/ |, }: I! _
1 X8 F* E/ x1 `8 ?8 y( L: f- K |