你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

在STM32上跑Arduino的程序

[复制链接]
STMCU小助手 发布时间:2022-8-27 19:46
可能不少接触过STM32 和Arduino的小伙伴看到标题觉得很神奇,STM32上怎么能跑Arduino 的程序呢?,我第一次Arduino的2000人交流群里发这个项目时候,大家也觉得很神奇。
# i8 f" |0 G" v+ m
6 W/ g5 ?2 F9 F可能传统学习路线 ( 51 -> STM32 -> 各种Arm核心MCU )  的单片机工程师并不了解什么是Arduino,Arduino是一个以avr单片机作为硬件(现在不光支持avr了,还有STM32、ESP8266等等),拥有数以千计的开源项目的电子设计平台。比如你玩pid ,你不懂pid 可以直接Arduino IDE的库管理中下载别人封装好的PID库,比如你想玩个MQTT远程控制,Json解析/正则表达式,NTP服务 ... 不需关心MQTT的底层原理,Json怎么解析。虽然传统单片机上也可以移植cJSON库进行解析,但是ArduinoJSON可以使用更优雅的方式解析json。
, O( P& N/ P# K- F
5 ?/ P% Y) r" I9 H4 UcJSON解析( f7 ?( ?$ X; V. L4 a4 ?" }7 U6 f5 Y
! |" ?) ~% q) @, e* V
  1. #include <stdio.h>
    2 i$ e( s6 O# L& i7 [
  2. #include "cJSON.h"! ~/ j/ {* Q4 Z9 |& X& A

  3. ! o% ~6 _5 [7 H* d# `
  4. int main(void)
    8 Y+ U3 Y4 E2 q1 E- V9 U  f
  5. {8 [7 f8 ~8 E% I# @, X5 c
  6.     cJSON* cjson_test = NULL;( v2 b3 U9 Q) G. K8 O
  7.     cJSON* cjson_address = NULL;
    . U5 {) X+ @! c3 q0 Y; t
  8.     cJSON* cjson_skill = NULL;( f+ @' k% K! B5 _# ~. S5 X
  9.     char* str = NULL;+ k: s6 W5 ~: L* {

  10. 6 C+ o% n7 X" W; A1 q8 X' a8 u
  11.     /* 创建一个JSON数据对象(链表头结点) */3 N3 }& M) P" @! C5 v9 t
  12.     cjson_test = cJSON_CreateObject();
    * r) b3 T$ r2 w9 ^$ T+ H" z. t

  13. " N3 O  G$ V* M: ]# a; z! X
  14.     /* 添加一条字符串类型的JSON数据(添加一个链表节点) */4 V) F2 z9 e4 {; V/ L9 X* [
  15.     cJSON_AddStringToObject(cjson_test, "name", "mculover666");
    & k& R2 u% E5 Y
  16. - a7 K; i/ U; g% E' Z& Q  R
  17.     /* 添加一条整数类型的JSON数据(添加一个链表节点) */
    : c  A5 }2 F( O# B* [* I
  18.     cJSON_AddNumberToObject(cjson_test, "age", 22);
    ! j" p7 i) {' j6 \

  19. : J; n) I2 Y# E: f! P
  20.     /* 添加一条浮点类型的JSON数据(添加一个链表节点) */
    ! |1 E  G3 o( U2 \
  21.     cJSON_AddNumberToObject(cjson_test, "weight", 55.5);
    9 t  v0 \2 ]4 o' Z% M' X

  22. * l3 ]& I0 x0 k! ~# X
  23.     /* 添加一个嵌套的JSON数据(添加一个链表节点) */# B3 |0 D( [8 v# a5 r
  24.     cjson_address = cJSON_CreateObject();
    , }' c  g. Q2 ~& R# t: Y  H/ {
  25.     cJSON_AddStringToObject(cjson_address, "country", "China");6 e& j/ @9 U- t' L- d: J
  26.     cJSON_AddNumberToObject(cjson_address, "zip-code", 111111);# ^+ f9 x; p5 e
  27.     cJSON_AddItemToObject(cjson_test, "address", cjson_address);
    . g4 ?' ~+ O. v
  28. % _5 N" ~+ V# d: P" S
  29.     /* 添加一个数组类型的JSON数据(添加一个链表节点) */
    5 t# ^8 ?1 ?- Z# ~) E3 v$ j2 l; Y
  30.     cjson_skill = cJSON_CreateArray();  {: \7 g! F0 y: Z
  31.     cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C" ));
    . @; \3 G+ `2 v- v$ V. X6 C$ r
  32.     cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Java" ));$ S8 k' i' p4 m: O
  33.     cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Python" ));+ M2 w- T* s$ `& j4 a5 @
  34.     cJSON_AddItemToObject(cjson_test, "skill", cjson_skill);3 w$ e$ P( W+ z

  35. " s0 M3 i& q# h0 L
  36.     /* 添加一个值为 False 的布尔类型的JSON数据(添加一个链表节点) */
    ! s& n/ D( H8 w) ^
  37.     cJSON_AddFalseToObject(cjson_test, "student");. R& J2 V+ {% J- r8 \4 Q
  38. . {, t" J7 q4 o) r% a& x
  39.     /* 打印JSON对象(整条链表)的所有数据 */
    $ J6 I; G4 M  ~# j! j
  40.     str = cJSON_Print(cjson_test);
    * d* k- m  u1 l1 Q
  41.     printf("%s\n", str);+ W4 _6 ?% L5 t3 b7 Q/ E: x
  42. 3 a- B1 m) Z0 l/ Y# y' T4 A# V
  43.     return 0;
      r  n4 ?4 z# I. T, g0 ]
  44. }
复制代码
6 y4 Y: Q; h* t3 b% p
ArduinoJSON
; g6 c" f4 B& \7 B9 Z# i& j$ d( J1 ]. ?: q) T* M+ |7 h6 U0 c: k
  1. DynamicJsonDocument doc(1024);3 t6 x% B5 O+ F( k3 R' I2 b8 }; |  }

  2. ! t2 |  Y: |* t7 G
  3. doc["sensor"] = "gps";! F& W  w* L+ n- q$ _  J
  4. doc["time"]   = 1351824120;
    ' Y1 x2 c+ V9 L6 T& Y+ \$ K
  5. doc["data"][0] = 48.756080;
      S% O# f" @" d2 a9 v
  6. doc["data"][1] = 2.302038;) H0 l/ i2 d  q* s  f
  7. . U  Q+ j1 W) Z, n- {* P
  8. serializeJson(doc, Serial);
    ! t1 y/ ]8 H) F
  9. // This prints:$ J6 k3 [. }# l7 ^1 ^' D
  10. // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
复制代码

" B" Y  }7 ]+ t6 s: q看到了有木有,得益于C++的特性、我们可以使用更优雅、高效、安全的方式解析JSON。
' M" p, |6 Y) g+ l- Q$ W
* q8 x% M3 @( E0 J' v4 Y6 mArduino平台有很多类似于ArduinoJSON这样优秀的开源库。如果能为我们所用就好了。
9 x( @7 d- w: ?! Y! a) r( m& y1 G7 {6 r
于是我将移植了Arduino 核心API到STM32上。这样Arduino能用的库STM32只要下载下来,并将源代码添加进工程,包含头文件目录就可以使用了。# O% q2 N0 z- y7 o) M8 E
) T/ k- \, b( F4 d7 X9 q" M) ?
为了更好的支持C++目前项目采用AC6编译器,不包含第三方库的话AC5也是可以 0 warning, 0 Errors编译的。不过不推荐使用AC5,因为第三方库基本上都大量使用了C++11 甚至是C++14的特性编写。只要AC6可以完美支持。  y! ~  |7 c+ ~3 d

1 \) T8 S1 b2 ?/ k+ x; \: F8 ]
6 B7 y3 Q( l, _6 @) o7 `系统框架说明
. e+ ^* X! A0 {+ R8 z# y
' r6 l: ]/ ?4 ?+ T% _" U M5ASP(99K}O(ZUN19K3G443.png
: }: b* |3 o0 C8 Z
  d  C+ N# k' G大家下载下来工程后,可以看到有很多文件夹。其中DOC是文档目录,里面存放了说明文档。大家可以看看。
, L7 c9 a5 V% F+ f, D# e7 v6 P9 B+ L. h' b
Drivers 是驱动包,这个是由MCU厂商提供的,比如我们用的是STM32F103,这里面存放的就是STM32F103的标准库源码,如果我们用的是F4、H7 这里面放的就是HAL库源码。我们用华大的HC32就用的是华大提供的驱动库源码。MDK文件夹里放的是MDK工程文件,以后还可能多个IAR文件夹,顾名思义是IAR的工程文件目录。USER里只有个main.cpp 是我们用户编写的代码。
, s+ o9 I$ o) {% a8 q
. u4 i/ z/ g0 D Y[E0J6J0HAQUJR%@MUHEK7R.png * ~  q$ d$ t8 `+ E/ G- q. l
, s1 Q7 w* e, _
/ {0 {1 e% A2 V, P6 G1 m- W/ v  T3 x
Frame文件夹下就是框架源码了。ArduinoAPI顾名思义是Arduino 的核心API(用法请参照Arduino 官网)。LLA_Drivers是底层抽象驱动层,顾名思义是对Drivers 驱动包的进一步抽象(封装),对其它MCU的移植也基本上就是移植这里面的文件。4 Y# [$ x* i8 O# u8 U

/ E# ^  B+ i8 `: A0 ^: Z' l4 q7 q; N, F% u+ b6 D* f6 j
如何添加第三方库:
5 H7 U( `% ?/ V
$ {- B5 `0 y- D( a FASIZE5JF%(E_BHYB0T{]LJ.png
2 t3 o" S& I0 c8 k# D- ?
/ C  M& o6 P+ y0 r& F( s  P添加一个新的分组,明明为库的名称。然后把库文件夹下的所有cpp和.c文件全部添加进来。
4 ]% R- }, A2 ~
* M6 X. H  G" H8 ? }ZA]DM_44WKWVXUNT_%M[[I.png & T3 Q. u! K& B5 k
" X0 O: d3 k5 e0 Z3 z! h0 d2 |
然后将库文件夹下的头文件路径包含进来。运行编译,然后解决一下编译错误(部分库因为用了寄存器级别的代码所以肯定编译不过的)。
2 l5 V* V; m5 _: p
- J- O+ X) F" f. ]默认工程里跑了个MQTT的demo,需要是STM32F103ZET6 + W5500 以太网芯片(连接在SPI2 //SCK-PB13 MISO-PB14 MOSI-PB15 上),所以Arduino API 的 SPI其实是STM32的SPI2,如果你需要修改为SPI1的话打开ArduinoAPI的SPI.cpp文件拉到最底下更改下注释就行了
' A; }' Y% U) H) s4 n' W2 \& G5 @; r) ~8 p2 J! [
  1. //SPIClass SPI(LLA_SPI0);//SCK-PA5 MISO-PA6 MOSI-PA7
      ?0 T  M# x0 g6 U; q% a
  2. //SPIClass SPI_2(LLA_SPI1);//SCK-PB13 MISO-PB14 MOSI-PB15
    # I  y9 e, Y0 l6 X

  3. 3 J2 E# A& Q& `; P
  4. SPIClass SPI(LLA_SPI1);//SCK-PB13 MISO-PB14 MOSI-PB15
复制代码

( P0 k6 i7 r0 t0 M8 L6 o这是我跑的MQTT例程,通常情况下第三方库都会有个examples文件夹,里面的demo程序直接复制粘贴进main.cpp 就可以运行。+ {& z2 c4 U5 P- k) M' [

* j, f* v2 ]. Z% U6 \ {CD[7S1EQ(9I($VJAX0B5`B.png 3 V" O5 z- ^% D$ ^% i! c

# N/ U$ s- f- M5 `/ g" N- I' P! I0 }. U
LLA层串口断言:  H' R' @! V# t  K

* E9 g. {" j' N8 Z% ]你填错了函数参数,会定位出错位置并且会有提示。( ?% |, f6 D. j9 L: s; v2 w
1{IOBTPL2(D%W]M3VWMEV)4.png # |1 W! \& o' Q$ ^+ R# y

  Z4 k6 Y7 [3 Y5 h7 N 作者:捉住一只皮皮虾# b: |! o0 n7 K+ K* `# C; {
( G4 K6 Y3 z2 ~  k7 f' \* L

+ ^9 N# e+ k0 q9 z$ U  T; [. P" @& W
赞 收藏 评论0 发布时间:2022-8-27 19:46

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版