|
本帖最后由 harvardx 于 2015-1-24 21:52 编辑 7 d, Y8 ^- s' |3 ~0 j5 @ 1 前言 友情链接: 沐紫妹妹关于最新Nucleo - F091RC开发板介绍以及相关的nucleo介绍 Nucleo平台最新开发利器——ST Nucleo-F091RC开发板评测/ N, y: x3 B9 E https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=599462&fromuid=2039986 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编译就可以了. 9 U; I; s2 ~4 s5 w$ t& K( k! k 2 回顾 ' Y! e- @4 h$ |0 p: T ( Z1 E' ^( Q5 F, [. s4 l% P 简单回顾一下, nucleo系列的几种开发方法,以最新的Nucleo 091开发板为例: 1. nucleo 091 可以mbed开发,比较新颖, 也比较简单, 但是是cpp的, 可能很多同学太适应; 目前mbed.org已经有091系列的支持,大家可以登录mbed云端查看; 2,标准外设库,目前标准已经到了1.5.0版本, 可以到此下载: 下载地址:" l$ ^, ]8 a, P# x6 s http://www.st.com/st-web-ui/stat ... 0_stdperiph_lib.zip " _% o* e4 h" S- O, m4 ^) y! y 标准库解压后,有很多例程,其中包含了091的 ,可以到STM32F0xx_StdPeriph_Lib_V1.5.0\Projects\STM32F0xx_StdPeriph_Examples7 ~& V/ d+ P( h# n 目录下查看,怎么使用这些例程呢, 在里面的Libary_examples.html网页有说明,如下:2 V; ^ c, V" K. a: I How to proceed?
5 e& _6 R: a+ ~$ f5 @ t * X- p% |0 L, S$ l( J' Q% b& e 3 Cubemx库,这是目前st比较推崇的. 目前pc配置软件CubeMx已经到了最新的4.6.0版本 下载地址: ( http://www.st.com/st-web-ui/stat ... ite/stm32cubemx.zip), 同样支持F0的cube外设库CubeF0已经是1.2.0版本 下载地址: (http://www.st.com/st-web-ui/stat ... are/stm32cubef0.zip) 其实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测试,感觉很好. 首先上一个最简单的例程,
Nucelo_091_ledtoggle.zip
(4.97 MB, 下载次数: 1031)
|
微信公众号
手机版
. c+ K4 v7 n* ^% l" Z' M
关于例程中的ticker 其实就是定时器,大家可以看下面的详细说明:' r4 x9 j3 U+ T& p7 W
mbed 时钟系统, u( u9 Q1 F9 [* N
微处理器的大量应用都和时间相关,如我们前面代码中多次出现的wait函数就是最常用的时间等待函数,显然,精确的时间等待必须建立在精确的计时技术上,这就需要用到计数器系统。
计数器的工作原理非常简单,就是每当它接收到一个脉冲时,它的计数值加一,一旦它的计数值达到用户设定的阈值,计数器就会产生一个中断信号让系统处理并重新从0开始计数。根据计数器可设定阈值的大小,我们可以把计数器分成8位计数器,16位计数器等,8位计数器可设定的最大阈值为2^8-1即255,16位则为65535。如果我们给定的脉冲信号频率为1M,而给定的计数器阈值为0,那么计数器就会每1us产生1个中断信号,这就为系统计时产生了依据。对于xbed LPC1768来说,它有四个通用计时器,它们可以用来计时、PWM输出等。
除了wait相关的等待函数以外,mbed还提供了三个对象用来完成和时间相关的功能,分别是Timeout,用来在给定的时间执行特定函数;Ticker,用来定时执行特定函数;Timer,用来给系统计时,它们可用的方法描述如下:
类名
方法
用途6 o' J. _& N/ a9 C& X d q$ Z
' n: L; Q/ G6 A+ j" b& U
Timer
3 b; l9 a' g/ o) e* l
Timer();% A0 W/ a3 e2 O: c* p
' A0 `! V- X" c) F0 X
构造函数,实例化Timer对象
% Y) G) M- I% h' f ]
void start();
开始计时
/ l. v% B" @4 u7 i0 y" m
void stop();
5 I! J9 c' E* U3 `
停止计时! m8 F i2 \% T$ |# ~8 j+ X
0 l. q |3 h% s' H/ Z- }
void reset();
, R) ]5 `( h# P' Y( g: G' G8 b
重新计时,即把时间计数恢复从0,如果原来处于start状态,那么计时继续% f- _$ g) K: _4 T
float read();
读取计时开始后过去的时间,单位是秒
R% o+ G! V) f& u9 |
int read_ms();" ^. n+ \0 e r7 w
读取计时开始后过去的时间,单位是毫秒, \& @; b7 k# G) W, {
+ y7 s; q* s+ ]
int read_us();1 D( j8 P* [# j0 w) m
8 m; M4 V" v! v$ h
读取计时开始后过去的时间,单位是微秒
operator float();
8 e+ h# g9 U$ Z( H0 z9 `! [4 @
操作符重载,相当于read
Ticker
Ticker();. W+ o# J* P1 i
构造函数,实例化Ticker对象
9 A! o' J# u' t& v$ d9 R
void attach(void (*fptr)(void), float t)
/ p0 C, a8 f+ D8 J+ A
设定每t秒需要执行的函数* l$ L& `' f8 |/ w0 H" J
void attach_us(void (*fptr)(void), unsigned int t)
设定每t微秒需要执行的函数. ]4 Q; ? E7 h5 F6 j3 x
void detach();3 Q! E3 q, F: r, R
! G0 z/ x7 X7 m- q. j0 f
取消本对象需要定时执行的函数0 N; u6 y: b$ V. i
0 j: ?# _7 i; U6 P
Timeout) L2 m, z# J1 r9 R
Timeout();
构造函数,实例化Timeout对象5 |& i1 c. P/ ~' k
. W/ N0 o# W3 u- Y2 s" N
void attach(void (*fptr)(void), float t)
) U! P1 s) H- Y
设定t秒后需要执行的函数$ z! r( t7 M, o& O A* u% D. r
void attach_us(void (*fptr)(void), unsigned int t); Y) @7 a& D" H+ o
设定t微秒后需要执行的函数" E6 m& S4 }6 P9 J6 Z4 W5 H
$ t; s4 c+ E! l; U1 }
void detach();- k" k& G1 V9 S
. }! [3 y6 c7 ?* W2 U7 @* k& |. t- P
取消本对象需要执行的函数
mbed Timer的应用7 m f/ l5 `9 e4 w( P- L7 G
mbed的Timer对象主要用来计算用户关心的时间间隔,下面是一个简单的示例,可以计算用户按下按钮的时间,主要代码如下:3 A# w6 _% j" p/ B" ?
5 Z% q: G* w" j! i3 Q
Serial pc(USBTX,USBRX);* g9 K* c8 \2 c9 ^7 n5 T: L
InterruptIn btn(P2_8);% A& L9 _2 u. G. w
Timer mytimer;& A, U% M' a8 |) O6 A, G
+ Z, [5 a# c0 O, V+ i ]9 Y
int falltime;+ E" d9 n! c: Y$ ]
int risetime;1 s2 W5 z- k& }
7 [& |/ i4 w0 r% o# e
void fallfunc()
{
7 n5 a' L) l+ F. M2 M/ F
falltime=mytimer.read_us();9 i1 a0 s4 N9 }- c. S5 a' ]3 B
}1 ]: K* H3 w4 _" c; I' P
void risefunc()4 j6 B$ S0 O5 \3 r' j
# s, q5 h/ {* p/ Y, O1 K
{8 M1 O o; z8 ^% r4 i1 S0 i
, w" p& ^8 _4 ?. q/ F
risetime=mytimer.read_us();* b! d! {+ J8 x s
3 Q- }( }* [& I, v
pc.printf("You press button for %d us \n",risetime-falltime);- l( E5 D" V: I0 l( e
}
int main() {* U) `& r4 A# V# ~9 p0 C Y8 L
mytimer.start();+ r9 M2 Q! L) n7 g" i! k) T
btn.fall(&fallfunc);$ w" c5 f$ `" x
4 I# r4 {# s& R7 [, T- p+ U$ j( ^ t
btn.rise(&risefunc);
while (1);
}
程序运行的结果如下,当然,我们需要理解,任何中断的处理都有一定的延迟时间,所以此结果还是会有一定的误差,但绝对在us级别。( o3 S$ a0 G2 ^( R, |
% `4 \ r% s1 [/ L3 C8 ~( T
You press button for 330410 us
You press button for 137603 us3 U' Y' J) `4 N$ }
8 v$ c1 Q: n# R8 Y" T) _: a5 ?
You press button for 122679 us, I# R9 G1 b% _
4 ^% M% A1 S1 r) S8 q
You press button for 140683 us
有时候我们需要利用多个Timer来计算不同的时间,这只需要定义多个Timer对象即可:
N* @: t' f& x z3 W% A3 P3 J$ _
Timer timer_led;. b3 }5 ]) ]% k t/ i! Q. X
& o5 E% u" }+ F# s6 p# p
Timer timer_serial;5 d' a5 Z# @4 n" b: V5 U
, M- J8 }) Q4 x) K
DigitalOut led1(LED1);0 e$ }8 _& g+ L$ H7 T6 j4 Y
Serial pc(USBTX,USBRX);
void task_led(void)% D, |* I6 l+ B1 B) D& o3 J$ d" F
{5 E) E `5 Y* ^( P/ _# N
led1=!led1;) b. I! \9 T7 p e+ A
. Y5 y) Z" s" s: _8 R; U
}+ V/ P' P- n0 |. q4 }6 L
void task_serial(void)
{& @0 s" u* a$ H3 C# `
$ ^8 G9 O% \, |0 `5 }
pc.printf("Timer passed %d ms \n",timer_serial.read_ms());
6 L9 O4 C% |& A/ a ~* J8 H
}, U0 ~+ {6 Q- j# g' p
# y" F2 o# H) _8 f& ^6 S+ n E1 m
int main()7 H |! |4 O0 k/ d
{
timer_led.start();
timer_serial.start();
9 k$ q$ E8 ]7 g3 N3 Y
while (1)
{ z4 m5 @5 P5 x0 X6 q1 O
. p5 c6 }$ c, P# p8 M* [7 k
if (timer_led.read()>0.5): g/ e, _% b6 D! c t* S K
$ I& `% ], N! w: _! e" O% e
{
/ L, _! }' L! l W3 r4 f7 |+ w' {) l
task_led();
( v; W* p J; V/ m7 g. c1 g1 W
timer_led.reset();
}
0 P% T0 }" {6 a2 {# }8 `
if (timer_serial.read()>1)1 W- I }$ ], ~: }
: O5 D: _& ^7 q6 L
{ //test Timer value7 M6 H9 Y9 C g/ A+ U4 S" `% M
, H# [- }3 J$ e0 K
task_serial();6 D3 C1 n/ o4 N! I& P$ l+ m0 ~; R
6 O5 n! f& F5 [" T2 V
timer_serial.reset();; J" F- \/ W/ ~% M
/ \6 f' b3 R1 ^% x$ z/ r( B
}4 f( s1 U; Y, x: L
! C; k; A( G4 Q& I4 S' g) n
}
5 z+ L$ M2 ` ~
9 p: }: e3 E* R, C% Q
}3 ]2 I2 j0 m* F. ~
7 T( ~8 |5 T6 y8 o/ v' ?/ [4 x" `
mbed Timeout的应用
4 H4 x, T, A& S9 i
mbed的Timeout对象主要用来在给定的时间后执行给定的函数,如下面的测试代码,运行后你会发现xbed LPC1768的四个led分别点亮,由于timeout只会被执行一次,所以点亮后会保持不变:
' {3 ^6 k! U0 c) z$ I2 i
DigitalOut led1(LED1);
DigitalOut led2(LED2);+ P+ D9 S9 P+ z5 d7 }3 T! R
DigitalOut led3(LED3);, @5 h( D3 c4 T t& V9 M. C$ K
DigitalOut led4(LED4);0 g9 x+ F# @ _) u/ e% |: Q& U
, ~2 Z9 w: ~* c* |
Timeout timer_led1;
Timeout timer_led2;: X. x! s( k3 G- N( h2 O# N
Timeout timer_led3;
Timeout timer_led4;
! J8 U: f; ~" Y* \' k. g0 Q3 m" }% U4 J
void led1flip()
3 v6 ~+ W& K$ q) X4 v
{
led1=!led1;$ l1 S" s: n, q; B
~7 C$ j# {1 K0 i
}! b' i/ e n R h; I7 y
void led2flip()
{
5 ^7 M- [$ p6 K+ D7 v. z, F
led2=!led2;0 H) w9 D- B' J$ \3 g
}% h7 J6 n- u) _3 f
void led3flip()
{
2 }4 C* _4 V5 V& _0 f. c- g1 }
led3=!led3;
' f9 n. c& ]3 a m1 H6 g: }
}0 H' Q; i+ o9 T4 R
void led4flip()8 |3 y4 L b% I) v2 G
{1 Y- ^% U$ m6 t2 @9 x5 C
led4=!led4;
}
- x5 c) b( O6 |: U3 z9 U+ B
int main() {2 U4 N9 D! r# W- p/ H+ E. R6 i% I* u& \7 A
timer_led1.attach(&led1flip,0.5);
0 R7 i3 G- \% l+ ]* @% t" m9 u
timer_led2.attach(&led2flip,0.5*2);
timer_led3.attach(&led3flip,0.5*4);
timer_led4.attach(&led4flip,0.5*8);( q+ P% S0 f x. U
: S, }; I: t4 }( v( B. F
while (1);/ l& a6 B" h3 A- z% ~( h% N
}
mbed Ticker的应用1 D! E3 }- @" S4 Y1 F# {
& W R4 o i$ N" ]. j
mbed的Ticker对象主要用来执行各类需要定期执行的函数,它和Timeout的唯一不同就是Timeout相关的函数只会被执行一次,而Ticker相关的则会被定期执行,如下面的测试代码,运行后你会发现xbed LPC1768的四个led将按照不同的频率变换:$ s4 j0 v4 ?! F4 {* r% h
1 ?) V# Z, }% \" I! [* g& G+ \2 B
DigitalOut led1(LED1);
DigitalOut led2(LED2); o, B7 Z7 v" ~7 M' B; O
DigitalOut led3(LED3);3 R* u" l9 c. G( @
! i2 G( y/ G' J# N a {2 \ P
DigitalOut led4(LED4);2 d4 K) Q! E1 W) t( ~
5 u: T$ N% ] \0 h
Ticker timer_led1;
Ticker timer_led2;
Ticker timer_led3;
3 F B: ^# j! [9 P" D. m/ Z
Ticker timer_led4;
void led1flip()
" H; C+ O1 V! }4 H, P0 {! Q) G
{ O! Y! k: D4 v4 ~, e! h
led1=!led1;( {( N2 F0 ]" W& K
}! o9 Z0 o6 s( Y" z8 y: p0 f
# |4 o( [* [ \2 N5 t/ Z
void led2flip()
( [, e ]6 ?+ ]6 z; X8 d
{
9 a: w7 U5 z6 [. W9 R: M
led2=!led2;
}, F8 @- T$ \" |$ j
void led3flip()- z6 W, U1 A& r- G X% A% A8 a
* G3 b) H& H% x- c6 r- V7 v; l0 h
{$ Z5 N% G5 T- c& O7 Z
led3=!led3;
}( b0 f) C1 X6 O" |) _4 {7 w
) ]# t; R. _. ]7 Z6 J9 B
void led4flip()! C* H0 K, z2 B8 f
Z# z' Z/ m5 O4 K" s
{
led4=!led4;
}
int main() {
timer_led1.attach(&led1flip,0.5);
timer_led2.attach(&led2flip,0.5*2);! q+ e* \3 ?8 o6 E
c }3 T1 S+ @+ g R5 g1 ] h i
timer_led3.attach(&led3flip,0.5*4);
timer_led4.attach(&led4flip,0.5*8);
while (1);
* x6 I" s A, Y- c/ \
}$ n8 x2 y3 y( M4 `8 c
}; x# L+ ]/ T, A- d- P- g; x9 A3 H
我们在使用Ticker对象的过程中还可以随时对Ticker设定的间隔进行更改,更改后的时间是即时生效的,如下面的代码,我们发现,用户每按一次按钮,led1的闪烁频率就会加快一倍。: h% {# V _* ^/ I
DigitalOut led1(LED1);) ~6 B1 D1 `) L+ q! ]. k
InterruptIn btn(P2_8);. N; J6 m: K1 h- I
. B! c6 S; X( d. U) ^8 t- n
Ticker timer_led1;: Y% O' p- O2 m4 \3 b
6 G' S; H, [0 c7 K( U T
float interval;& X( n4 Q% f% j m$ x" M2 e8 b
void led1flip()
6 Y4 x6 \7 o4 K( T# @7 M
{
led1=!led1;
}: Y( d y6 N% y: M4 B$ d$ o+ I& n
) Q5 a! r. U3 |( k1 S" Z8 r
void changefred()5 V7 E* [8 `$ @
{
interval=interval /2.0;5 l2 I1 J1 X' @" s5 ]! z; ^
timer_led1.attach(&led1flip,interval);# l4 }& ~# b. e) y
" h2 W& n, \% m) A' j* @8 `7 b
}9 v+ {1 }6 a! v/ x
int main() {! C, R/ t& s3 C" g; p) m8 L
interval=2;& B; i( n1 A6 P) i4 Y, p, {% w2 i* s) J
btn.fall(&changefred);
1 W Q4 e; d. U% p y. o
timer_led1.attach(&led1flip,interval);
while (1);* O$ A% L4 V i) h) D6 f
# p0 S+ G6 p% f! l- e" j5 g6 i
3 c0 O* f" }$ C# q" E
}
; S' i- s( ~3 C0 m7 ?
9 B8 f5 U6 i$ w
那还得再下载个其他的压缩的软件,,比较麻烦。。。% v+ {+ v, Y7 h) M: a
( O* E% [$ n* m0 n3 z
. D3 K0 G7 ~6 A
建议楼主以后压缩的时候压缩成常见的压缩格式,,方便下载者
' ~, } K/ t3 c& }( Y" z9 _
4 F1 M- g2 O' A5 U: H! H5 q
8 }8 b( B) m5 c7 n1 m/ k1 ~
有的 .下载最新的F0_1.5.0的标准库. 里面有072的例程. cube_fw_1.2.0库里面也有nucleo 072的例程.哈哈
帖子的地址有,下载最新的1.5.0的标准外设库.里面就有