本帖最后由 harvardx 于 2015-1-24 21:52 编辑 1 前言 , F8 Q$ t7 d) t6 D# F8 z 友情链接: 沐紫妹妹关于最新Nucleo - F091RC开发板介绍以及相关的nucleo介绍 Nucleo平台最新开发利器——ST Nucleo-F091RC开发板评测 https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=599462&fromuid=2039986 5 A3 i( I* T( H7 R4 |- d; Z" q7 n" o 7 m' h. h) u( M% Q" x 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编译就可以了. 2 k8 s) |; W; j; u9 P ) X" R! Y& n1 f9 d7 @ 2 回顾 . q% W/ E, P6 }2 y9 Z, _ 0 {# C: E2 L! f9 N% n% |) g" J3 c+ c, j 简单回顾一下, nucleo系列的几种开发方法,以最新的Nucleo 091开发板为例: 1. nucleo 091 可以mbed开发,比较新颖, 也比较简单, 但是是cpp的, 可能很多同学太适应; 目前mbed.org已经有091系列的支持,大家可以登录mbed云端查看; 2,标准外设库,目前标准已经到了1.5.0版本, 可以到此下载: 下载地址:; \/ u, \; a; G* _ http://www.st.com/st-web-ui/stat ... 0_stdperiph_lib.zip % g, b# m# l! R* |* Q 标准库解压后,有很多例程,其中包含了091的 ,可以到STM32F0xx_StdPeriph_Lib_V1.5.0\Projects\STM32F0xx_StdPeriph_Examples 目录下查看,怎么使用这些例程呢, 在里面的Libary_examples.html网页有说明,如下:4 r2 |* ^- w' w3 @4 |* u" z How to proceed?
8 F1 G2 c3 f+ `1 L$ ?5 H, e 3 Cubemx库,这是目前st比较推崇的. 目前pc配置软件CubeMx已经到了最新的4.6.0版本* o1 M- K- H, _/ a7 w' u 下载地址:4 v Y) ^) A; r1 b0 f, s: ]& Q. W ( http://www.st.com/st-web-ui/stat ... ite/stm32cubemx.zip), 2 Q% n$ Z# d( x4 L. ]1 P 同样支持F0的cube外设库CubeF0已经是1.2.0版本 下载地址: (http://www.st.com/st-web-ui/stat ... are/stm32cubef0.zip) / @3 j% y" S( K- ]6 I+ w 其实Cube终究也是库,只不过代表着更加先进的方案,相信在st巡回研讨会上大家都有所了解.记得很多工程师刚开始不太适应,其实是更加方便我们开发,至少他可以通过图形化,来快速配置我们单片机.生成所需要的模块初始化或者操作代码. 3 CubeMx结合CubeF0_V1.2.0 库 开发 Nucleo -STM32F091 开发板实例 因为 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测试,感觉很好. 首先上一个最简单的例程,8 N$ T/ w; y0 x4 c* b9 X |
关于例程中的ticker 其实就是定时器,大家可以看下面的详细说明:
mbed 时钟系统
微处理器的大量应用都和时间相关,如我们前面代码中多次出现的wait函数就是最常用的时间等待函数,显然,精确的时间等待必须建立在精确的计时技术上,这就需要用到计数器系统。0 j2 F4 O+ q5 r) C: u |9 y( L
计数器的工作原理非常简单,就是每当它接收到一个脉冲时,它的计数值加一,一旦它的计数值达到用户设定的阈值,计数器就会产生一个中断信号让系统处理并重新从0开始计数。根据计数器可设定阈值的大小,我们可以把计数器分成8位计数器,16位计数器等,8位计数器可设定的最大阈值为2^8-1即255,16位则为65535。如果我们给定的脉冲信号频率为1M,而给定的计数器阈值为0,那么计数器就会每1us产生1个中断信号,这就为系统计时产生了依据。对于xbed LPC1768来说,它有四个通用计时器,它们可以用来计时、PWM输出等。
3 V' i& I8 x! M% i8 ]" `: V+ y2 G
# b6 }' Y) i @; V3 F1 \
|" a( w3 ~) Q1 [% C" c
除了wait相关的等待函数以外,mbed还提供了三个对象用来完成和时间相关的功能,分别是Timeout,用来在给定的时间执行特定函数;Ticker,用来定时执行特定函数;Timer,用来给系统计时,它们可用的方法描述如下:) n6 c' r5 J2 ~
类名
方法
& o6 q7 C. G. b+ k
用途9 G4 o/ {+ @8 P% j
7 v% }+ [" @& p2 q5 S5 T5 X
Timer
Timer();
8 d( ?0 b2 _& M k5 A% a
构造函数,实例化Timer对象
void start();
开始计时 \+ U6 |) @; i
void stop();; C8 q3 x% B3 j7 S& E
停止计时, e" i6 t6 ^: c$ f3 q* c. b
( _# U7 g- D: O2 D4 |9 C
void reset();. E2 ^" i% G6 X* L( U3 h$ x
重新计时,即把时间计数恢复从0,如果原来处于start状态,那么计时继续. _; L; y. B. y3 n0 ^7 p- E3 b
% L5 n# _, c4 c" j3 F2 [- L
float read();4 Z0 ?% Y: u, H# ^% e
读取计时开始后过去的时间,单位是秒3 s1 W5 ]3 e' H2 b6 k p! _
int read_ms();
5 i+ ~6 F" j+ G% x
读取计时开始后过去的时间,单位是毫秒
4 Y9 N) r, W1 m/ ]- t
int read_us();
读取计时开始后过去的时间,单位是微秒- Y3 X* \2 {( s% |( H
- D3 w: R8 ~" j& F# g7 B
operator float();5 a6 J, w4 t1 g% l& }
操作符重载,相当于read
Ticker) ^9 ~) R4 \5 C( S- [
Ticker();2 |; T# R5 f5 c8 m
构造函数,实例化Ticker对象: j# K4 ^% U3 ^1 b/ a$ }' c0 O; ~/ T0 z
* I1 V$ Y' c/ z; G3 A+ Q& [
void attach(void (*fptr)(void), float t)$ ` L' H6 B+ q
' l0 G& U0 Z( `- W
设定每t秒需要执行的函数
void attach_us(void (*fptr)(void), unsigned int t)
设定每t微秒需要执行的函数" m% S l; U! Q1 @% n, K1 Q
* S/ Y% S, a4 `/ D( E' d6 ~
void detach();
取消本对象需要定时执行的函数" H; \- x& H7 o$ N P" ^( J
. K" f, E/ X* o
Timeout' j3 k& \) Q# J; E5 x
Timeout();
( c& M% r6 g8 x: O1 ]0 d: F
构造函数,实例化Timeout对象
! ~4 i5 [. R. h) Z0 f8 J
void attach(void (*fptr)(void), float t)6 f- x7 W, H" z/ g+ ^& R
设定t秒后需要执行的函数
void attach_us(void (*fptr)(void), unsigned int t)9 J! _2 S# H3 s/ e. X
k9 t Z9 ~( Z. x+ C
设定t微秒后需要执行的函数
void detach();
取消本对象需要执行的函数! i% a1 _8 [, q" t' Z! W U) T& K
mbed Timer的应用4 b& S" i U% t6 B# E& C
* A. Y' z. T$ R" R
mbed的Timer对象主要用来计算用户关心的时间间隔,下面是一个简单的示例,可以计算用户按下按钮的时间,主要代码如下:0 C b, ^. S( E" h+ C
Serial pc(USBTX,USBRX);
/ J* @8 q& L, s
InterruptIn btn(P2_8);
) T1 {0 G2 o) |. X6 F2 y
Timer mytimer;
int falltime;; X/ q& A( J& c% O# Z% G
int risetime;% j7 N3 s+ K d* {
6 |) z9 ?& N" w3 l2 g! \: ]
void fallfunc()/ ?# p) @) h4 Q
b6 e0 V1 {. |5 G5 y `
{
falltime=mytimer.read_us();
}
void risefunc()* b4 ~ O9 M+ P) p- h, b
{, P8 y8 L' {- _0 @( I% ?4 @/ K
risetime=mytimer.read_us();
! N- I5 m, d& v4 x {, |
pc.printf("You press button for %d us \n",risetime-falltime);
1 t" R) k1 r* b9 d; o! G
}: W1 Y) e+ b, L' J% J5 y0 _8 R
int main() {
mytimer.start();7 l1 z6 K4 g7 C# a
btn.fall(&fallfunc);, Y1 ?7 ?: C8 H/ y- x0 W% ]
2 a0 ? A( o% a5 H2 Q3 X( p) l
btn.rise(&risefunc);) E9 d- l; w3 O# ?9 a0 m
2 K$ D7 `, B) I0 u( D
while (1);3 a2 E+ l- Q' G( u
V# }3 _4 i9 I- ~- K3 G2 i9 D3 n
}
" a$ x4 b& H( i: K y
程序运行的结果如下,当然,我们需要理解,任何中断的处理都有一定的延迟时间,所以此结果还是会有一定的误差,但绝对在us级别。: W2 q2 G+ E# p! W3 ]+ O& J
You press button for 330410 us: m/ P, d A2 N( w5 P, i
You press button for 137603 us* d, Z- F2 v9 I+ i+ o
/ L# `6 `" q" i) W+ a3 t. \
You press button for 122679 us% a4 u" ]% u, Y2 D+ z7 V- B/ p
You press button for 140683 us
$ |& a* N. M h, k# d! s& z+ r
有时候我们需要利用多个Timer来计算不同的时间,这只需要定义多个Timer对象即可:
" T( b/ P9 U: \2 ^' ]
Timer timer_led;
/ b1 Y4 _8 }+ m! H% V7 A9 F: U; N
Timer timer_serial;2 P2 v& a. G; O) ~
! m& s0 i0 l6 l7 T1 f, w+ ]
DigitalOut led1(LED1);3 E4 V) X" k/ p% c3 m+ i8 @% r
Serial pc(USBTX,USBRX);
void task_led(void)
{. l% u& I6 [/ ^0 T) L+ k- }$ \
: _, ^6 H+ G, h% {! m) V5 d
led1=!led1;4 L6 t( C2 n; `
8 Q; k5 M$ {% w, Q- O
}
void task_serial(void)
{% ~ c6 t9 r% s* C
0 }7 _8 S/ _. ^
pc.printf("Timer passed %d ms \n",timer_serial.read_ms());$ g3 g5 W4 Y: ]9 a2 E9 g s
" o# \5 P! ^! _7 f8 e2 ^1 t
}
int main()
; ^3 v9 u3 A0 x& C e) p, H/ X8 A
{
9 x _$ h# ?% U7 l% @6 J
timer_led.start();
) J: {8 }. |% i
timer_serial.start();
6 X! v! m0 t' m4 e
while (1)+ w* M! b- B8 W7 a
{
if (timer_led.read()>0.5)
{
* }9 d/ Z/ J) s% }% B
task_led();
timer_led.reset();
/ K+ E; T* [( O" k' X9 A6 a
}$ z6 A+ z2 y0 [! }
if (timer_serial.read()>1)
{ //test Timer value% ~* g @$ |. J
task_serial();
. b+ L7 l* F6 u: |
timer_serial.reset();
}6 _( ~# J* G+ v8 s' }
}
! j/ K6 }/ ^- H! F& ?6 h* _
3 K3 ?$ l; \6 F- K1 t3 ?
}
; I6 O9 D' \- d
mbed Timeout的应用, Z6 d. i1 D. ^7 @ L
+ L8 H8 `' i2 \( L( P
mbed的Timeout对象主要用来在给定的时间后执行给定的函数,如下面的测试代码,运行后你会发现xbed LPC1768的四个led分别点亮,由于timeout只会被执行一次,所以点亮后会保持不变:
DigitalOut led1(LED1);
DigitalOut led2(LED2);1 _0 D& R, }4 F, v
DigitalOut led3(LED3);
DigitalOut led4(LED4);
Timeout timer_led1;& h& f7 ]$ ?+ v$ d& V$ P% W
Timeout timer_led2;
Timeout timer_led3;
. P% b& s$ N4 w. p" y; t/ W1 B5 Y
Timeout timer_led4;8 I' I8 ^6 X. N* @: f( g' _
void led1flip()
2 u& v; Z1 M5 {4 ^
{
2 E i- l% J$ X7 C! T
led1=!led1;
}
# X* |0 t" l! ^
void led2flip()- U( k. E+ K9 X- E' A! L+ w
$ `; H# @( x. @/ r, a
{) R. v% f% Q0 j; K$ k* P
\6 W) j+ N2 B' ^7 O3 {
led2=!led2;: T2 d! H1 b. P3 n; Y6 S; l
6 E0 `% ?6 H$ z7 j& M
}/ K% a/ h7 ~# Y N" G; g
: U+ _5 Y+ g1 |; o1 F
void led3flip()
{+ H# Q4 m7 {( ^, C, X+ d, ^. l) C
5 [& I' q: h' O# t! g2 i
led3=!led3;0 ?. M! M' h- ] @+ Y' A
* j+ z% q. D- c. q3 z! {$ o
}
, C+ s; X# g& {5 F5 {0 a
void led4flip()
{
led4=!led4;
}# b) P, p+ h8 j6 `$ s
int main() {
timer_led1.attach(&led1flip,0.5);
timer_led2.attach(&led2flip,0.5*2);, y# B. i- a v/ F' ^0 S
1 }- V& K5 y5 a! x
timer_led3.attach(&led3flip,0.5*4);
( c$ V. h8 A8 ?' q+ G
timer_led4.attach(&led4flip,0.5*8);
& ? u0 x' u" u A' Y
while (1);
0 |# j# a6 i8 @$ e6 I2 R Z$ i. Q
; e K4 A w, N3 B& G, n+ a
}: X% M6 o8 }7 F- j7 u b
- F8 v' y) N* v; V& }) @" S* r
mbed Ticker的应用
mbed的Ticker对象主要用来执行各类需要定期执行的函数,它和Timeout的唯一不同就是Timeout相关的函数只会被执行一次,而Ticker相关的则会被定期执行,如下面的测试代码,运行后你会发现xbed LPC1768的四个led将按照不同的频率变换:
4 X0 O- V' U% Q/ D& Q+ {8 U
DigitalOut led1(LED1);
2 R, E, ^$ S0 {! W2 H
DigitalOut led2(LED2);
DigitalOut led3(LED3);
+ X- n- _( m7 }; p) ?: t- d
DigitalOut led4(LED4);6 Q1 k: A! K5 C
1 F) O2 M2 h( D7 L
Ticker timer_led1;
8 W. K* C$ }+ ~. B
Ticker timer_led2;
; j2 l( f4 i U& Y
Ticker timer_led3;
Ticker timer_led4;
3 x; a+ ^( c, v- s/ i+ X( |; b
void led1flip()
5 P/ Q6 D+ a1 g( f' e1 R
{
1 ]4 D; V" k$ o, a! L& [9 y9 s
led1=!led1;* Q2 ^8 A3 ~2 `: n
* Z- q6 u C* [0 z
}
void led2flip()
{
led2=!led2;
! B' B3 t3 {" ]% L7 F
}
7 U/ c) Y! I* K; F% J# ^! O+ E
void led3flip()( C2 Y9 d4 B. {6 f5 p
{1 i' z9 c! P: U7 q6 v' v8 t( F
led3=!led3;* x( |* K, b+ h; ~& c s* M
, G$ O: ?1 Q9 w
}
) A' Q( z" C% G/ J7 Y6 K/ O, k
void led4flip()
& _ x8 X! N V
{
led4=!led4;
6 f6 L$ T4 u ?, e4 n7 D2 W
}6 C3 l: Z! d6 Y
9 w) j0 } I$ [( {. k; h
int main() {
- X2 X0 A1 B. R9 ~; c' `
timer_led1.attach(&led1flip,0.5);
timer_led2.attach(&led2flip,0.5*2);
timer_led3.attach(&led3flip,0.5*4);2 g2 q3 q! C& M) c# e
+ y: {. x0 S1 b- D6 F
timer_led4.attach(&led4flip,0.5*8);
8 C% K& L! Q8 n2 T* L- B
while (1);
! b, Q7 W7 G2 I
}$ U( {* g. w8 S3 H! p
我们在使用Ticker对象的过程中还可以随时对Ticker设定的间隔进行更改,更改后的时间是即时生效的,如下面的代码,我们发现,用户每按一次按钮,led1的闪烁频率就会加快一倍。
5 R0 ^1 F7 `, w7 F& ^5 b
DigitalOut led1(LED1);6 L T6 g) n& \
InterruptIn btn(P2_8);* ^8 t/ v& F6 @/ y' U4 s+ Q
Ticker timer_led1;6 \/ A H3 O* T4 s+ U
5 o: B5 C" {7 d, G6 ]
float interval;
void led1flip()0 y6 } e% K) F8 W3 u2 F0 n
{
& N- E9 }. L1 S0 K- Q! F, v$ v0 l
led1=!led1;
( a2 W' J# w0 o7 N! ^9 ^
}) O- a$ p, z' v# ~7 D
* `8 e$ m/ j% `
void changefred()# m; F2 c7 C. F: A1 b2 l0 b
8 W$ d3 X% w% A7 Y/ [) {/ W
{8 W" ?1 r2 n2 |' a8 G4 D4 g
1 {: p9 H! p0 D, h }% E4 w) c
interval=interval /2.0;
/ n2 Y- @* }2 L: `3 D( }. j
timer_led1.attach(&led1flip,interval);
}6 W5 b8 P5 m/ ] W6 Z
int main() {
interval=2;
btn.fall(&changefred);
timer_led1.attach(&led1flip,interval);4 h( \: f6 \0 y+ J
while (1);. B6 l& N+ k) J$ v
3 o6 d" @8 |9 K0 _" o. q" Q
- z6 E' R$ z3 K; Q
6 b2 [5 _( X6 C/ x! h0 b
}
8 O% K) U5 ^* E$ t5 O. s
$ b) [7 f( _6 t' W' u9 b" x* V
那还得再下载个其他的压缩的软件,,比较麻烦。。。
9 T8 j$ n5 b3 M
建议楼主以后压缩的时候压缩成常见的压缩格式,,方便下载者, A7 t8 A% e. ]
7 A$ N0 w, W8 y) ~
有的 .下载最新的F0_1.5.0的标准库. 里面有072的例程. cube_fw_1.2.0库里面也有nucleo 072的例程.哈哈
帖子的地址有,下载最新的1.5.0的标准外设库.里面就有