目标:点亮一颗LED、按键控制一颗LED。
- RT-Thread studio,版本: 2.2.6,不一样其实区别也不大
- RT-Thread:标准版,4.0.3版本
- 芯片包版本:0.1.9
- 开发板:正点原子潘多拉开发板,主控STM32L475VET6
1. 简述
PIN设备读写和外部中断是定义在同一个文件中,因此可以一起看。
PIN设备在 RT-Thread Settings中默认是开启的,而且不可关闭,因此无需任何配置。
了解以下几点即可:
- 其属于设备行列,使用时需要包含头文件:
#include <rtdevice.h>
; - 引脚编号,定义在设备驱动文件
drivers/drv_gpio.c
中; - PIN设备的状态和模式声明在
rt-thread -> components -> drivers -> include -> drivers -> pin.h
中; - PIN设备相关函数定义在
rt-thread -> components -> drivers -> include -> drivers -> misc -> pin.c
中。
可以去对应的文件中查看全部的定义。
2. 点亮一颗LED
如前文所示,PIN设备是默认开启的,创建工程后无需任何配置,直接编写案例即可。
在工程中新建一个文件夹,在文件夹中新建一个.c
文件,添加以下内容。
编译下载后,在Shell窗口输入led_thread_test
命令,可以看到两个LED闪烁。
这个案例,相对来说,比官网的复杂一丢丢,主要是想试试怎么传参数。
/*
* 程序清单:这是一个 pin 设备使用例程
* 例程导出了 led_thread_test 命令到控制终端
* 命令调用格式:led_thread_test
* 程序功能:运行后两个led闪烁,闪烁时间间隔分别为1s和2s
*/
#include <rtdevice.h>
#include "drv_common.h"
#include <rtthread.h>
// 线程函数体需要传入的参数
typedef struct
{
rt_uint32_t flash_ms;
rt_uint8_t led_index;
}Parameter_struct;
// 线程相关参数
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
// LED引脚定义
#define LED0_PIN GET_PIN(B, 5)
#define LED1_PIN GET_PIN(E, 5)
// LED编号
#define LED0 0
#define LED1 1
// 定义LED0的参数结构体
Parameter_struct Parameter0_struct =
{
.flash_ms = 1000,
.led_index = LED0,
};
// 定义LED1的参数结构体
Parameter_struct Parameter1_struct =
{
.flash_ms = 2000,
.led_index = LED1,
};
/* led_test:动态创建线程
* 1. 定义一个 线程结构体指针 这里命名为:led_thread
* 2. 编写一个 线程函数体 这里命名为:led_thread_entry
* 3. 调用 rt_thread_create 创建一个线程
* 4. 调用 rt_thread_startup 启动线程
*/
static rt_thread_t led_thread = NULL;
/**
* @brief LED闪烁线程函数体
*
* @param flash_ms 闪烁间隔时间,单位毫秒
* @param led_index led编号,0/1
*
* @return none
*
* @note static防止和其他文件中的重名;此线程不会终止。
*/
static void led_thread_entry (void *parameter)
{
// 接收传过来的参数
Parameter_struct *in_parameter = (Parameter_struct *)parameter;
// rt_kprintf("in_flash_ms = %d, in_led_index = %d \n", in_parameter->flash_ms, in_parameter->led_index);
// 反转使用
rt_uint32_t count = 0;
while(1)
{
// 判断LED编号
switch(in_parameter->led_index)
{
case LED0:
rt_kprintf("led0 flash \n");
rt_pin_write(LED0_PIN, count % 2);
break;
case LED1:
rt_kprintf("led1 flash \n");
rt_pin_write(LED1_PIN, count % 2);
break;
default:
rt_kprintf("please enter the correct LED index.(0/1) \n");
}
count++;
rt_thread_mdelay(in_parameter->flash_ms);
}
}
static int led_thread_test(void)
{
// LED模式初始化
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
rt_pin_write(LED0_PIN, 1);
rt_pin_write(LED1_PIN, 1);
/* led0:动态创建线程 start */
if(Parameter0_struct.flash_ms != 0)
{
led_thread = rt_thread_create("led0_th", // name
led_thread_entry, // 函数体入口
(void*)&Parameter0_struct, // 函数体 参数
THREAD_STACK_SIZE, // 分配内存大小
THREAD_PRIORITY, // 优先级
THREAD_TIMESLICE); // 时间片大小
/* 如果获得线程控制块,启动这个线程 */
if (led_thread != RT_NULL)
rt_thread_startup(led_thread); // 启动线程
else
{
// 输出错误码
rt_kprintf("led0 flash thread is failed...the error code is %ld \r\n", led_thread->error);
}
}
/* led0:over */
led_thread = RT_NULL;
/* led1:动态创建线程 start */
if(Parameter1_struct.flash_ms != 0)
{
led_thread = rt_thread_create("led1_th", // name
led_thread_entry, // 函数体入口
(void*)&Parameter1_struct, // 函数体 参数
THREAD_STACK_SIZE, // 分配内存大小
THREAD_PRIORITY, // 优先级
THREAD_TIMESLICE); // 时间片大小
/* 如果获得线程控制块,启动这个线程 */
if (led_thread != RT_NULL)
rt_thread_startup(led_thread); // 启动线程
else
{
// 输出错误码
rt_kprintf("led1 flash thread is failed...the error code is %ld \r\n", led_thread->error);
}
}
/* led1:over */
return RT_EOK;
}
MSH_CMD_EXPORT(led_thread_test, led thread test);
3. 按键控制LED
在工程中新建一个文件夹,在文件夹中新建一个.c
文件,添加以下内容。
编译下载后,在Shell窗口输入key_irq_test
命令,然后按下按键,对应LED亮起。
/*
* 程序清单:这是一个 PIN 设备绑定中断使用例程
* 例程导出了 key_irq_test 命令到控制终端
* 命令调用格式:key_irq_test
* 程序功能:通过按键控制led亮灭
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
// KEY引脚定义
#define KEY0_PIN GET_PIN(E, 4) // RIGHT
#define KEY2_PIN GET_PIN(E, 2) // LEFT
// LED引脚定义
#define LED0_PIN GET_PIN(B, 5)
#define LED1_PIN GET_PIN(E, 5)
void led0_on(void *args)
{
rt_kprintf("led0 on, led1 off!\n");
rt_pin_write(LED0_PIN, PIN_LOW);
rt_pin_write(LED1_PIN, PIN_HIGH);
}
void led1_on(void *args)
{
rt_kprintf("led0 off, led1 on!\n");
rt_pin_write(LED0_PIN, PIN_HIGH);
rt_pin_write(LED1_PIN, PIN_LOW);
}
static void key_irq_test(void)
{
/* LED引脚为输出模式 */
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
/* 默认高电平 */
rt_pin_write(LED0_PIN, PIN_HIGH);
rt_pin_write(LED1_PIN, PIN_HIGH);
/* 按键0引脚为输入模式 */
rt_pin_mode(KEY0_PIN, PIN_MODE_INPUT_PULLUP);
/* 绑定中断,下降沿模式,回调函数名为led0_on */
rt_pin_attach_irq(KEY0_PIN, PIN_IRQ_MODE_FALLING, led0_on, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY0_PIN, PIN_IRQ_ENABLE);
/* 按键2引脚为输入模式 */
rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);
/* 绑定中断,下降沿模式,回调函数名为led1_on */
rt_pin_attach_irq(KEY2_PIN, PIN_IRQ_MODE_FALLING, led1_on, RT_NULL);
/* 使能中断 */
rt_pin_irq_enable(KEY2_PIN, PIN_IRQ_ENABLE);
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(key_irq_test, key irq test);