说明:
这次先介绍下PIN设备的操作方法,然后一步一步完成PIN设备的BSP过程。
该BSP主要实现使用PIN设备管理接口
管理按键
和led。
应用程序通过RT-Thred提供的pin设备管理接口来操作GPIO,函数接口如下表:
方法名称 | 方法描述 |
---|---|
rt_pin_mode() | 设置引脚模式 |
rt_pin_write() | 设置引脚电平 |
rt_pin_read() | 读取引脚电平 |
rt_pin_attach_irq() | 绑定引脚中断回调函数 |
rt_pin_detach_irq() | 脱离引脚中断回调函数 |
rt_pin_irq_enable() | 使能引脚中断 |
在使用引脚之前需要先设定引脚的工作模式,通过下面函数完成:
void rt_pin_mode(rt_base_t pin, rt_base_t mode);
参数 | 描述 |
---|---|
pin | 引脚编号 |
mode | 引脚工作模式 |
返回 | 描述 |
无 | 无 |
引脚编号是由rt-thread的pin设备管理驱动程序定义的,并不是芯片的引脚号。有2种方式可以获取引脚编号:使用宏定义GET_PIN(port, pin)
或者查看PIN 驱动文件drv_gpio.c
。
使用宏定义比较方便。比如要获取led
的引脚编号,硬件图如图1.led原理图
:
代码如下:
#define LEDR_PIN GET_PIN(H, 10)
#define LEDG_PIN GET_PIN(H, 11)
#define LEDB_PIN GET_PIN(H, 12)
代码如下:
#define KEY1_PIN GET_PIN(H, 10)
#define KEY2_PIN GET_PIN(C, 13)
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 /*开漏输出*/
设置引脚电平使用如下函数完成:
void rt_pin_write(rt_base_t pin, rt_base_t value);
参数 | 描述 |
---|---|
pin | 引脚编号 |
value | 电平逻辑值:PIN_LOW (低电平),PIN_HIGH(高电平) |
返回 | 描述 |
无 | 无 |
读取引脚电平使用如下函数完成:
int rt_pin_read(rt_base_t pin);
参数 | 描述 |
---|---|
pin | 引脚编号 |
value | 电平逻辑值:PIN_LOW (低电平),PIN_HIGH(高电平) |
返回 | 描述 |
PIN_LOW | 低电平 |
PIN_HIGH | 高电平 |
如果需要使用引脚的中断功能,那么需要使用如下函数将某个引脚设置为某种中断触发模式,并且绑定中断触发回调函数,当中段发生时,执行回调函数:
rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode,
void (*hdr)(void *args), void *args);
参数 | 描述 |
---|---|
pin | 引脚编号 |
mode | 中断触发模式 |
hdr | 中断回调函数,用户自己定义 |
args | 总段回调函数的参数,无时为空:RT_NULL |
返回 | 描述 |
RT_EOK | 绑定成功 |
错误码 | 绑定失败 |
中断触发有以下5种模式:
#define PIN_IRQ_MODE_RISING 0x00 /*上升沿触发*/
#define PIN_IRQ_MODE_FALLING 0x01 /*下降沿触发*/
#define PIN_IRQ_MODE_RISING_FALLING 0x02 /*上升沿和下降沿都触发*/
#define PIN_IRQ_MODE_HIGH_LEVEL 0x03 /*高电平触发*/
#define PIN_IRQ_MODE_LOW_LEVEL 0x04 /*低电平触发*/
绑定好中断出发回调函数以后,就可以通过下面的函数使能引脚中断:
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled);
参数 | 描述 |
---|---|
pin | 引脚编号 |
enabled | 使能状态:PIN_IRQ_ENABLE(开启),PIN_IRQ_DISABLE(关闭) |
返回 | 描述 |
RT_EOK | 使能成功 |
错误码 | 使能失败 |
绑定好中断出发回调函数以后,如果需要不再执行中断触发回调函数,可以使用如下函数脱离绑定的回调函数:
rt_err_t rt_pin_detach_irq(rt_int32_t pin);
参数 | 描述 |
---|---|
pin | 引脚编号 |
返回 | 描述 |
RT_EOK | 脱离成功 |
错误码 | 脱离失败 |
注意:脱离中断回调函数后,中断并没有关掉,只是不再执行被脱离的回调函数,可以再次绑定该回调函数,当然也可以不绑定该对调函数,去绑定其他回调函数也是可以的
有了前面的rt-thread:_001STM32F429IGT BSP前期准备,那么该bsp无非就是再次模版基础上加入bsp的应用程序而已,比较方便。
实现红、绿、蓝三个led灯的轮流亮灭。硬件图请看图1
。
首先新建两个文件bsp_led.c
和bsp_led.h
;然后把bsp_led.c
放入bsp_src
文件夹里,bsp_led.h
放入bsp_inc
文件夹里。同时在
main.h
里面添加bsp_led的头文件,如下:
#include "bsp_inc/bsp_led.h"
其中bsp_led.h
里面的代码如下:
#ifndef __BSP_LED_H
#define __BSP_LED_H
#include "applications/main.h"
/* 定义LED_R、LED_G、LED_B、 的引脚 */
#define LEDR_PIN GET_PIN(H, 10)
#define LEDG_PIN GET_PIN(H, 11)
#define LEDB_PIN GET_PIN(H, 12)
/* 定义蜂鸣器的引脚 */
#define SPEEK_PIN GET_PIN(I, 11)
/* 声明bsp_led线程函数 */
static void bsp_led_thread_entry(void *parameter);
#endif
其中bsp_led.c
里面的代码如下:
#include "bsp_led.h"
/***************************************************************
* 函数: static void bsp_led_sample(int argc, char *argv[])
* 参数: int argc, char *argv[]
* 返回值:无
* 功能: 完成相关led对应引脚的初始化设置,创建并启动bsp_led线程
*****************************************************************/
static void bsp_led_sample(int argc, char *argv[])
{
/* 设置led引脚的模式 */
rt_pin_mode(LEDR_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LEDG_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LEDB_PIN, PIN_MODE_OUTPUT);
/* 设置led引脚的初始输出电平 */
rt_pin_write(LEDR_PIN, PIN_HIGH);
rt_pin_write(LEDG_PIN, PIN_HIGH);
rt_pin_write(LEDB_PIN, PIN_HIGH);
static rt_thread_t bsp_led_tid = RT_NULL; /* 定义bsp_led线程的控制块 */
/* 创建bsp_led线程 */
bsp_led_tid = rt_thread_create("bsp_led_tid", bsp_led_thread_entry,
RT_NULL, 513, BSP_LED_PRIORITY, 10);
/* 启动bsp_led线程 */
if (bsp_led_tid != RT_NULL)
{
rt_thread_startup(bsp_led_tid);
}
}
/* 导出bsp_led_sample至FinSH终端 */
MSH_CMD_EXPORT(bsp_led_sample, bsp led sample);
/***************************************************************
* 函数: static void bsp_led_thread_entry(void *parameter)
* 参数: 空指针
* 返回值:无
* 功能: 实现led流水运行
*****************************************************************/
static void bsp_led_thread_entry(void *parameter)
{
while (1)
{
/* LED_R 2秒周期运行 */
rt_pin_write(LEDR_PIN, PIN_LOW);
rt_thread_mdelay(1000);
rt_pin_write(LEDR_PIN, PIN_HIGH);
rt_thread_mdelay(1000);
/* LED_G 2秒周期运行 */
rt_pin_write(LEDG_PIN, PIN_LOW);
rt_thread_mdelay(1000);
rt_pin_write(LEDG_PIN, PIN_HIGH);
rt_thread_mdelay(1000);
/* LED_B 2秒周期运行 */
rt_pin_write(LEDB_PIN, PIN_LOW);
rt_thread_mdelay(1000);
rt_pin_write(LEDB_PIN, PIN_HIGH);
rt_thread_mdelay(1000);
}
}
打开stm32f429-hlg-v1.0\board
下面的Kconfig
文件,在该文件的 menu "BSP module"
配置模块下面添加如下图内容:
有了该宏,那么在env
工具里面就可以很方便的开启或者关闭该宏,如果开启该宏,则在rtconfig.h
里面就会生成该宏。
打开stm32f429-hlg-v1.0\applications
下面的SConscript
编译链接脚本文件,在里面添加如下图内容:
在env
里输入menuconfig
打开工程配置,开启Enable led
,如下图:
然后一直按Esc
至保存界面,选Yes
保存退出。
在env
输入scons --target=mdk5
重新生成keil5
工程;输入scons --target=mdk4
重新生成keil4
工程;输入scons --target=iar
重新生成iar
工程;输入scons --target=vsc
更新VSCode
头文件路径。
打开keil5
工程,然后就可以看到现在的工程目录结构如下图:
然后编译之后看看是否有错误或者警告。只要前面步骤没有出错,这里肯定不会要问题。
下载程序到开发板。然后打开终端工具。在中断输入例程的导出命令bsp_led_sample
,便可以看到开发板led灯三种颜色轮流亮灭。再输入查看线程指令list_thread
,便可以看到bsp_led线程
的运行基本信息,如下图:
这样一个led灯的bsp就彻底完成了。
按键的bsp过程基本上与led的bsp过程一样。在此做一些扩展,加入pin中断
操作,关于pin设备的中断管理API请看本文前面的介绍。
完成利用按键的外部中断来操作led灯,按下key1灯亮,按下key2灯灭。硬件图请看图2
。
首先新建两个文件bsp_key.c
和bsp_key.h
;然后把bsp_key.c
放入bsp_src
文件夹里,bsp_key.h
放入bsp_inc
文件夹里。同时在
main.h
里面添加bsp_key的头文件,如下:
#include "bsp_inc/bsp_key.h"
其中bsp_key.h
里面的代码如下:
#ifndef __BSP_KEY_H
#define __BSP_KEY_H
#include "applications/main.h"
/* 定义KEY1和KEY2 的引脚 */
#define KEY1_PIN GET_PIN(A, 0)
#define KEY2_PIN GET_PIN(C, 13)
/* 定义bsp_key线程的优先级 */
#define BSP_KEY_PRIORITY 5
/* 声明函数 */
void ledr_on(void *parameter);
void ledr_off(void *parameter);
static void key_led_entry(void *paraemter);
static void key_led_sample(int argc, char *argv[]);
#endif
其中bsp_led.c
里面的代码如下:
#include "bsp_key.h"
/***************************************************************
* 函数: void bsp_ledr_on(void *parameter)
* 参数: 空指针
* 返回值:无
* 功能: 按键中断回调函数,实现ledr亮
*****************************************************************/
void bsp_ledr_on(void *parameter)
{
rt_kprintf("key1 press down! led on!\n"); /*按下key1按键打印信息*/
rt_pin_write(LEDR_PIN, PIN_LOW); /*按下key1灯亮*/
}
/***************************************************************
* 函数: void bsp_ledr_off(void *parameter)
* 参数: 空指针
* 返回值:无
* 功能: 按键中断回调函数,实现ledr灭
*****************************************************************/
void bsp_ledr_off(void *parameter)
{
rt_kprintf("key2 press down! led off!\n"); /*按下key2按键打印信息*/
rt_pin_write(LEDR_PIN, PIN_HIGH); /*按下key2灯灭*/
}
/***************************************************************
* 函数: static void bsp_key_entry(void *paraemter)
* 参数: 空指针
* 返回值:无
* 功能: 按键线程,实现按键中断回调函数绑定,以及使能按键中断
*****************************************************************/
static void bsp_key_entry(void *paraemter)
{
while (1)
{
rt_thread_mdelay(10);
/*确定按键中断触发模式以及绑定中断回调函数*/
rt_pin_attach_irq(KEY1_PIN, PIN_IRQ_MODE_RISING, bsp_ledr_on, RT_NULL);
rt_pin_attach_irq(KEY2_PIN, PIN_IRQ_MODE_RISING, bsp_ledr_off, RT_NULL);
/*确定按键中断触发模式以及绑定中断回调函数*/
rt_pin_irq_enable(KEY1_PIN, PIN_IRQ_ENABLE);
rt_pin_irq_enable(KEY2_PIN, PIN_IRQ_ENABLE);
}
}
/***************************************************************
* 函数: static void bsp_led_sample(int argc, char *argv[])
* 参数: int argc, char *argv[]
* 返回值:无
* 功能: 完成相关led对应引脚的初始化设置,创建并启动bsp_led线程
*****************************************************************/
static void bsp_key_sample(int argc, char *argv[])
{
/*定义按键线程设备块*/
static rt_thread_t key_tid = RT_NULL;
/*设置按键以及led对应引脚的输入、输出模式*/
rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLDOWN);
rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLDOWN);
rt_pin_mode(LEDR_PIN, PIN_MODE_OUTPUT);
/*设置led的默认输出电平*/
rt_pin_write(LEDR_PIN, PIN_HIGH);
/*创建按键线程*/
key_tid = rt_thread_create("key_tid", bsp_key_entry, RT_NULL,
512, BSP_KEY_PRIORITY, 10);
/*开启按键线程*/
if (key_tid != RT_NULL)
{
rt_thread_startup(key_tid);
}
}
/*导出bsp_key_sample命令至FinSH终端*/
MSH_CMD_EXPORT(bsp_key_sample, bsp key led sample);
打开stm32f429-hlg-v1.0\board
下面的Kconfig
文件,在该文件的 menu "BSP module"
配置模块下面添加如下图内容:
有了该宏,那么在env
工具里面就可以很方便的开启或者关闭该宏,如果开启该宏,则在rtconfig.h
里面就会生成该宏。
打开stm32f429-hlg-v1.0\applications
下面的SConscript
编译链接脚本文件,在里面添加如下图内容:
在env
里输入menuconfig
打开工程配置,开启Enable key
,如下图:
然后一直按Esc
至保存界面,选Yes
保存退出。
在env
输入scons --target=mdk5
重新生成keil5
工程;输入scons --target=mdk4
重新生成keil4
工程;输入scons --target=iar
重新生成iar
工程;输入scons --target=vsc
更新VSCode
头文件路径。
打开keil5
工程,然后就可以看到现在的工程目录结构如下图:
然后编译之后看看是否有错误或者警告。只要前面步骤没有出错,这里肯定不会要问题。
下载程序到开发板。然后打开终端工具。在中断输入例程的导出命令bsp_key_sample
,然后按下key1
可以看到对应的输出信息,以及开发板等亮;按下key2
,可以看到对应的输出信息,以及开发板灯灭。再输入查看线程指令list_thread
,便可以看到bsp_key线程
的运行基本信息,如下图:
这样一个使用按键中断控制led灯的bsp就彻底完成了。
有了上一篇文章rt-thread:_001STM32F429IGT BSP前期准备前期准备`完成的模板,在此基础上增加led和key的bsp就非常容易轻松。再结合env工具,可以快速实现工程配置。
rt-thread:_001STM32F429IGT BSP前期准备
RT-Thread PIN设备管理-官网连接