开源一夏 | 在 STM32L051 上使用 RT-Thread (二、无线温湿度传感器 之 CubeMX 配置)

前言
上篇文章我们仅仅是开了个头,使用 RT-Thread Studio 新建了一个基于 STM32L051 的 RT-Thread Nano 工程,本文我们就在在这个工程的基础上使用 STM32CubeMX 做 STM32 的基本配置。
本 RT-Thread 专栏记录的开发环境:
RT-Thread 记录(一、RT-Thread 版本、RT-Thread Studio 开发环境 及 配合 CubeMX 开发快速上手)
https://xie.infoq.cn/article/44be1057caace7a6a2c4c4b59
RT-Thread 记录(二、RT-Thread 内核启动流程 — 启动文件和源码分析)
https://xie.infoq.cn/article/44be1057caace7a6a2c4c4b59
RT-Thread 内核篇系列博文链接:
RT-Thread 记录(三、RT-Thread 线程操作函数及线程管理与 FreeRTOS 的比较)
https://xie.infoq.cn/article/1d2e8e030ae689d6b8ee44b05
RT-Thread 记录(四、RT-Thread 时钟节拍和软件定时器)
https://xie.infoq.cn/article/3198c9b741782036bfd6e54e9
RT-Thread 记录(五、RT-Thread 临界区保护
https://xie.infoq.cn/article/7a41020e03184950664df7391
RT-Thread 记录(六、IPC 机制之信号量、互斥量和事件集)
https://xie.infoq.cn/article/1f49bfd6c69377deb9eee838f
RT-Thread 记录(七、IPC 机制之邮箱、消息队列)
https://xie.infoq.cn/article/360b04e7bc6024917afecef1d
RT-Thread 记录(八、理解 RT-Thread 内存管理)
https://xie.infoq.cn/article/bd5d8f8a19fa11ea9feacf34d
RT-Thread 记录(九、RT-Thread 中断处理与阶段小结)
https://xie.infoq.cn/article/3da9530cfac06feece3523a0c
RT-Thread 应用篇系列博文连接:
在 STM32L051 上使用 RT-Thread (一、无线温湿度传感器 之 新建项目)
一、使用 STM32CubeMX 配置
STM32CubeMX 配合 RT-Thread Studio 使用的方法在我的博文:
RT-Thread 记录(一、RT-Thread 版本、RT-Thread Studio 开发环境 及 配合 CubeMX 开发快速上手)
https://xie.infoq.cn/article/44be1057caace7a6a2c4c4b5
的第三小节有说明:

配置我们需要根据原理图进行,本应用所用到的外设原理图如下(无线通讯模块没有放进来,使用的是串口 TXD3 和 RXD3,另外使用的外部 8Mhz):

1.1 基础步骤
点击 CubeMX Setting,然后选择芯片类型,点击 OK 即可打开 STM32CubeMX,如下图:

进入 CubeMX 后设置步骤就很基础了。不会可以参考这篇博文,正好是使用 STM32L051C8 写的:
STM32L051测试 (一、使用CubeMX生成工程文件 — ST系列芯片通用)
我们按照 时钟,调试接口,串口,GPIO,定时器,工程选项 依次配置,下面就简单列一下步骤:
时钟:
RCC 选项,外部高速时钟 选择使用外部晶振:

选择完时钟就可以在 Clock Configuration 中配置系统时钟,直接把系统时钟改成最大的 32Mhz,点击确定,系统会自动修改好时钟树:

调试接口:
SYS 选项,在 Debug Serial Wire 前打勾,表示使用 SWD 接口:

串口:
串口一已经用作了打印串口,在工程 drivers 文件夹里的drv_usart.c
文件中已经使用INIT_BOARD_EXPORT(rt_hw_usart_init);
初始化了,所以我们这里不需要使能。
我们直接设置一下我们需要和无线通讯模块 通信的 串口,原理图上是串口 3,在 L051 上是LPUART1
(STM32F103C8 和 STM32L051C8 是 pin to pin 的):

GPIO:
普通 GPIO 设置,2 个按键输入,一个 LED 输出,2 个 IO 口做软件 I2C:

定时器:
我们设置两个硬件定时器,一个 1S,一个 1ms,我们可以根据自己使用不使用选择初始化。
设置为 1S 的定时器 TIM2:

设置为 1ms 的定时器 TIM21:

工程选项:
最后在 Project Manager 中做最后的配置,生成工程:


完成上述步骤,点击 CubeMX 右上角 GENERATE CODE 生成工程。根据我以前的博文说明,生成好了以后,不要打开,直接关闭 CubeMX 即可,然后回到 RT-Thread Studio,出现下面的弹框点击确定即可。

完成以后多了 cubemx 文件夹,然后编译一下,正常结果如下(其实我自己走流程的时候,出过一次问题,后面小节会说明):

1.2 修改配置
还是根据《RT-Thread 记录(一、RT-Thread 版本、RT-Thread Studio 开发环境 及 配合 CubeMX 开发快速上手)》中的记录,修改一下SConscript
文件,使得包含我们 CubeMX 生成的 GPIO 、串口和定时器设置:

修改完成以后不要忘了同步 scons 配置!!再重新构建!
这里要特别说明一下stm32f1xx_it.c
这个文件:
在《RT-Thread 记录(一、RT-Thread 版本、RT-Thread Studio 开发环境 及 配合 CubeMX 开发快速上手)》中我建议不需要添加,因为里面有些中断响应函数, RT-Thread 内核有自己的实现方式。但是这里我还是添加了,但是要把stm32f1xx_it.c
文件中 一些中断响应函数的给注销了,因为在 RT-Thread 内核有其他地方有实现!
我的做法是,除了下图自己后面程序设计需要使用到的,其他的都给删除了,注意这里方便说明用的是函数声明部分,需要在stm32f1xx_it.c
文件中函数实现部分删除:

配置完成以后再次进行编译,结果如下:

完成上面配置后我们就可以开始设计我们的程序了。
1.3 踩坑记录
按照上面 1.1 小节的基础步骤设置 ,完成以后,在 CubeMX 最后一步生成工程的时候居然卡死了,我只能强制退出 CubeMX 任务,重新点击 CubMX Settings 打开 CubeMX 进行配置。
完成以后发现左边 CubeMX 里面的文件列表不是和当时我文章记录的一样:

居然没有SConscript
,编译报错了,即便我重新复制进去,也没有用……
一般来说,如果编译除了问题,我们应该从编译结果去查找问题,然后分析解决,但是对于这种软件联动的自动化配置,我还是建议重新操作尝试解决。所以我把工程全部删除,然后重新来一遍看看。
因为考虑到 CubeMX 卡死过一次,项目出问题了,两个软件没有成功的关联,所以我是重新操作了一次正常了。
而且有一个系列操作,在我们点击 RT-Thread Studio 打开 CubeMX 以后,最好是等待 RT-Thread Studio 的一个弹框消失以后再进行操作:

二、初始简单测试
完成上面的配置,我们的基本框架就已经搭建好了,剩下的就是实现应用程序了,那么在实际的操作之前,我们先简单验证一下整体的框架没有问题,简单测试下 LED 和按键,串口的话要单独一篇文章分析。
2.1 基本设计思路
首先我们得在 main.c 文件中包含必备头文件,和在 main 线程中做基本的初始化:

其实这个步骤就和裸机一样,我们完全可以把 main 当成裸机中的 main 函数,所有的程序在 main 中实现,也是可以。 这种方式就类似于 ESP32-C3 使用 ESP-IDF 开发环境中,大部分操作都在 app_main 任务中实现, app_main 也不过是 FreeRTOS 启动时候创建的一个任务。
记得在上一篇博文中我们提到过 一个 main 线程就占用了 2K,这个 2K 不能浪费,要么我们在 main 里面多做一些工作,要么就是到时候把 main 线程的大小改小。
我们一个单品温湿度传感器,有几个主要的工作:
I2C 数据采集,这个部分需要移植一下代码,然后采集实现部分需要用一个线程来实现,计划是定时器到了一定的计数之后,发送一个信号量使得线程唤醒采集一次;
无线模块串口通讯,这个部分是和上一步联动的,定时器到了定时时间,通知传感器采集数据,然后把数据放置无线通讯协议中发送出出去,这个部分还得用一个线程实现,串口的通讯;
LED 灯,其实可有可无,但是作为我们第一个基础应用,还是加上也没关系,LED 的切换,到时候可以随意加在哪里,比如采集到了数据成功发送以后,LED 灯闪烁一次;
按键,按键其实也可有可无,但是还是因为我们的第一个基础应用,我想把我常用的按键驱动移植过来试一试,根据以往经验,按键驱动也需要一个线程,而且这个线程至少需要 512 字节的空间;
定时器,根据产品所需要的的定时时间释放信号量,使得数据采集线程开始工作,定时器是硬件定时器,使用中断实现不用额外线程;
这里思路暂时先这样,后期如果使用过程中有新的改动,再来更新。
2.2 外设简单测试
然后我们把一些外设需要的宏定义设置一下:

LED:
然后在主函数中写一个 LED 灯切换的逻辑(此部分太简单了,所以截个图看看就行了):

按键:
然后新建一个线程,给到时候按键驱动移植使用,这里就用简单的按键处理方式,大小设定为 512 字节。
<font color=#0033FF>值得注意的是,我们新建任务只能用静态初始化的方式,因为我们没有定义使用 heap,新建的线程大小直接影响 RAM 空间大小。</font>

定时器:
我们有一个 1S 的定时,我们也来简单测试一下,具体的测试方式和我们在记录九中的一致:RT-Thread 记录(九、RT-Thread 中断处理与阶段小结)
但是这次我们加了stm32f1xx_it.c
文件,所以我们这次直接在stm32f1xx_it.c
文件中修改(再次说明,实际使用中中断响应函数中不要添加打印操作,这里只是测试测试!!!):

所有改完以后编译一下:

OK!编译没问题,下载查看测试结果:

三、时刻关注占 RAM 大小
在小内存芯片上使用操作系统,程序运行占用的 RAM 大小我们不容忽略,我们在应用中务必学会观察内存占用情况:
完成 CubeMX 基础步骤以后,默认只添加了两个.c 文件,与初始工程的比较:

修改完配置,表示着我们的基础框架基本搭建好了,我们多添加了 GPIO、串口,和定时器的驱动程序:

说明!上面几张图因为刚开始,所以贴了和初始工程的比较,往后的比较我不可能从初始工程开始贴图,只能与上一次工程完善的结果做比较:

本文的简单测试,程序运行时候需要占用 RAM 的大小: 1536+5184= 6720 字节,我们的芯片 RAM:8192 字节。
结语
本文依然还处于工程配置阶段,再次手把手做了次教学,如何使用 STM32CubeMX 配合 RT-Thread Studio 开发。
我们详细的说明了配置步骤,同时在初始测试小节写好了本应用的的设计思路。做了基本框架设计 和 初步的测试说明。
现在看来,这系列应用篇还真算得上保姆级的教程了 = =!博主自己现在都觉得真的细……
下一篇的内容应该是把 I2C 读写的程序移植过来,到时候看看篇幅,如果又有很多细节那就这一个内容,如果内容篇幅简单到时候看情况添加。
好了,本文就到这,谢谢大家!
版权声明: 本文为 InfoQ 作者【矜辰所致】的原创文章。
原文链接:【http://xie.infoq.cn/article/b8695fecf630f5c93262b0dd8】。文章转载请联系作者。
评论