RT-Thread 线下培训**-**实验环境搭建
对象:RT-Thread初学者
环境搭建
开发板 简介
本次实验开发板为 infineon。
本款款开发板作为教学开发板,并且在RT-Thread完整版本的代码里面也有开发板的bsp,这样就能达到开箱
即用的效果。
开发平台及代码介绍
- 电脑选择:win10、win11。
- 开发平台:选择RT-Thread Studio,点击下载安装教程完成安装。
- 代码:安装好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 灯和按键的引脚分别为 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);
以下代码功能: 在终端中输入 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 灯闪烁出对应摩斯电码