RT-Thread | 开发学习入门-2030802

RT-Thread 线下培训**-**实验环境搭建

对象:RT-Thread初学者

环境搭建

开发板 简介

本次实验开发板为 infineon。

本款款开发板作为教学开发板,并且在RT-Thread完整版本的代码里面也有开发板的bsp,这样就能达到开箱

即用的效果。

开发平台及代码介绍

  1. 电脑选择:win10、win11。
  1. 开发平台:选择RT-Thread Studio,点击下载安装教程完成安装。
  1. 代码:安装好Studio之后,在SDK管理器中下载相应的代码包,按照开发板不同,选择对应的代码安装

包即可。Infineon:PSOC62-IFX-EVAL-KIT(PSoc62 评估板)

工具链 v5.4.1

创建工程

创建rt-thread项目,基于开发板 英飞凌开发板 的工程。

给工程添加软件包

双击打开rt-thread-settings添加后保存,可以在工程中发现 morse 的软件包。

以上是摩斯电码工程搭建全过程。

软件包的配置

使用开发板上的USER按键完成摩斯密码的体验,配置如下:选择 MORSE SAMPLE,使用 KEY_SAMPLE。

USER按键是P6.2,在morse-key-example.c中将引脚定义修改为 #define USER_KEY GET_PIN(6, 2) 。

线下培训

无法下载的,检查下面的包有没有安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IiyBXeMD-1690969025961)(https://docimg2.docs.qq.com/image/AgAACDQyxbrSS3QlQMVOlpcnt2gdd8Xn.png?w=981&h=589)]

LED 和按键示例

LED 灯和按键的引脚分别为 P0.0 P6.2

LED 和 按键同属于 PIN 设备控制 关于 PIN 设备介绍请查看 PIN 设备

LED 使用示例:

以下代码功能: LED 灯以 500ms 为间隔闪烁

#include 
#include 
#include 

/* defined the LED0 pin: P0.0 */
#define LED0_PIN               GET_PIN(0, 0)

int main(void)
{
    int count = 1;
    /* set LED0 pin mode to output */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);

    while (count++)
    {
        rt_pin_write(LED0_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED0_PIN, PIN_LOW);
        rt_thread_mdelay(500);
    }
    return RT_EOK;
}

按键使用示例:(需要关闭 morse 软件包)

以下代码功能: 开发板上电,每次按下按键,串口终端都会输出 RT-Thread! 字样

#include 
#include 
#include 

#define USER_KEY GET_PIN(6, 2)

void irq_callback()
{
    rt_kprintf("RT-Thread!\r\n");
}

int main(void)
{
    rt_pin_mode(USER_KEY, PIN_MODE_INPUT_PULLUP);
    rt_pin_attach_irq(USER_KEY, PIN_IRQ_MODE_RISING_FALLING, irq_callback, RT_NULL);
    rt_pin_irq_enable(USER_KEY, PIN_IRQ_ENABLE);
    return 0;
}

自动初始化机制

下面是自动化执行的示例

以下代码功能: 开发板上电将会看到终端上打印下面的字符

export_app RT-Thread!
#include 

int export_app(void)
{
    rt_kprintf("export_app RT-Thread!\r\n");
    return 0;
}
INIT_APP_EXPORT(export_app);

自定义 msh 命令

以下代码功能: 在终端中输入 hello 后回车,将会打印 hello RT-Thread! 字样

void hello(void)
{
    rt_kprintf("hello RT-Thread!\n");
}

MSH_CMD_EXPORT(hello , say hello to RT-Thread);

线程管理

线程1:每隔500ms打印一次计数

线程2:打印10次计数后,打印退出并退出

这个例子创建一个动态线程初始化一个静态线程,一个线程在运行完毕后自动被系统删除,另一个线程一直打印计数,如下代码

#include 

#define THREAD_PRIORITY         25
#define THREAD_STACK_SIZE       512
#define THREAD_TIMESLICE        5

static rt_thread_t tid1 = RT_NULL;

