====>>> 文章汇总(有代码汇总) <<<====
在学习(运行)完 RTT 的内核例程之后,就要学习如何利用RTT进行外设的使用了。
但是在使用外设之前,先要简单了解一下外设使用的框架。还有非常重要的时钟配置。
在RT-Thread中,把MCU的 IO 统称为设备,并按照不同的功能分为了多种,PIN设备、IIC设备、PWM设备等等。
在操作这些设备时,RT-Thread 在硬件和应用程序之间提供 I/O 设备模型框架。从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层。
1. IO设备管理层: 基类。放在 rt-thread -> src 目录下,属于RTT内核中的内容。比如 上图中的 device.c 类。
2. 设备驱动框架层: 放在 rt-thread -> components -> drivers 目录下,也属于RTT内核中的内容。可以在 RT-Thread Settings中进行添加。
3. 设备驱动层: 放在 drivers 目录下。名字和如何使用取决于不同BSP开发者的定义。比如这里STM32的BSP开发者在 board.h 中有详细定义如何使用不同的设备。这部分就是RTT框架中要求的,但是要自己实现的内容。
使用 RT-Thread Studio 创建工程,这部分也是会自动添加。
不管使用什么开发,时钟总是最重要的一部分之一,需要修改为我们开发板上的时钟频率。因此,在这里分析一下先(不想知道的直接看2.2小节)。其实还是要看启动过程,不过这里只看时钟相关。
在创建工程的时候,根据提示默认使用的是内部时钟,如果需要修改,请修改drv_clk.c
文件。
然后在 rt-thread -> src -> components.c 文件中能看到包含int entry(void)
在内的所有初始化函数。
从int entry(void);
函数中进入rtthread_startup();
函数,再从中进入rt_hw_board_init();
函数,再从中进入hw_board_init(BSP_CLOCK_SOURCE, BSP_CLOCK_SOURCE_FREQ_MHZ, BSP_CLOCK_SYSTEM_FREQ_MHZ);
函数。
这里面传入的参数是定义在 board.h 文件中的,默认如下:
/-------------------------- CLOCK CONFIG BEGIN --------------------------/
#define BSP_CLOCK_SOURCE (“HSI”)
#define BSP_CLOCK_SOURCE_FREQ_MHZ ((int32_t)0)
#define BSP_CLOCK_SYSTEM_FREQ_MHZ ((int32_t)80)/-------------------------- CLOCK CONFIG END --------------------------/
但是,继续往下翻下去,发现传入的这几个参数根本没用。
再从中进去clk_init(clock_src, clock_src_freq, clock_target_freq);
函数。这个函数就定义在drv_clk.c
文件中。
该函数又调用了system_clock_config(target_freq);
函数,该函数内容如下,这里的时钟配置为默认使用的内部高速时钟。
可以看出,最后这里是时钟初始化的地方。需要修改时钟只需要修改此函数即可。
可以看出,board.h中的那几个宏定义在传参的过程中,最后也没传过来。(即 没用)
最简单的配置时钟的方法还是,使用cubemx生成一个。
从左侧打开cubemx窗口,然后配置上调试接口、时钟树、串口,然后选择makefile,直接生成工程,其他的都没有改动。生成完毕之后,然后关闭cubemx界面(后续都是关闭界面之后才生效,就不再写了),在左边可以看到cubemx文件夹。
注意:
- 串口的配置,打开就行,具体的参数可以不用管其实。
- 如果没看到这个文件夹,就鼠标在工程栏选中工程,然后右键刷新一下。
如果没弹出来,注意cubemx界面是否关掉了。一定要关掉才可以。
点击cubemx的时候,有时候会不小心点到多次,打开了两个cubemx界面,都要关掉才行。
因为cubemx根据你的配置重新生成了一份配置文件,所以原有的那一份就给你换了个名字做备份。而且后续每次使用cubemx生成代码后,该文件中的宏定义会自动打开,就不用手动打开了。
为什么在上面的配置中需要勾选串口,是因为,默认的配置文件中是打开了串口的定义的,但是使用cubemx重新生成的话,不勾选串口,生成的配置文件中不会自动添加使用串口的宏定义。
另外,再次打开上面提到的drv_clk.c
文件查看clk_init
函数。
可以发现使用cubemx生成之后,这个函数被自动更改了,提示我们这个函数现在使用的是cubemx生成的内容了。而且此时跟随SystemClock_Config();
函数定义的位置,可以发现,它会跳到cubemx生成的那个main.c
文件中的时钟初始化部分,即调用的是新生成的时钟初始化函数。
而且,在cubemx生成的main.c文件中的main函数中,在定义的前面自动加了**__WEAK**标识。
然后,点击编译,应该也是可以通过的,无错误无警告。
如果有串口相关错误:检查cubemx是否打开了串口一的配置(SHELL默认用的串口一,但是实际上随便勾选一个串口,让cubemx把串口的头文件打开就行了,具体的引脚初始化函数其实没用到)