% f/ E2 B& h2 ~. v
9 I( x! P5 I* }+ ^4 J
( @, c# E- P, S& y `
Arduino的板子虽然有国内的兼容板子,但最终价格也要在40+(意大利原产的就要100+了)。虽然也已经不贵了,但是如果一个方案里用的板子多了,整体成本也是在那里的。况且谁又不希望用最低的价格做最多的事呢?就在儿子4年级时,他们的信息课开始在学习Arduino的简单开发。当时学校发了2块Arduino Uno,这没有毛病。但又过了一个学期,换了一个供应商,发过来的是长这样的板子。
/ e* @6 c# W4 n' W/ |6 N7 T8 D8 h: @6 V, B" w5 S, A4 k* N: |
% q/ a4 @& M3 g; W* ZSTM32F030 Demo Board . M$ Y. s3 P+ P$ |) \- g' }1 c. P( i
. M2 g8 r2 U! b9 {" V! F5 v0 P那一下我就懵了,还有这种玩法?但是其实当时老师并没有让他们直接在上面编程的,而是老师已经写好代码,固定了输入和输出口,学生只要根据需要换输入和输出的模块就可以实现很多功能了。而我的确上网查了一下,STM32是可以基于Arduino来写代码的,但是因为老师的这种操作,所以我就没有机会接触到是怎么用Arduino来编写STM32的代码了。这事一放就放下几年。最近在搞那个乘车方案,要用到3个端,特别是用户手持端是要人手一个的。它需要做到体积小,成本低。这就让我重新想起STM32了。但是开始搞了一下,不得要领,最后还是放弃了。这两天折腾别的板子时,顺手拿起来,发现搞定了。那现在就记录一下吧。$ G1 w! H- \2 Q7 b
" K; K0 k& D- h9 F$ }" W' s一、在Arduino开发环境中增加STM32
$ Y5 x) r) Y O T! i+ m5 s# G! q1️⃣ 添加“附加开发板管理网址”
) k) r( ^6 Z2 V6 m找到“首选项”+ \ }% v0 O& v$ O1 H8 H: L% ]
. {, h( T o8 J/ R
) d0 Z1 Q0 A, W( Z4 }
( t% S3 |2 f7 t
修改“附加开发管理器网址”
! u `- S) r( }
I* O& R( L! \2 H: M
7 m$ ?7 v; x n8 o: Y8 M4 ~" X& z
3 f3 d/ X2 M6 m1 }链接是这个,直接拷贝进去就行。这个是比较新的,一些兄弟分享的网址因为是过去分享的,已经无效的,所以请使用我分享的这个。有助于避坑。(如果你修改完这个后发现Arduino启动不了了,请看本文最后的解决方法。)' _3 D' J1 i' ^+ J& j! X% t
+ U- M; G4 D. S; u5 U如果你好奇,可以用浏览器打开它,它是长下面这个样的。具体内容就是一些板子的信息和对应的工具及所有相关代码和包的下载地址等。9 U1 a; C) B2 l) z2 r
- @) B. [/ p' }( x
+ T c5 I5 w- ~1 c1 u
# x- S0 p% q, T; t6 ~/ y& Y
然后点击界面上的“好”。就完成了这一步。# j; b; z/ G% Y
" h* M) u* {' q$ E8 v- B
2️⃣ 增加STM32开发板
% P, ?, I( Y% f' r; z/ _在“工具”=>"开发板:XXX"里找到“开发板管理器”2 H( J' o7 |2 h/ V. o0 X
6 f* I. ^, ~! M( S! j
5 }6 o' u/ V" D" m4 \9 m2 w3 } @) j+ C: k9 d2 y9 g
然后选择“贡献”,找到STM32 MCU based boards,将它安装就行了。我这里因为已经安装了,所以“安装”按钮是灰的。安装过程需要点时间, 国内连Github有点慢,如果你有加速的方式的话这时可以拿出来用了。
6 I) i7 V# T8 h' ]+ @: N5 z; W, I# Y g9 ?0 C
+ Z' a8 H8 `$ e- Y& n, A
/ g* P) ]- D1 R; I
3️⃣ 选择STM32开发板+ V6 t6 E R U" H
安装完后,你就可以在这里选择你的开发板了。我的是STM32F0系列,所以选择了Generic STM32F0 Series。
! l' M! L7 ]% k9 D4 w1 P+ L7 ]' x' E
8 |. H1 U% }# J% C2 c: v6 l& Q( A. Y
. Z+ _8 W" G9 j记得选择STM32CubeProgrammer(Serial),这是我们通过UART(也就是TX, RX方式连接)的上传方式。7 ~' m5 X {' J$ F& F1 v
+ M2 [- N: s2 O) A# H5 O H
/ w/ J/ S I! C& b3 E$ Y( Q2 ?/ Z8 t8 U. F1 t6 u P( a
4️⃣ 写代码测试8 }/ r; A' {5 v3 q% }" c
到这里我们就可以写代码试一试了。
7 ^; f3 h- N6 { H0 Z( S. K6 t* v2 Y, ~/ }4 S
我从Arduino的示例中找到了"Blink"这个示例。% x- H) a3 I! L- R+ R
y3 A. i8 A2 ~
3 j: m7 Y. B9 v m0 L# ?& m: e
1 q! l$ M" i0 G* H7 k- Y( J得到如下代码:
( M1 ]: o5 R4 u0 i3 X# I5 x2 U- void setup() {: j$ {2 z4 Z f ?
- // initialize digital pin LED_BUILTIN as an output.8 ]% A0 ~) L5 U
- pinMode(LED_BUILTIN, OUTPUT);2 C8 ]; H4 Q: _- J- ]# v" x
- }8 r) T; ?; ~6 m+ U4 \- n; r
-
; r J% x7 j; C: m- i& ~ - // the loop function runs over and over again forever& M5 \/ h) E* h! S- L
- void loop() {
( Q( o. t# e0 W1 e6 k5 U - digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)! _0 q) F/ z1 |
- delay(1000); // wait for a second
, Z6 A1 K/ W/ L4 K# J - digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW Q. d8 w- z B4 u: ?5 ?
- delay(1000); // wait for a second4 V3 c3 a% e/ D' b7 ?0 T" k* |& k
- }
复制代码
( V: ~4 F1 t, B
/ m! `0 T! g: Y5 D7 \ 如果你细心看,这里的“LED_BUILTIN”是蓝色的。但是STM32是不支持这个宏定义的,那我要怎么操作STM32的各个PIN呢?我找了很多文章,发现原来其实使用起来很简单,看下图,你要用到哪个PIN,直接用哪个PIN的名字就行了。比如我用的是PA4,代码里面直接用PA4就行了。另外,如果你细心看,你会发现下图中用绿色圈出来的LED灯其实就是有2根深色的线连着PA4的。所以我们只要设置PA4的电平,就能让这个LED灯亮起来。
# C* ?- a, |+ j- H- o0 S. O2 z! f$ H/ N) s
* F# s" l9 ^2 a) B i3 J! Y6 U4 |
1 ^: B# b5 r3 z# z" M代码我改成了这样:: [0 }0 p2 |7 u
- void setup() {
, ]( \, X4 \( O! r3 q* m- J2 Q - // initialize digital pin LED_BUILTIN as an output.( P& O$ R- g9 F1 E7 Z/ d
- pinMode(PA4, OUTPUT);
Q3 l% R( |8 K6 R9 W - }# z. B4 k, b/ c4 G! G
- 4 \/ W+ p P. m% m
- // the loop function runs over and over again forever: b2 H- {& P" y2 N/ ~
- void loop() {
7 Z+ s) P2 T' n8 p' Q - digitalWrite(PA4, HIGH); // turn the LED on (HIGH is the voltage level)6 G# E) I, x0 E
- delay(1000); // wait for a second
4 q* q! F: ]5 q6 E - digitalWrite(PA4, LOW); // turn the LED off by making the voltage LOW
5 Y7 _& b; z. H; l6 S! A2 E5 n - delay(1000); // wait for a second" q# ?( F9 R0 p; r; c0 V+ d0 o
- }
复制代码 * k6 c+ Y7 @- C6 o: M" h8 A
$ c0 r& p( m3 Y* g. f {& Y* 注意,观察,当你选择了STM32的板子后,这个代码里的“PA4”会变成蓝色。而如果你选回Arduino Uno,那PA4就变回黑色。也就是说,如果看到是蓝色的,那表示你没有写错了。
; F3 I4 N8 { t# v; z3 J
+ j" z' F4 _8 X# i" Q/ j6 U2 N x( Z( ]5️⃣ 下载& d" X, {9 O6 b, U0 p
1. 关于连线
' P3 @' F. g1 @! m! ?! j$ h* {接下来就是要下载了。还记得我一开篇说我之前曾经不得要领吗?问题就在这里。我根据使用Arduino的经验,想当然地连上了MicroUSB线,但发现电脑找不到我的STM32F030。我一直以为这块板子时间长了,坏掉了。然后另一篇文章中,我提到新买的那块Arduino Nano不能用(其实是选错芯片类型了),我以为是USB控制器坏了,所以我用USB转TTL(下图这个东西)来连它,发现原来这样也是可以正常使用的。所以啦,我在想,那这个STM32应该是USB控制器坏了,我用USB转TTL不就好了?
+ [- }8 M+ j2 ~+ n3 M. D
$ R) G0 E" h" c5 _1 D- M
3 p" j7 ?* T3 c* z2 S3 k2 v6 B
+ R7 q9 g" ~1 y! e6 _/ N
连上后,发现可以正常下载代码了。你猜怎么着?我又查了一下STM32F030 Demo Board的文档。发现人家就写着"Power only"。为我的无知感到汗颜。
! m4 Q2 x2 ^8 G5 r8 M$ |# u0 L/ R# I! V/ G
4 p2 A/ k+ g# Z& L/ J# m& j: ^* q
连线方式如下,因为没有找到Fritzing的对应STM32的部件,所以直接拍照。(有STM32的Fritzing部件的同学请分享给我一下。先谢过!)
3 C$ Z6 j' r3 } `8 f" Y1 O. M) \
; ?) ?" b. Y8 _: V" H
( Z2 ]* y( s& e2 B! Y
1 w' z- h' \6 L& t6 Q+ e
具体连法如下。其实习惯了的话都知道,看到Tx和Rx,只要反着对连就能跟模块通信了。我一个做软件的觉得这种方式很无敌啊。
" a5 o1 I* ^1 p$ \" B7 H1 {" b9 G
4 a! r3 e( V3 z- r& }2 E
* J# M6 \7 r2 c" X& _9 h- `
/ k3 M1 G" ^- l; o- e2. 下载) h6 ^0 d# F }' A# ^/ v/ ~& ^
这时准备要点击Arduino的下载,但在此之前,记得让板子启动到bootloader模式。就是将板子上的跳线跳到3v3的位置然后接通电源(跳完按“重置按钮”效果也一样)。7 I8 Q5 {' c2 k- N, C
u% E+ e2 {. M$ p# q4 i8 Z, K1 q
' ]* P5 a* Y! b0 f* }( Z3 q6 D; w5 m* O! W8 J
这时就可以点“下载”了。
9 T5 C. e8 X3 z# B5 T+ H' O1 x* Q( l
3 V/ ]! y- l' d* N X' a- o0 ~) w: w; p7 S9 r
下载完成后,再将跳线跳回GND去,再按重置按钮。板子就会启动到工作状态,代码运行了。
) p) U+ N7 R, L0 Q) D/ y
* t( c$ R5 p; y( a- g9 y+ k& m
7 Q( [% V: F* Z5 W' N! ?
/ T& ~; I5 {/ @: H: N" X二、参考资料:- M! Q& n' R/ b; O9 v! p( f. n
$ s0 a. N4 s5 C8 p b# U6 {三、附录
9 i9 ?9 M* {; c. X' ]你在修改“附加开发管理器网址”时,不知道有没有遇到问题。我因为用了旧的地址,最后导致Arduino的IDE打不开了。我通过cmd.exe,然后手工运动Arduino里的Arduino_debug.exe看到了报错信息,发现报这个错。$ m7 u" @ a$ F& M/ K, k
: @0 y9 {3 _8 [ i% A7 a( {( g
. P. v* E6 e* ~5 A- java.io.FileNotFoundException: C:\Users\Eric.Li\AppData\Local\Arduino15 (拒绝访问。)9 D$ C' w7 I6 i0 d3 o
- at java.io.FileInputStream.open0(Native Method)) C$ q: {! J/ Z: o3 s
- at java.io.FileInputStream.open(FileInputStream.java:195)
* y+ ?; c$ |) ?' a3 V9 Z& B H& {0 y - at java.io.FileInputStream.<init>(FileInputStream.java:138)
2 I8 R( w( P/ @7 x+ F; B - at cc.arduino.contributions.packages.ContributionsIndexer.parseIndex(ContributionsIndexer.java:234). Q8 T% ?* U' b% j! f, u) z
- at cc.arduino.contributions.packages.ContributionsIndexer.mergeContributions(ContributionsIndexer.java:179)7 q* R. G( D5 N1 _5 M
- at cc.arduino.contributions.packages.ContributionsIndexer.parseIndex(ContributionsIndexer.java:116)1 [* k( C$ T- s- r
- at processing.app.BaseNoGui.initPackages(BaseNoGui.java:483)" k* L% g* K2 T) l; T# U% z
- at processing.app.Base.<init>(Base.java:272)
$ B4 f+ D1 G) M- X" E- o2 t - at processing.app.Base.main(Base.java:150)
复制代码
$ w! i1 H) ? l1 `2 P) L; _
3 K4 `1 g2 G* V然后在网上查了,然后做了如下操作。' b; D% v6 j1 C: f( j
有兄弟将这个"Arduino15“目录给删除掉了就好了。我试了将这个目录修改名字(Arduino15改为Arduino15X),有效的,Arduino的IDE能打开了。
/ {% U9 ~! _; j7 U7 x; P! H4 J3 G9 L但是我觉得这种做法不科学,所以我进入目录看,发现Arduino的IDE重新创建了Arduino15这个目录,而里面只有一个"preferences.txt"文件。
' i6 L% V/ m |1 H/ V5 m3 \我用这个文件覆盖我原来那个目录(Arduino15X),又将新目录(Arduino15)删除,再将原来那个目录(Arduino15X)修改名字变回Arduino15,一切工作正常。
% h# _! K8 Q' D' E0 Z5 g那其实问题就很明确了,就是”preferences.txt“文件里有错。
8 h+ k% q( J0 J6 w1 p' ~0 q! ~7 `修复操作就是将最新加的内容,也就是开发板管理器地址去掉就好了。
7 m b% v# \, O$ i
/ m- H* ^2 X% m0 a- g/ R5 T- board=uno$ H, U2 p4 v T5 y
- + K, ^( J6 G3 q1 k; G; K
- /***********干掉下面这行就可以了***********/0 x* \/ [; ]! d3 K7 ]2 \9 L
- 4 I! o* ]; a8 U- @4 v7 C# B
- boardsmanager.additional.urls=https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json
: }4 V9 E+ x$ e u7 d7 w - 0 k/ i8 \7 M5 v; |
- /****************************************/: w, S/ @/ Y, L6 v7 Q- X; [. Z# B
- 7 {" z0 A2 P" T1 p" B, m
- build.verbose=false
. k$ J, E; _) L, f4 j - build.warn_data_percentage=75
6 L6 O3 C3 w3 Z7 Q" W9 T - cache.enable=true1 H. a R2 U2 I" |0 e
- compiler.cache_core=true
" t) y3 I$ {. |- X$ X7 w( W - compiler.warning_level=none4 B1 h; p) s; \* R4 U( N$ A
- console=true
2 H9 K- @7 Z' H- { - console.auto_clear=true! R, M [2 P* S v G7 D! `
- console.error.file=stderr.txt2 s" `/ }' S [2 ^
- console.length=500
% I. y& r; I! {& K1 h/ D, g - console.lines=4
6 N' @$ `; ]& S. x m i - console.output.file=stdout.txt; T. ?) I) r! \( b. x4 B
- editor.antialias=true. q0 h& }0 N. v6 K- B9 W
- editor.auto_close_braces=true
" @5 J/ L& q) t9 a - editor.caret.blink=true
2 R4 K7 q; u" W* S/ [ - editor.code_folding=true
; L2 T8 a6 y; u - editor.divider.size=2+ c3 P$ ?9 b% Q9 {; |' Q5 h
- editor.external=false: N8 Z3 l' j$ Z$ d
- editor.font=Monospaced,plain,127 |: E& d+ g7 D- e
- editor.indent=true' X f7 r+ D4 Z7 s1 p/ D$ N
- editor.invalid=false
/ K- U* g Q- h - editor.keys.alternative_cut_copy_paste=true
( h& {1 T `8 F - editor.keys.home_and_end_beginning_end_of_doc=false7 B: p* B) E# }9 V# y
- editor.keys.shift_backspace_is_delete=true( [/ {& z4 v6 _$ B' C
- editor.languages.current=
* m$ d h1 h* Z$ {* }' T - editor.linenumbers=true3 F; F2 @+ m' ?1 P
- editor.save_on_verify=true: X5 e' J; F$ o2 ^4 d) s5 y, K) K
- editor.tabs.expand=true! J$ w" \, E4 h7 i# B& ~) ?
- editor.tabs.size=25 ? e0 g% a& [$ m$ P' G2 z
- editor.update_extension=true
6 Z+ `5 \2 m8 A0 I% R - editor.window.height.default=600
' A0 j( {; G Z6 \ - editor.window.height.min=290
. b A* y2 n/ ` - editor.window.width.default=500
; x) |: n0 o0 K- w - editor.window.width.min=400
5 K" O- s0 C6 w9 m( }- g# k+ }8 c - export.applet.separate_jar_files=false) e4 p) y- t- t2 M9 z0 O5 C& |
- export.application.fullscreen=false* c. l6 W$ Z M' s" u
- export.application.platform=true" m B/ Y8 @8 ^
- export.application.stop=true( w: X- I+ }$ {& E% A& F
- export.delete_target_folder=true4 d$ i8 v0 C. S: u1 c( K! @
- gui.scale=auto
' Z$ T; l' _+ X+ r7 T, ^ - ide.accessible=true
- |( i' _0 t5 Y" G - last.folder=C:\Users\Eric.Li\Desktop\Temp\stm32test\stm32test.ino
' k2 j" s, f- F& q' t3 X - last.ide.1.8.19.daterun=1649298830
6 r' t+ c& ]' C - last.ide.1.8.19.hardwarepath=C:\Program Files (x86)\Arduino\hardware
3 W* o) L+ L3 V6 \. o+ a - last.screen.height=1080
M4 T) M S9 P1 C - last.screen.width=1920
, c, n# H2 W( @5 D, z7 ] - last.sketch.count=2
$ I! c; {- j+ Z. z - last.sketch.default.location=760,290,500,600,414,0
7 p0 y! |& K+ @ - last.sketch.default.path=C:\Users\Eric.Li\Desktop\Temp\stm32test\stm32test.ino- K" Y7 [8 y' ?5 _* n0 o& O7 l+ Y; L
- last.sketch0.location=650,240,500,600,-1,05 e6 h) p8 r3 O) [* k- z% Y. `! V* s
- last.sketch0.path=C:\Program Files (x86)\Arduino\examples\01.Basics\Blink\Blink.ino3 C0 P7 ^/ i/ j7 B
- last.sketch1.location=-8,-8,1936,1056,870,6' R- ^ t* v* b/ E+ E
- last.sketch1.path=C:\Users\Eric.Li\Desktop\Temp\stm32test\stm32test.ino. f' e8 r9 J7 b' a5 B7 S) y
- platform.auto_file_type_associations=true: p% L+ f Q P
- preferences.readonly=false. K2 @/ Z( E/ P# K
- preproc.color_datatype=true+ g# L5 a7 E3 Y: z0 ^0 U
- preproc.enhanced_casting=true) ]/ o9 v% F4 ]; X/ q% ]( N; |
- preproc.imports.list=java.applet.*,java.awt.Dimension,java.awt.Frame,java.awt.event.MouseEvent,java.awt.event.KeyEvent,java.awt.event.FocusEvent,java.awt.Image,java.io.*,java.net.*,java.text.*,java.util.*,java.util.zip.*,java.util.regex.*2 h! ]3 Q# i+ v' U
- preproc.output_parse_tree=false
1 m: a% f X% c4 H: C) D0 w- U$ ` - preproc.save_build_files=false
* n/ Y8 n+ h2 ?5 w# A+ ^& \# h# f9 w - preproc.substitute_floats=true# ^5 X2 {" K6 W1 L I* v, B6 w- n" i9 b
- preproc.substitute_unicode=true
: O0 S7 B% T7 i& I - preproc.web_colors=true
; y6 k; F4 v; N2 L7 \ - programmer=arduino:avrispmkii, X O; e! Y5 G! E
- proxy.manual.hostname=3 i5 c6 [0 f6 t: ?
- proxy.manual.password=
6 G8 V9 ^2 A3 X( Q0 p: P - proxy.manual.port=
+ n+ \8 B7 {8 | - proxy.manual.type=HTTP
9 \0 E1 k' c* p) ^& O - proxy.manual.username=* e4 t; i b# l5 Q$ \6 U1 [
- proxy.pac.url=
" v0 K. e5 v- X# _ - proxy.type=auto- z8 U/ J, j# J3 z5 A$ n2 D
- recent.sketches=C:\Program Files (x86)\Arduino\examples\01.Basics\Blink\Blink.ino,C:\Users\Eric.Li\Desktop\Temp\stm32test\stm32test.ino
: o: L% A& J2 A4 I! @& @1 E- ` - run.display=11 B* r! X6 Z( T- I" |% z1 ^" y
- run.options=
+ [4 P# O2 p1 |- S* _7 D - run.options.memory=false
2 s' y# {$ y% [* P: G - run.options.memory.initial=640 T* u' z& M4 E5 E( l
- run.options.memory.maximum=256" O; @$ h- f* t+ J( q5 o2 t
- run.present.bgcolor=#666666
( _- _: w$ a) W- k( V - run.present.exclusive=false$ o6 k/ Q2 h0 ^! o
- run.present.stop.color=#cccccc
8 f0 N( i1 C( E/ U; H0 m4 G - serial.databits=8
, X* L) y0 ]# D6 { - serial.debug_rate=9600
# A5 q: j' ?/ C$ S" l+ | - serial.line_ending=1
. V$ J5 }* r9 S3 P# i+ W& o - serial.parity=N s2 v2 F: q: H R
- serial.stopbits=1) O+ }6 H( z( M' K4 H
- sketchbook.path=C:\Users\Eric.Li\Documents\Arduino p1 N& m/ k& ~6 Z' u: b
- software=ARDUINO
8 C& P0 H0 W# z9 y, d( R - target_package=arduino
' e+ t8 l$ h6 Q - target_platform=avr
8 s. g- N) j2 ]( f5 a) P6 x - theme.file=; F5 E7 U8 \5 j) ^- o6 v
- update.check=true( Q# c3 ]5 d% Q2 h; i. z
- update.id=2142332045165484339, q8 e6 J8 [" j
- update.last=1649297850467
1 h( ~$ t( w$ h* p' P - upload.using=bootloader
( {, W( B- F9 |; f& M5 T+ c: y7 @ n' l - upload.verbose=false
( g" F% l9 Y' O, o7 x: e- C - upload.verify=true
复制代码 " ]/ G0 r$ }; A, n$ l* d: X
' t1 t8 k7 u: i7 ?————————————————
# A3 B- p G5 H3 Z' @$ I) ^版权声明:本文为CSDN博主「长风Eric(fengcan)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
6 t) A' h, f: X1 D }原文链接:https://blog.csdn.net/fengcan/article/details/124009060
, e: ?9 |' }+ b! B" ]. l- X; P
9 v! v& @4 m/ U6 F, h" k* k |