/* 线程 1 的入口函数 */
static void thread1_entry(void *parameter)
{
    rt_uint32_t count = 0;

    while (1)
    {
        /* 线程 1 采用低优先级运行,一直打印计数值 */
        rt_kprintf("thread1 count: %d\n", count ++);
        rt_thread_mdelay(500);
    }
}

ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 线程 2 入口 */
static void thread2_entry(void *param)
{
    rt_uint32_t count = 0;

    /* 线程 2 拥有较高的优先级,以抢占线程 1 而获得执行 */
    for (count = 0; count < 10 ; count++)
    {
        /* 线程 2 打印计数值 */
        rt_kprintf("thread2 count: %d\n", count);
    }
    rt_kprintf("thread2 exit\n");
    /* 线程 2 运行结束后也将自动被系统脱离 */
}

/* 线程示例 */
int thread_sample(void)
{
    /* 创建线程 1,名称是 thread1,入口是 thread1_entry*/
    tid1 = rt_thread_create("thread1",
                            thread1_entry, RT_NULL,
                            THREAD_STACK_SIZE,
                            THREAD_PRIORITY, THREAD_TIMESLICE);

    /* 如果获得线程控制块,启动这个线程 */
    if (tid1 != RT_NULL)
    rt_thread_startup(tid1);

    /* 初始化线程 2,名称是 thread2,入口是 thread2_entry */
    rt_thread_init(&thread2,
                    "thread2",
                    thread2_entry,
                    RT_NULL,
                    &thread2_stack[0],
                    sizeof(thread2_stack),
                    THREAD_PRIORITY - 1, THREAD_TIMESLICE);
    rt_thread_startup(&thread2);

    return 0;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(thread_sample, thread sample);

定时器管理

定时器1:周期定时器,10次之后让其停止

定时器2:单次定时器

这是一个创建定时器的例子,这个例程会创建两个动态定时器,一个是单次定时,一个是周期性定时并让周期定时器运行一段时间后停止运行,如下所示:

#include 

/* 定时器的控制块 */
static rt_timer_t timer1;
static rt_timer_t timer2;
static int cnt = 0;

/* 定时器 1 超时函数 */
static void timeout1(void *parameter)
{
    rt_kprintf("periodic timer is timeout %d\n", cnt);

    /* 运行第 10 次,停止周期定时器 */
    if (cnt++ >= 9)
    {
        rt_timer_stop(timer1);
        rt_kprintf("periodic timer was stopped! \n");
    }
}

/* 定时器 2 超时函数 */
static void timeout2(void *parameter)
{
    rt_kprintf("one shot timer is timeout\n");
}

int timer_sample(void)
{
    /* 创建定时器 1  周期定时器 */
    timer1 = rt_timer_create("timer1", timeout1,
                             RT_NULL, 10,
                             RT_TIMER_FLAG_PERIODIC);

    /* 启动定时器 1 */
    if (timer1 != RT_NULL)
        rt_timer_start(timer1);

    /* 创建定时器 2 单次定时器 */
    timer2 = rt_timer_create("timer2", timeout2,
                             RT_NULL, 30,
                             RT_TIMER_FLAG_ONE_SHOT);

    /* 启动定时器 2 */
    if (timer2 != RT_NULL)
        rt_timer_start(timer2);
    return 0;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(timer_sample, timer sample);

消息队列

线程1:接收消息,20次后不再接收,最后删除消息队列。

线程2:发送消息,第8次发送一条紧急消息,20次后退出。

这是一个消息队列的应用例程,例程中初始化了 2 个静态线程,一个线程会从消息队列中收取消息;另一个线程会定时给消息队列发送普通消息和紧急消息,如下代码所示:

#include 

/* 消息队列控制块 */
static struct rt_messagequeue mq;
/* 消息队列中用到的放置消息的内存池 */
static rt_uint8_t msg_pool[2048];

ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;
/* 线程 1 入口函数 */
static void thread1_entry(void *parameter)
{
    char buf = 0;
    rt_uint8_t cnt = 0;

    while (1)
    {
        /* 从消息队列中接收消息 */
        if (rt_mq_recv(&mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread1: recv msg from msg queue, the content:%c\n", buf);
            if (cnt == 19)
            {
                break;
            }
        }
        /* 延时 50ms */
        cnt++;
        rt_thread_mdelay(50);
    }
    rt_kprintf("thread1: detach mq \n");
    rt_mq_detach(&mq);
}

ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 线程 2 入口 */
static void thread2_entry(void *parameter)
{
    int result;
    char buf = 'A';
    rt_uint8_t cnt = 0;

    while (1)
    {
        if (cnt == 8)
        {
            /* 发送紧急消息到消息队列中 */
            result = rt_mq_urgent(&mq, &buf, 1);
            if (result != RT_EOK)
            {
                rt_kprintf("rt_mq_urgent ERR\n");
            }
            else
            {
                rt_kprintf("thread2: send urgent message - %c\n", buf);
            }
        }
        else if (cnt >= 20) /* 发送 20 次消息之后退出 */
        {
            rt_kprintf("message queue stop send, thread2 quit\n");
            break;
        }
        else
        {
            /* 发送消息到消息队列中 */
            result = rt_mq_send(&mq, &buf, 1);
            if (result != RT_EOK)
            {
                rt_kprintf("rt_mq_send ERR\n");
            }

            rt_kprintf("thread2: send message - %c\n", buf);
        }
        buf++;
        cnt++;
        /* 延时 5ms */
        rt_thread_mdelay(5);
    }
}

/* 消息队列示例的初始化 */
int msgq_sample(void)
{
    rt_err_t result;

    /* 初始化消息队列 */
    result = rt_mq_init(
        &mq,
        "mqt",
        &msg_pool[0],     /* 内存池指向 msg_pool */
        1,                /* 每个消息的大小是 1 字节 */
        sizeof(msg_pool), /* 内存池的大小是 msg_pool 的大小 */
        RT_IPC_FLAG_PRIO  /* 如果有多个线程等待,优先级大小的方法分配消息 */
    );

    if (result != RT_EOK)
    {
        rt_kprintf("init message queue failed.\n");
        return -1;
    }

    rt_thread_init(&thread1,
                   "thread1",
                   thread1_entry,
                   RT_NULL,
                   &thread1_stack[0],
                   sizeof(thread1_stack), 25, 5);
    rt_thread_startup(&thread1);

    rt_thread_init(&thread2,
                   "thread2",
                   thread2_entry,
                   RT_NULL,
                   &thread2_stack[0],
                   sizeof(thread2_stack), 25, 5);
    rt_thread_startup(&thread2);

    return 0;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(msgq_sample, msgq sample);

摩斯电码使用

摩斯电码目前已经被封装成软件包,可以直接选中 morse 软件包来体验摩斯电码

软件包的配置如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGsEPdF5-1690969025962)(https://docimg9.docs.qq.com/image/AgAACDQyxboUjoiWC8xJBpjP_KdVMRyN.png?w=1204&h=625)]

打开 samples\key\morse-key-example.c 文件,将 USER_KEY 宏所对应引脚对应到开发板的按键

即可编译烧录到开发板中运行,只需要按照摩斯电码的规律按下按键,串口终端上即可显示对应字符。

当使能了 PKG_USING_MORSE_SHELL 之后,输入回车所对应的摩斯电码即可执行输入的命令

摩斯电码参照表 morse 软件包

下载之后如果没有文件,请将 Version 改为 latest

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J7nVYarl-1690969025963)(https://docimg2.docs.qq.com/image/AgAACDQyxbqyvYLMm4NBXJsH2ZBRsj6q.png?w=861&h=349)]

思考&&挑战

参考资料:UART 设备

​ 一、 串口输入字母,LED 灯闪烁出对应摩斯电码

​ 二、 串口输入单词,LED 灯闪烁出对应摩斯电码

你可能感兴趣的:(28-RT-Thread,学习)