|
本帖最后由 harvardx 于 2015-1-24 21:52 编辑 1 前言 ' U2 g( {( N; c( N* U, P. {8 a% d 友情链接: 沐紫妹妹关于最新Nucleo - F091RC开发板介绍以及相关的nucleo介绍" _% C. K# V( ]9 H( r9 P! C7 N: ? Nucleo平台最新开发利器——ST Nucleo-F091RC开发板评测1 k3 g$ |$ q% X0 Z) Y; ]# J https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=599462&fromuid=2039986' M! ^6 _2 w/ {" y7 [ 3 u& E3 ~9 ^% I8 z 8 w5 _& j( w: E; h+ l6 J ( y7 b" B% t4 \2 i ST的上新速度真够快的,如果是一个淘宝店铺,肯定是钻石带星的. 这不, STM32F091RC -nucleo 开发板又来到了我们的身边! Nucleo家族又迎来了一批新成员, 像咱们社区刚刚提供给大家的STM32f334- Nucleo 开发板. st的技术更新让我们应接不暇, 可以更加天马行空的选择自己的MCU right.拿到最新的STM32F091RC -nucleo 开发板.老规矩,先评测几个简单的例程. led_toggle, key, ADC ,DAC神马的 ,几种开发方法,大家估计都耳熟能详了. 这就是Nucleo的好处. 统一的外形,统一的包装,统一的开发方法. 真正做到了 All in one,大家所需要关心的就是自己想要实现什么应用,做些什么,底层的细节, 驱动,io分频神马的 ,都可以直接套用. 如果你要 Hello world一下,在nucleo开发板上仅仅需要, 选择不同的mcu编译就可以了. ( t3 W1 U" E, M. H + D& D! a: t4 R 2 回顾 7 S$ }6 c* ?9 E4 A 简单回顾一下, nucleo系列的几种开发方法,以最新的Nucleo 091开发板为例:+ D* T; k5 D0 x. l7 G 1. nucleo 091 可以mbed开发,比较新颖, 也比较简单, 但是是cpp的, 可能很多同学太适应; 目前mbed.org已经有091系列的支持,大家可以登录mbed云端查看;8 N+ c4 q* ]0 W' }- Q 4 W& n t* {' X& J/ G7 V# P 2,标准外设库,目前标准已经到了1.5.0版本, 可以到此下载: 下载地址: http://www.st.com/st-web-ui/stat ... 0_stdperiph_lib.zip 标准库解压后,有很多例程,其中包含了091的 ,可以到STM32F0xx_StdPeriph_Lib_V1.5.0\Projects\STM32F0xx_StdPeriph_Examples/ W4 B7 J1 h, b9 U, X 目录下查看,怎么使用这些例程呢, 在里面的Libary_examples.html网页有说明,如下: How to proceed?
3 Cubemx库,这是目前st比较推崇的. 目前pc配置软件CubeMx已经到了最新的4.6.0版本9 Y3 t7 d9 n R2 C& e" b# w5 S 下载地址: ( http://www.st.com/st-web-ui/stat ... ite/stm32cubemx.zip), 2 l( d( N+ R" _6 h9 P+ j 同样支持F0的cube外设库CubeF0已经是1.2.0版本) c; H+ s* w9 b, q+ y4 C 下载地址: (http://www.st.com/st-web-ui/stat ... are/stm32cubef0.zip) 其实Cube终究也是库,只不过代表着更加先进的方案,相信在st巡回研讨会上大家都有所了解.记得很多工程师刚开始不太适应,其实是更加方便我们开发,至少他可以通过图形化,来快速配置我们单片机.生成所需要的模块初始化或者操作代码. - o& ~1 |) v- y % p- p8 v5 c5 p2 h4 h 3 CubeMx结合CubeF0_V1.2.0 库 开发 Nucleo -STM32F091 开发板实例 0 H) p( K9 X1 Q8 n1 X 因为 091比较新,在keil4下,需要添加官方的dfp支持包, 否则将看不到这些器件. keil5就好办多了. 可以通过pack installer来进行. 这是在开发st最新单片机时,需要面临的问题,具有共性. 一般情况下,如果库(标准外设库或者cube库)出来了.可以在STM32F0xx_StdPeriph_Lib_V1.5.0\Utilities\Third_Party这样类似的目录下.找到这些支持包. 标准库1.5.0下的例程很多还是uv4工程的, 最新的\STM32Cube\Repository\STM32Cube_FW_F0_V1.2.0\Projects\STM32F091RC-Nucleo\Examples\里面的例程好多已经是MKD5工程了,非常好.免除了同学们添加支持器件的麻烦,直接通过更新pack intaller就搞定.而且无需去复制模版到每个驱动模块的例程,在外设驱动模块的例程中,已经帮我们添加好了工程.直接用mdk5打开就可以.建议大家升级到最新的MDK513测试,感觉很好. 首先上一个最简单的例程,1 m- p5 Y' e2 E% S: J( a& c/ t
Nucelo_091_ledtoggle.zip
(4.97 MB, 下载次数: 1031)
|
微信公众号
手机版
关于例程中的ticker 其实就是定时器,大家可以看下面的详细说明:" J; Z% f' [# K; V* q2 w
mbed 时钟系统, o- m! ]; p. ^3 D
微处理器的大量应用都和时间相关,如我们前面代码中多次出现的wait函数就是最常用的时间等待函数,显然,精确的时间等待必须建立在精确的计时技术上,这就需要用到计数器系统。' a* O5 N3 T" H0 P M
* ]% [: l8 L3 Q5 x* y/ h
计数器的工作原理非常简单,就是每当它接收到一个脉冲时,它的计数值加一,一旦它的计数值达到用户设定的阈值,计数器就会产生一个中断信号让系统处理并重新从0开始计数。根据计数器可设定阈值的大小,我们可以把计数器分成8位计数器,16位计数器等,8位计数器可设定的最大阈值为2^8-1即255,16位则为65535。如果我们给定的脉冲信号频率为1M,而给定的计数器阈值为0,那么计数器就会每1us产生1个中断信号,这就为系统计时产生了依据。对于xbed LPC1768来说,它有四个通用计时器,它们可以用来计时、PWM输出等。. ?3 B3 u) b5 Y' T8 U
$ f! o' y( w7 V
. H+ C, R, p6 v# P
除了wait相关的等待函数以外,mbed还提供了三个对象用来完成和时间相关的功能,分别是Timeout,用来在给定的时间执行特定函数;Ticker,用来定时执行特定函数;Timer,用来给系统计时,它们可用的方法描述如下:
类名- M) L2 P! W% r* ~2 l( P
方法9 I- Z# l0 x9 @+ h6 X0 |
, b8 t! Z" \! x$ {* i8 |0 v
用途
Timer( s: U4 ]+ W" ~/ v" \
Timer();
2 [+ x% y- ]4 @0 D
构造函数,实例化Timer对象% V, p6 x% k3 E$ Q& j; _. j
) |( o. L( ?3 j! p9 ?) w' @
void start();. }9 _" U( n* }
' J# t* O. l4 T' Y+ T: l5 V- v
开始计时1 V! C4 v5 s6 _. q2 d
) g9 J0 u, W% X6 V4 P6 k
void stop();
停止计时# r) g; l0 [7 p: z
4 V/ A' O* _$ R" i9 T3 A& U
void reset();
重新计时,即把时间计数恢复从0,如果原来处于start状态,那么计时继续5 c3 c) h' V& q' Q
1 L0 y7 S r+ b2 g& O( ]
float read();, c' X, m8 x H k# k$ ?! M: x+ G
读取计时开始后过去的时间,单位是秒1 G! j; g8 \5 Y
9 e7 G( O% B, {! t" z; `: D \/ S4 z0 F
int read_ms();
读取计时开始后过去的时间,单位是毫秒( p* E5 Q2 P: W
# C4 a% |, j$ x* a
int read_us();* I' m" ~/ V* W0 K' Y6 ~2 I3 i
读取计时开始后过去的时间,单位是微秒7 W( j) w8 u) H0 a
3 ~( R- f& ]8 y* u1 h
operator float();
2 }+ Z- P9 K1 [7 a9 o3 J3 c7 Z4 w, \
操作符重载,相当于read
8 q% v- x4 E( e1 a2 d( b' O
Ticker* t3 a" s+ h0 j$ q4 q' v' U
Ticker();
构造函数,实例化Ticker对象
void attach(void (*fptr)(void), float t)6 a0 j* h+ q) e- ?. p+ Q
设定每t秒需要执行的函数
void attach_us(void (*fptr)(void), unsigned int t)& Q* R9 [6 ]% _5 \
+ }8 u4 w9 ]* @ T/ { o
设定每t微秒需要执行的函数
void detach();
* [, T6 r4 ^& \
取消本对象需要定时执行的函数" O+ N4 O, M& c: \8 o
Timeout- P' O+ D$ L5 Z: K- w
) i4 N7 v4 G: ~1 T4 g
Timeout();1 ` I( p% _! e( ~; Z5 l, q; J
! v% m7 X2 S3 e* t6 \- J, b
构造函数,实例化Timeout对象 {! g7 C' D7 [' A1 N6 w& [
2 y& v& h; ~, X0 G: c0 \
void attach(void (*fptr)(void), float t)
( l& q$ Y; }2 o$ q) r5 P& q7 n9 m7 d
设定t秒后需要执行的函数+ n, q9 \$ T; n; N( O# ^
4 F; ~; Z8 h+ D$ s2 n
void attach_us(void (*fptr)(void), unsigned int t)
设定t微秒后需要执行的函数
1 C' q r, H5 K0 n
void detach();7 ]4 v# |5 ^* m
( J9 p) U3 l6 t N; P
取消本对象需要执行的函数& \" b# e& D4 N! T" `
, e, W7 a8 G1 z {8 y. s$ o
mbed Timer的应用
4 u$ n" ^0 x2 \& _; a
mbed的Timer对象主要用来计算用户关心的时间间隔,下面是一个简单的示例,可以计算用户按下按钮的时间,主要代码如下:& P7 m, Y7 o4 j1 U, ~7 J s" E
Serial pc(USBTX,USBRX);
3 @! }# V6 _* M4 w
InterruptIn btn(P2_8);
( d" C' C1 B, M, s/ O; \
Timer mytimer;
int falltime;
int risetime;% h$ A" E Y0 c" Q1 m( k
/ ~" p/ y5 v, Y- Z$ i( ~6 a
void fallfunc()& w5 S- g( ~! n% Q" j t
{; \3 s3 O) t7 y5 P ]; t
1 ~$ M$ q; K( K
falltime=mytimer.read_us();
}
+ m. P Z8 R7 V% Q: u; S
void risefunc()9 s. z" g# x" z7 Z' {
3 M1 _, t6 D4 G# q3 k* s
{4 w5 u* t/ o! _
risetime=mytimer.read_us();! }$ @. }1 w# V [( y+ `
pc.printf("You press button for %d us \n",risetime-falltime);
- s$ o& G1 R8 U; k, t
}0 r4 T0 G; y) ]3 e
5 `) j! ]5 r2 g: [
int main() {
mytimer.start();
6 f6 S6 K6 \8 T( g; `4 J) k
btn.fall(&fallfunc);% D, Z$ Y, h4 {; L3 u9 ?
btn.rise(&risefunc);
, P$ z( i. H8 x7 z' Y& G
while (1);: J# l. ?* E' F- J
: n0 d4 C& \3 x3 {- D* G
& { J* }' P) y* t& `- ?# g. f
9 Z; P/ R8 [) \3 e
}
程序运行的结果如下,当然,我们需要理解,任何中断的处理都有一定的延迟时间,所以此结果还是会有一定的误差,但绝对在us级别。
, Z& j( z* g2 ^. F- T1 b9 u
You press button for 330410 us
' }+ Y; D! f$ P1 Q
You press button for 137603 us
* L" V. j) w, _* Z1 J
You press button for 122679 us
You press button for 140683 us. G2 J5 B5 k5 e
有时候我们需要利用多个Timer来计算不同的时间,这只需要定义多个Timer对象即可:
Timer timer_led;
. ]9 K0 X. s; b, I/ x! J9 p
Timer timer_serial;
DigitalOut led1(LED1);/ u& @ P+ n7 N# e9 Y
2 x$ N/ d+ t% ], |
Serial pc(USBTX,USBRX);) `6 t* u, u; K
; O7 y; N: i4 @( ]4 p; l
void task_led(void); j* `9 s0 N6 o) B$ s+ G' _
3 m3 I' c8 P1 z
{
led1=!led1;3 D) }: C. t6 ?: O
}
void task_serial(void)
; w& L+ `0 Q) R
{
pc.printf("Timer passed %d ms \n",timer_serial.read_ms());
$ r& Y/ c# s5 i7 {, n8 Z+ U% O$ U
}. r. H6 e8 n% B) W+ ?- P, y
) Z% [) l. l( J; ]
int main()
! M( |# y1 `8 z# H4 }7 s$ H( b
{3 u& K2 e8 m O$ |8 v, Z
& q6 O, |; @: V3 x1 }, l9 o9 p' \
timer_led.start();) ]3 F; A" R3 v7 i4 p
' M# f% h; Q9 M
timer_serial.start();6 W! Y: p$ U6 }3 _3 Z( u4 K; [# g
while (1)+ D' {2 I7 q0 C9 g
{
if (timer_led.read()>0.5)
4 [6 E1 d3 S' a- V! F: g. [
{
task_led();
timer_led.reset();
. H1 Y& ?; V( H% v6 R
}% Y+ g# o3 A& @5 `' r
if (timer_serial.read()>1)4 x; @0 r4 H. V$ V0 F8 ?8 n
& m# j4 T( f* X
{ //test Timer value
task_serial();1 @5 v4 z5 u: r/ G" W0 H; j
$ W$ p+ P. ~& ?/ Z
timer_serial.reset();
}. l5 U, b$ Q# q& |3 y
5 {; Q, N+ x3 h; a$ E5 V
}
0 m2 t1 _; q- F9 ~) f; E( j
}, c1 w$ Q8 I# s9 l
. o: F3 P1 V, H0 |
mbed Timeout的应用
mbed的Timeout对象主要用来在给定的时间后执行给定的函数,如下面的测试代码,运行后你会发现xbed LPC1768的四个led分别点亮,由于timeout只会被执行一次,所以点亮后会保持不变:
DigitalOut led1(LED1);& E: B) q1 t5 H3 Q: I: t8 D% g
DigitalOut led2(LED2);2 k( ^( h0 h2 i8 \
, S( \2 E9 b' G, f. B
DigitalOut led3(LED3);
DigitalOut led4(LED4);
9 F( d* m( c) y% L' S2 O
Timeout timer_led1;+ {" k% T a# y- q3 D. n( Z
Timeout timer_led2;4 r9 w3 y7 ^8 R& N1 }6 U/ J
" v5 [! {" N( Y* O. Z
Timeout timer_led3;
$ t6 F7 b4 J' V2 j6 Q- U9 M
Timeout timer_led4;* Z; i& K3 P8 u ~
void led1flip()0 v u) M7 R& e
{: x. `8 @& B$ l9 M1 Z7 A, ~/ ]
led1=!led1;' g' f9 Q) y, E' ~& a3 D' E1 T
}
void led2flip()
3 u) I- N% ~2 q* P0 l. K' w
{$ u: s5 e& D0 x8 E2 m+ q9 N
& X a# w9 ^1 v4 ~9 |) A
led2=!led2;
; R, L+ Q6 w4 f! K) q* S
}
; F* x% z1 ]% N {: ~; ^/ y! z
void led3flip()
{& e% F) R9 l `& ?5 N- E. T$ o
led3=!led3;
9 l7 A; p: U/ I0 j% H; B7 r$ K. ]
}
void led4flip()
; @- z+ N4 s* t$ H
{) r2 _5 G; I' Z$ m% @
/ J4 p5 G. e: w: J! k( r5 P
led4=!led4;
}/ Y1 c9 N/ z3 v# R1 ~( s. G
int main() {) n6 L- U& D+ _6 w2 u
+ ?: j& }0 ?0 }% ?
timer_led1.attach(&led1flip,0.5);6 Q7 M" l O+ J9 \" r1 \/ i% U
" G6 g% E+ L6 e0 {
timer_led2.attach(&led2flip,0.5*2);, w& x; H# b* ^8 I* f% H( r
/ Y v9 l/ {7 f/ [
timer_led3.attach(&led3flip,0.5*4);& i* s7 h/ A/ \" C& a* _" u! W* L
! ~* G: }9 [ |3 b6 m( f
timer_led4.attach(&led4flip,0.5*8);4 E0 e$ G4 Q; B( d" e( Z2 m2 H
while (1);
& C( L* z9 v* P, y! t! S
& c! y- ]4 W2 j- v" \& ^+ A
}+ J1 D3 e Z9 I
8 M7 ^9 E, Y% K0 [# @1 R
mbed Ticker的应用8 @ A# Y9 a0 n- M/ s) P
mbed的Ticker对象主要用来执行各类需要定期执行的函数,它和Timeout的唯一不同就是Timeout相关的函数只会被执行一次,而Ticker相关的则会被定期执行,如下面的测试代码,运行后你会发现xbed LPC1768的四个led将按照不同的频率变换:
# E o6 j, o) I/ s/ V3 k) v
DigitalOut led1(LED1);
( n3 {" T7 v) w3 G$ ^/ ]3 _
DigitalOut led2(LED2);
DigitalOut led3(LED3);1 T6 b# A% e8 V
1 X V$ j5 Q7 `: `% L
DigitalOut led4(LED4);* O: ?9 O8 L. H" j
Ticker timer_led1;
$ m* @7 a5 x1 H, v( `* z
Ticker timer_led2;' T" c7 W$ X8 }, q6 n; i
Ticker timer_led3;# F$ G6 l# R/ R4 p' L& I) u
+ Y( ^$ k0 w8 k* X# k, _5 E) ]
Ticker timer_led4;1 z a$ A3 f/ J' S: U6 d
void led1flip()* U& U* v2 n6 e; I4 i
{; R3 _& x+ r5 U- u1 F9 ?% P$ k
led1=!led1;$ T& b4 P1 M) c% s D4 z5 ]
}
+ |8 f: F4 R; t9 a% p
void led2flip()) Z1 E9 N: ~8 b2 a" j
. v! K7 D" e4 Y* S: S
{; L, @+ Y( w, W2 A! t/ k+ U9 y
6 ~* ~! R2 l5 H4 w3 k4 k2 H
led2=!led2;' }- |4 }( E7 ^" b* p
}
void led3flip()! y7 m {: M6 u. V$ s" w& y" D
{$ `6 `0 Y) s+ | X/ E
led3=!led3;! b T+ l% w" Y7 D- \
; {. t: d! b5 R9 @/ b$ z5 e
}" y. `6 A5 w* x3 b* [2 n. W
void led4flip()
{. i! l6 _9 A; W5 e
2 S0 W/ c# f8 k+ o6 C) r6 l7 m
led4=!led4;# |4 s0 \) O" q! E& ?3 l3 H& V
V- O& x+ A2 ?4 N, l% H( Q
}
& w, g/ i# X7 v
int main() {
3 G: H( j n8 x2 C
timer_led1.attach(&led1flip,0.5);# Z1 o2 K7 n- T0 _; B- g
timer_led2.attach(&led2flip,0.5*2);
timer_led3.attach(&led3flip,0.5*4);
+ g' m4 G1 F& E+ | _# G
timer_led4.attach(&led4flip,0.5*8);
6 t& f% Q" ~ n% {+ C; `$ [( @6 Z& k
while (1);1 H' O) F" n6 T$ m/ |% }* R1 ?1 p
4 m2 t |4 ]: p# H I0 h& p( U
8 ? J# y. j' v) s+ S
}3 [7 I. N4 `/ i& m" R7 E, h' F
/ j; |# b0 g1 w
我们在使用Ticker对象的过程中还可以随时对Ticker设定的间隔进行更改,更改后的时间是即时生效的,如下面的代码,我们发现,用户每按一次按钮,led1的闪烁频率就会加快一倍。
: u9 Y, O& ] j
DigitalOut led1(LED1);
InterruptIn btn(P2_8);
Ticker timer_led1;, F. ?1 `( I7 S% c: x. ^
float interval;
void led1flip(); u4 h) y0 c$ Q( B5 F m2 d8 U. H# A; U
$ L9 k, y; X$ c, U8 l
{ @1 |' g1 b7 k, P
9 [# t2 |& A s
led1=!led1;& f$ O: o7 B# P) }& L, J( Q! z
}
' C, z' d2 P% U9 t3 r. B1 o5 v
void changefred()
{
interval=interval /2.0;
timer_led1.attach(&led1flip,interval);8 L: T: a0 \5 j
}! X( c( \: q2 z
int main() {
4 a8 \# D) d9 ~- [
interval=2;
btn.fall(&changefred);5 p: U w L; l: D
timer_led1.attach(&led1flip,interval); c4 s7 p1 N5 `8 d' y
, u7 v1 N6 N3 [* x& a5 V6 {
while (1);
: C- E4 i6 V5 k# k8 Y F6 Y8 T6 \
) I8 ]8 O0 }/ |/ {
}
; s7 h% p! y/ o1 m# |# |2 Z& s
那还得再下载个其他的压缩的软件,,比较麻烦。。。1 \0 R! d1 y9 o9 r, r. u/ V
; X. \8 B% d8 q/ p4 u# V( F
, [0 @0 w- g( O2 d/ R
建议楼主以后压缩的时候压缩成常见的压缩格式,,方便下载者
8 i3 r7 } C. F# D' U2 W
( c& |% _+ O3 ]: z& k7 J/ B7 p
有的 .下载最新的F0_1.5.0的标准库. 里面有072的例程. cube_fw_1.2.0库里面也有nucleo 072的例程.哈哈
帖子的地址有,下载最新的1.5.0的标准外设库.里面就有