基于RTThread嵌入式物联网应用开发第二章GPIO操作实验!
第二章 GPIO操作实验
本章主要内容为通过使用RT-Thread中的PIN设备接口函数对开发板上板载的LED灯进行操作。主要实现功能为点亮LED灯让其规律闪烁。1.1 硬件介绍
在IOT开发板上已经为我们集成焊接了一个三色的RGB灯,具体位置如下图所示:
RGB灯图示
在官方给的原理图资料中我们也可以找到LED模块的电路图。如电路图所示,我们可以发现3个LED灯外接了一个3V的直流电源接口,后面的引脚接入到了单片机的引脚,所以我只需要将单片机的引脚输出改为低电平输出即可点亮LED灯。
LED灯电路原理图
LED灯单片机引脚图
1.2 软件设计1.2.1 单色灯点亮测试a) 功能实现思路分析
从电路原理图中我们可以发现,LED_G对应了单片机的39号引脚(GPIO PE8)。若不想查看原理图,也可以查看官方给出的IO引脚分配表。分配表中也给出了LED_G对应的GPIO引脚为PE8。
所以我们只需要利用RT-Thread为我们提供的通用GPIO驱动来将PE8设置为低电平输出即可点亮LED灯。
我们需要使用的API函数主要有以下两个,功能分别为设置引脚模式与设置引脚电平。在stuido创建的工程下,有一个drivers的目录,此目录是RT-Thread为用户封装好的一些常用驱动库。此章节需要使用的为gpio驱动库。关于驱动库的使用方式以及介绍我们可以前往RT-Thread官方文档中进行查看,此部分内容为设备和驱动下的PIN设备。
在基于传统HAL库开发中,我们总的开发流程可总结为以下步骤:1.对GPIO口进行配置;2.GPIO口初始化;3.设置GPIO口工作模式;4.设置GPIO口引脚电平状态。使用RT-Thread进行开发也可总结为以下几个步骤:1.定义引脚编号映射;2.设置引脚工作模式;3.设置引脚电平状态。基于此流程我们可以对软件进行设计。总流程图如图所示:
软件设计流程图
在RT-Thread中获取引脚编号的方式有三种,一种是利用API函数的方式、一种是利用宏定义的方式还有一种是查看驱动文件来获取引脚编号。此历程采用查看驱动文件来获取引脚编号,其他方式的使用场景请自行前往官方文档查看。
查看驱动文件来获取引脚编号具体实现步骤如下:
1. 打开drivers目录下的drv_gpio.c文件。打开过后我们可以看到已经给我们定义了非常多的相关宏定义以及结构体
2. 找到static const struct pin_index pins[] 结构体,此结构体中为我们设置了单片机与操作系统引脚编号的映射关系。
3. 找寻自己需要的端口号。以__STM32_PIN(72, E, 8) 为例,E为GPIO口名称,即GPIOE。8为引脚号,即PE8。则72就是对应的引脚编号。所以PE8端口在RT-Thread中对应的引脚编号为72。我们在使用过程中只需要定义一个宏定义值为72即可对应单片机的PE8端口。
在我们得到了引脚编号后,即可进行代码编写,调用想用的API函数进行GPIO口的工作模式设定以及电平工作状态设定。b) 设置引脚模式
引脚在使用前需要先设置好其工作模式是输入模式还是输出模式,需要调用的API函数接口如下:void rt_pin_mode(rt_base_t pin, rt_base_t mode);
具体参数详解如下表:
参数
描述
pin
引脚编号
mode
引脚工作模式
引脚编号即为我们在上一步中在驱动文件中查询到的引脚编号,比如PE8为72,我们只需要传入72即可。引脚的工作模式目前RT-Thread支持的宏定义为5中宏定义。具体解释如下表所示:
参数
描述
#define PIN_MODE_OUTPUT 0x00
/* 输出 */
#define PIN_MODE_INPUT 0x01
/* 输入 */
#define PIN_MODE_INPUT_PULLUP 0x02
/* 上拉输入 */
#define PIN_MODE_INPUT_PULLDOWN 0x03
/* 下拉输入 */
#define PIN_MODE_OUTPUT_OD 0x04
/* 开漏输出 */
所以参数mode我们只需要传入定义好的宏定义即可。c) 设置引脚电平
上一步我们设置完了引脚的工作模式为输出模式,这一步我们需要对引脚的电平进行设置,从9.1节中我们可以得到只需要将GPIO引脚设置为低电平即可点亮LED灯。所以我们只需要利用API函数将其设置成为低电平即可完成此功能。
需要使用的API函数接口如下:void rt_pin_write(rt_base_t pin, rt_base_t value);
参数讲解如下:
参数
描述
pin
引脚编号
value
电平逻辑值,可取 2 种宏定义值之一:PIN_LOW 低电平,PIN_HIGH 高电平d) 具体代码实现
在上一小节中,我们已经将从硬件到使用API函数接口去实现功能做了完整的分析。下面我们将开始着手编写代码,进行实际操作。
具体实现步骤如下:
1. 打开我们新建的工程,新建一个led的源文件。
2. 在源文件中导入需要的头文件#include,#include; 定义led线程句柄、定义相关宏定义的值;
3. 编写led线程入口函数,入口函数里实现在上一小节中梳理的引脚设置模式。
4. 编译、下载运行。/*导入头文件*/ #include #include /*定义线程句柄与GPIO引脚宏定义*/ static rt_thread_t LEDG_Thread = RT_NULL; #define LEDG 72 #define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 512 #define THREAD_TIMESLICE 5 /*编写入口函数*/ static void LEDG_Thread_Entry(void *parmas) { /*设置引脚模式*/ rt_pin_mode(LEDG, PIN_MODE_OUTPUT); /*设置引脚电平状态*/ rt_pin_write(LEDG, PIN_LOW); rt_kprintf("ledg on. "); } int led_G(void) { /*创建线程*/ LEDG_Thread=rt_thread_create("led_thread",LEDG_Thread_Entry,RT_NULL,THREAD_STACK_SIZE,THREAD_PRIORITY,THREAD_TIMESLICE); if (LEDG_Thread == RT_NULL) { rt_kprintf("create led thread failed. "); return -1; } /*启动线程*/ rt_thread_startup(LEDG_Thread); return 0; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(led_G, led_G);
5. 打开终端命令行执行led_G命令,查看结果。我们可以发现在终端控制台中会打印一段话ledg on.且在开发板上会发现LED灯部分绿色的灯亮起。如下图所示:
实验结果图1.2.2 呼吸灯应用a) 功能实现思路分析
我们在上一小节中对开发板中单色RGB灯进行了点亮操作,从电路图中我们可以发现还有另外两只RGB灯可供使用。在此小节我们将实现三色灯交替闪烁的功能。
对于电路原理图以及单片机引脚接口都可以在原理图中以及引脚分配表中查询到,LED_B对应了PE9,LED_G对应了PE8,LED_R对应了PE7。在代码实现部分我们的步骤也分为以下三步:1.定义引脚编号映射;2.设置引脚工作模式;3.设置引脚电平状态。在设置引脚电平状态时我们需要对另外两个RGB灯进行关闭,确保在一个时间段能开启一个RGB灯,依次循环即可实现呼吸灯的效果。具体流程图如下所示:
软件流程图b) 具体代码实现
我们需要使用的API接口函数和查看单片机引脚编号的方法已经在上小节中做了介绍,这里就不在赘述了。我们编写功能代码时,按照流程图的思路进行编写即可。
1. 新建一个源文件,文件名自行更改。
2. 导入相关的头文件。
3. 创建RGB线程,并编写线程入口函数,入口函数中实现我们需要的功能。
4. 编译、下载、运行。
具体代码实现如下:/*导入头文件*/ #include #include /*定义线程句柄与GPIO引脚宏定义*/ static rt_thread_t RGB_Thread = RT_NULL; #define LEDB 73 #define LEDG 72 #define LEDR 71 #define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 512 #define THREAD_TIMESLICE 5 /*编写入口函数*/ static void RGB_Thread_Entry(void *parmas) { /*设置引脚模式*/ rt_pin_mode(LEDB, PIN_MODE_OUTPUT); rt_pin_mode(LEDG, PIN_MODE_OUTPUT); rt_pin_mode(LEDR, PIN_MODE_OUTPUT); /*设置引脚电平状态1.先打开LEDB 其他关闭 然后延迟500ms打开LEDG其他关闭延迟500ms,打开LEDR其他关闭*/ while (1) { rt_pin_write(LEDB, PIN_LOW); rt_pin_write(LEDG, PIN_HIGH); rt_pin_write(LEDR, PIN_HIGH); rt_thread_mdelay(500); rt_kprintf("LEDB on. "); rt_pin_write(LEDB, PIN_HIGH); rt_pin_write(LEDG, PIN_LOW); rt_pin_write(LEDR, PIN_HIGH); rt_thread_mdelay(500); rt_kprintf("LEDG on. "); rt_pin_write(LEDB, PIN_HIGH); rt_pin_write(LEDG, PIN_HIGH); rt_pin_write(LEDR, PIN_LOW); rt_thread_mdelay(500); rt_kprintf("LEDR on. "); } } int RGB_Demo(void) { RGB_Thread = rt_thread_create("RGB-Thread",RGB_Thread_Entry,RT_NULL,THREAD_STACK_SIZE,THREAD_PRIORITY,THREAD_TIMESLICE); if (RGB_Thread == RT_NULL) { rt_kprintf("create rgb thread failed "); return -1; } rt_thread_startup(RGB_Thread); return 0; } MSH_CMD_EXPORT(RGB_Demo,RGB_Demo);
我们把代码编译、下载到开发板中,打开终端命令行,输入RGB_Demo命令执行此线程代码。可以发现实验结果如下。
1. RGB灯部分红、蓝、绿交替闪烁。
2. 在终端命令行中循环打印led灯日志。