RT-Thread Studio开发 新手入门

文章目录

  • 前言
  • 一、RT-Thread Studio 与 STM32CubeMX 下载安装
  • 二、新建工程
  • 三、点亮LED灯
  • 四、按键中断
  • 五、串口通信
  • 六、OLED显示


前言

软件开发环境:RT-Thread Studio、STM32CubeMX
硬件:STM32F407ZGT6

一、RT-Thread Studio 与 STM32CubeMX 下载安装

RT-Thread Studio 主要包括工程创建和管理,代码编辑,SDK管理,RT-Thread配置,构建配置,调试配置,程序下载和调试等功能,结合图形化配置系统以及软件包和组件资源,减少重复工作,提高开发效率。一站式的 RT-Thread 开发工具,通过简单易用的图形化配置系统以及丰富的软件包和组件资源,让物联网开发变得简单和高效。

STM32CubeMX是一种图形工具,通过分步过程可以非常轻松地配置STM32微控制器和微处理器,以及为Arm® Cortex®-M内核或面向Arm® Cortex®-A内核的特定Linux®设备树生成相应的初始化C代码

RT-Thread官网:https://www.rt-thread.org/studio.html
STM32CubeMX官网:https://www.st.com/zh/development-tools/stm32cubemx.html
在这里插入图片描述
在这里插入图片描述

默认安装即可。

二、新建工程

①进入RT-Thread Studio,左上角 文件–>新建–>RT-Thread项目
在这里插入图片描述

②填入工程信息并选择相应型号
在这里插入图片描述

③打开新建工程,双击RT-Thread Settings,在“组件和服务层”中单击ulog日志,随后再进行保存设置、编辑
在这里插入图片描述

④编译后可发现工程报错,双击错误可定位到具体位置,知为switch语句出现问题,屏蔽即可,不影响使用,然后重新编译
在这里插入图片描述

该段yiswitch代码是一个在串口初始化过程中处理流控制选项的代码片段。代码中的 switch 语句根据配置结构体 cfg 中的流控制选项 flowcontrol 的值进行判断,并根据不同的选项设置对应的串口硬件流控制模式。

流控制是一种在数据传输过程中进行流量控制的技术,用于协调发送方和接收方之间的数据传输速率,以避免数据丢失或溢出。在串口通信中,常见的流控制选项包括无流控制、硬件流控制(如 CTS/RTS)和软件流控制(如 XON/XOFF)。

⑤重新编译后,无警告报错,则 开始下载程序到单片机
在这里插入图片描述

⑥下载成功,观察main.c函数,可知为串口打印功能

在这里插入图片描述

⑦打开串口,测试代码
在这里插入图片描述

至此新建工程完成!

三、点亮LED灯

首先可以直接复制上节的工程,在其基础上进行修改,具体操作为:选中工程,Crtl+C → Ctrl+V, 然后修改项目名即可
在这里插入图片描述

①观察电路图
在这里插入图片描述

②获取led引脚编号

GET_PIN(port, pin);     

这里为 GET_PIN(F, 2)

③设置引脚模式

void rt_pin_mode(rt_base_t pin, rt_base_t mode);   

这里为 rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);

④设置引脚电平

void rt_pin_write(rt_base_t pin, rt_base_t value);     

由上图知为上拉,即低电平点亮,所以这里为 rt_pin_write(LED0_PIN, PIN_LOW);

综上,代码如下:

#include <rtthread.h>
#include <rtdbg.h>
#include <board.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG

#define LED0_PIN    GET_PIN(F, 2)

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

    while (1)
    {
        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;
}

这里分析一下较陌生的头文件和宏定义 :

#include <rtthread.h>:包含了 RT-Thread 实时操作系统的头文件。RT-Thread 是一个开源的实时操作系统,适用于嵌入式系统和物联网设备。

#include <rtdbg.h>:包含了 RT-Thread 调试宏的头文件。该头文件提供了一些用于调试和日志输出的宏定义和函数。

#include <board.h>:包含了与硬件板级支持相关的头文件。该头文件通常包含了与硬件平台相关的宏定义、函数声明和硬件初始化代码等

#define DBG_TAG "main":定义了一个名为 DBG_TAG 的宏,将其值设置为字符串 “main”。在后续的调试输出中,可以使用该宏来标记输出的日志标签。

#define DBG_LVL DBG_LOG:定义了一个名为 DBG_LVL 的宏,将其值设置为 DBG_LOG。该宏用于设置调试输出的级别,这里设置为输出所有级别的日志信息。

return RT_EOK:RT_EOK通常被定义为值为0的宏,表示操作成功完成。

四、按键中断

①观察电路图知都为上拉,默认高电平。
在这里插入图片描述

②获取led引脚编号

#define KEY1_PIN    GET_PIN(F, 5)

③设置引脚模式

rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP)

④设置引脚中断回调函数

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

这里为设置为下降沿模式,回调函数名为led_on rt_pin_attach_irq(KEY1_PIN, PIN_IRQ_MODE_FALLING , led_on, RT_NULL);

⑤使能中断

rt_pin_irq_enable(KEY1_PIN, PIN_IRQ_ENABLE);

⑥编写中断回调函数

void led_on(void *args)
{
    rt_kprintf("turn on led!\n");

    rt_pin_write(LED0_PIN, PIN_LOW);
}

综上,代码如下:

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include <board.h>
#define LED0_PIN    GET_PIN(F, 2)
#define KEY1_PIN    GET_PIN(F, 5)
#define KEY2_PIN    GET_PIN(F, 6)

void led_on(void *args);
void led_off(void *args);

int main(void)
{
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_write(LED0_PIN, PIN_HIGH);

    rt_pin_attach_irq(KEY1_PIN, PIN_IRQ_MODE_FALLING , led_on, RT_NULL);/* 绑定中断,下降沿模式,回调函数名为led_on */
    rt_pin_attach_irq(KEY2_PIN, PIN_IRQ_MODE_FALLING , led_off, RT_NULL);
    rt_pin_irq_enable(KEY1_PIN, PIN_IRQ_ENABLE);/* 使能中断 */
    rt_pin_irq_enable(KEY2_PIN, PIN_IRQ_ENABLE);

    return RT_EOK;
}


/* 中断回调函数 */
void led_on(void *args)
{
    rt_kprintf("turn on led!\n");

    rt_pin_write(LED0_PIN, PIN_LOW);
}

void led_off(void *args)
{
    rt_kprintf("turn off led!\n");

    rt_pin_write(LED0_PIN, PIN_HIGH);
}

五、串口通信

①在工程中,双击打开cubemx 进行相关配置
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

②关闭cubemx,回到RT-Thread Studio进行更新

在这里插入图片描述

③查找串口设备(一般情况下,注册到系统的串口设备名称为 uart0,uart1等)

static rt_device_t serial;                /* 串口设备句柄 */

serial=rt_device_find(const char* name);

④定义串口配置参数

struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;   // 初始化配置参数 

config.baud_rate = BAUD_RATE_115200;        //修改波特率为 115200
config.data_bits = DATA_BITS_8;           //数据位 8
config.stop_bits = STOP_BITS_1;           //停止位 1
config.bufsz     = 128;                   //修改缓冲区 buff size 为 128
config.parity    = PARITY_NONE;           //无奇偶校验位

rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);    //控制串口设备。通过控制接口传入命令控制字,与控制参数

⑤打开串口设备

rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);     //以中断接收及轮询发送模式打开串口设备

⑥设置串口接收回调函数

rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev,rt_size_t size));   dev表示串口设备句柄,rx_ind表示回调函数指针

⑦串口发送/接收 函数

rt_device_write(serial, 0, str, (sizeof(str) - 1));   //serial表示串口设备句柄、0表示偏移量、str表示要发送的缓存区、(sizeof(str) - 1)表示发送的大小

rt_device_read(serial, 0, &ch, 1)   //serial表示串口设备句柄、0表示偏移量、ch表示要接收的缓存区、1表示接收的大小

⑧编写串口接收回调函数

static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{

    return RT_EOK;
}

⑨定义信号量用于接收处理

static struct rt_semaphore rx_sem;       /* 用于接收消息的信号量 */

rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);   /* 初始化信号量 */

rt_sem_take(&rx_sem, RT_WAITING_FOREVER);    /* 阻塞等待接收信号量,等到信号量后再次读取数据 */

rt_sem_release(&rx_sem);  /* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */

综上,代码如下:

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <string.h>
#include <board.h>
#define LED0_PIN    GET_PIN(F, 2)

#define SAMPLE_UART_NAME       "uart1"    /* 串口设备名称 */

static rt_err_t uart_input(rt_device_t dev, rt_size_t size);    /* 接收数据回调函数 */
static rt_device_t serial;                /* 串口设备句柄 */
static struct rt_semaphore rx_sem;       /* 用于接收消息的信号量 */
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  /* 初始化配置参数 */
char str[] = "hello RT-Thread!\r\n";
char ch;
int main(void)
{
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(LED0_PIN, PIN_HIGH);

    /* 初始化信号量 */
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
    /* step1:查找串口设备 */
    serial = rt_device_find(SAMPLE_UART_NAME);

    /* step2:修改串口配置参数 */
    config.baud_rate = BAUD_RATE_115200;        //修改波特率为 115200
    config.data_bits = DATA_BITS_8;           //数据位 8
    config.stop_bits = STOP_BITS_1;           //停止位 1
    config.bufsz     = 128;                   //修改缓冲区 buff size 为 128
    config.parity    = PARITY_NONE;           //无奇偶校验位

    /* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */
    rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

    /* step4:打开串口设备。以中断接收及轮询发送模式打开串口设备 */
    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);

    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(serial, uart_input);

    /* 发送字符串 */
    rt_device_write(serial, 0, str, (sizeof(str) - 1));


    while (1)
    {
        /* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
        if(rt_device_read(serial, 0, &ch, 1) != 0)
        {
            //rt_thread_mdelay(10);
            /* 阻塞等待接收信号量,等到信号量后再次读取数据 */
            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
            rt_kprintf("%c\n",ch);

            if(ch=='l')
                rt_pin_write(LED0_PIN, PIN_LOW);
            else if(ch=='e')
                rt_pin_write(LED0_PIN, PIN_HIGH);
        }
    }

    return RT_EOK;
}


/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    /* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
    rt_sem_release(&rx_sem);

    return RT_EOK;
}

六、OLED显示

①观察电路图
在这里插入图片描述

②进入RT-Thread Settings选中软件模拟I2C,单击开启并进入配置项
在这里插入图片描述
在这里插入图片描述

在软件包中,添加u8g2图形库,并进入配置项
在这里插入图片描述

③退出RT-Thread Settings,进入头文件board.h进行设置
在这里插入图片描述

④保存设置,回到main.c 直接调用u8g2的图形库API函数 即可驱动oled显示屏显示数据

  • 创建图形设备对象
u8g2_t u8g2; 
  • 初始化oled显示屏
u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_rtthread);      参数分别为: 对象、旋转角度、消息回调函数的指针、显示回调函数的指针
  • 设置控制 OLED 显示屏的引脚
u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_CLOCK, GET_PIN(F,1));//选择CLK引脚
u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_DATA, GET_PIN(F,0));//选择SDA引脚
  • 初始化设备对象
u8g2_InitDisplay(&u8g2);
  • 退出省电模式(默认开启)
u8g2_SetPowerSave(&u8g2, 0);
  • 清屏
u8g2_ClearBuffer(&u8g2); 
  • 设置字体
u8g2_SetFont(&u8g2, u8g2_font_ncenB14_te);
  • 设置要显示的字符
u8g2_DrawStr(&u8g2, 1, 50, "Nie Dong");
  • 将绘制好的图像数据发送到显示设备进行显示
u8g2_SendBuffer(&u8g2);

综上,代码为:

#include <rtthread.h>

#include <u8g2_port.h>
#include <rtdevice.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include <board.h>


int main(void)
{


    u8g2_t u8g2;  //图形设备对象                                        对象         旋转角度         消息回调函数的指针             显示回调函数的指针
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_rtthread);
    u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_CLOCK, GET_PIN(F,1));//选择CLK引脚
    u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_DATA, GET_PIN(F,0));//选择SDA引脚
    u8g2_InitDisplay(&u8g2);   // 初始化设备对象
    u8g2_SetPowerSave(&u8g2, 0);   // 退出省电模式

    u8g2_ClearBuffer(&u8g2);         //清屏
    u8g2_SetFont(&u8g2, u8g2_font_ncenB14_te);   //字体
    u8g2_DrawStr(&u8g2, 1, 50, "Nie Dong");//输入要显示的字符
    u8g2_SendBuffer(&u8g2);   //将绘制好的图像数据发送到显示设备进行显示

    return RT_EOK;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/136107.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言数据结构————————二叉树】

文章目录 文章目录 一、什么是树 树的定义 树的种类 树的深度 树的基本术语 二、满二叉树 定义 满二叉树的特点 三、完全二叉树 定义 特点 四、二叉树的性质 五、二叉树的存储结构 顺序存储结构 链式存储结构 六、二叉树的基本操作 七、二叉树的创建 八、二叉树…

电容的作用

文章目录 总结1.降压2.滤波3.延时4.耦合5.旁路电容 总结 1.降压 问题&#xff1a; 直接连接灯泡会烧掉 解决方案 进一步为了防止电容放电&#xff0c;伤人&#xff0c;加入一个大电阻 2.滤波 直流的情况 交流的情况 频率与容抗的关系 3.延时 4.耦合 滤除直流成分&#xf…

Android---动态权限适配问题

在 Android6.0&#xff0c;即 API 23 之前&#xff0c;App 需要的权限都会在安装阶段向用户展示&#xff0c;而在 App 运行期间不需要动态判断权限是否已申请。从 6.0 之后的版本开始&#xff0c;Android 系统做了一次大的改动。对于部分权限&#xff0c;App 需要在代码中动态申…

Visual Studio 2019 写 Unity 脚本时,烦人又离谱的自动补全!

Visual Studio 2019 写 Unity 脚本时&#xff0c;逆天又离谱的自动补全&#xff01; 血压高升的原因 写脚本的时候&#xff0c;智能提示有哪些函数可以使用&#xff0c;是非常棒的一件事情&#xff0c;有助于游戏开发者编写和检查自己的脚本代码。 但是&#xff01; 我想输入…

序列化模块-json和pickle

一、json json是所有语言都通用的一种序列化格式 &#xff0c;只支持 列表、 字典、 字符串、 数字 &#xff0c; 字典的key必须是字符串 1、dumps、loods # 在内存中做数据转换 : # durps 数据类型 转成 字符串 序列化 # loods 字符串 转成 数据类型 反序…

理解快速排序

理解快速排序 首先了解以下快速排序 快速排序&#xff08;QuickSort&#xff09;是一种常用的排序算法&#xff0c;属于比较排序算法的一种。它是由英国计算机科学家Tony Hoare于1960年提出的&#xff0c;是一种分而治之&#xff08;divide and conquer&#xff09;的算法。 …

C 语言函数

C 语言函数 在本教程中&#xff0c;将向您介绍C语言编程中的函数&#xff08;用户定义函数和标准库函数&#xff09;。此外&#xff0c;您还将学习为什么在编程中使用函数。 函数是执行特定任务的代码块。 假设您需要创建程序来创建一个圆并为其着色。您可以创建两个函数来解…

Redis04-分布式锁

目录 Redis实现分布式锁 分布式锁的工作流程 Redis实现分布式锁 Redission的watch dog Redis分布式锁的合理应用 Redis实现分布式锁 在单节点的服务器中&#xff0c;java中的synchronized机制是处于JVM层面的&#xff0c;只能保证线程之间的同步。而实际的服务部署中&…

第90步 深度学习图像分割:U-Net建模

基于WIN10的64位系统演示 一、写在前面 从这一期开始&#xff0c;我们杀个回马枪&#xff0c;继续学习深度学习图像分割系列&#xff0c;以为4090上岗了。 图像分割是计算机视觉的一个重要任务&#xff0c;目的是将数字图像分割成多个部分或区域&#xff0c;这些部分通常对应…

goroutine调度模型 调度策略

文章目录 背景 协程线程与协程的对比线程&#xff08;Thread&#xff09;协程&#xff08;Coroutine&#xff09; 运作线程模型 goroutine调度模型与演进过程G-M模型G-P-M模型抢占式调度器其他优化 调度策略队列轮转系统调用工作量窃取抢占式调度GOMAXPROCS 对性能的影响 Go在语…

multilinear多项式承诺方案benchmark对比

1. 引言 前序博客有&#xff1a; Lasso、Jolt 以及 Lookup Singularity——Part 1Lasso、Jolt 以及 Lookup Singularity——Part 2深入了解LassoJolt Lasso lookup中&#xff0c;multilinear多项式承诺方案的高效性至关重要。 本文重点关注4种multilinear多项式承诺方案的实…

【Python基础】try-finally语句和with语句

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

Springboot+vue的毕业生实习与就业管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的毕业生实习与就业管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点…

logback异步日志打印阻塞工作线程

前言 最新做项目&#xff0c;发现一些历史遗留问题&#xff0c;典型的是日志打印的配置问题&#xff0c;其实都是些简单问题&#xff0c;但是往往简单问题引起严重的事故&#xff0c;比如日志打印阻塞工作线程&#xff0c;以logback和log4j2为例。logback实际上是springboot的…

Smart Link 和 Monitor Link应用

定义 Smart Link常用于双上行链路组网&#xff0c;提高接入的可靠性。 Monitor Link通过监视上行接口&#xff0c;使下行接口同步上行接口状态&#xff0c;起到传递故障信息的作用。 Smart Link&#xff0c;又叫做备份链路。一个Smart Link由两个接口组成&#xff0c;其中一个…

2016年408计网

这一年&#xff0c;计算机网络部分的全部考题都围绕该网络拓扑图进行。 第33题 在 OSI 参考模型中, R1、Switch、Hub 实现的最高功能层分别是() A. 2、2、1 B. 2、2、2 C. 3、2、1 D. 3、2、2 本题考察路由器、以太网交换机、集线器各自实现的最高功能层是什么题目给定R1是…

链表OJ题【环形链表】(3)

目录 环形问题的思考 ❓Q1 ❓Q2 &#x1f642;Q2 ❓Q3 ❓Q4 8.环形链表 9.环形链表Ⅱ 今天接着链表的经典问题环形问题。大家一定要自己动手多写写。&#x1f642; 快慢指针&#xff08;保持相对距离/保持相对速度&#xff09;野指针考虑为NULL的情况带环链表&#x…

Java14新增特性

前言 前面的文章&#xff0c;我们对Java9、Java10、Java11、Java12 、Java13的特性进行了介绍&#xff0c;对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 今天我们来一起看一下Java14这个版本的一些重要信息 版本介绍 Java 14…

No180.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

【图像处理:OpenCV-Python基础操作】

【图像处理&#xff1a;OpenCV-Python基础操作】 1 读取图像2 显示图像3 保存图像4 图像二值化、灰度图、彩色图&#xff0c;像素替换5 通道处理&#xff08;通道拆分、合并&#xff09;6 调整尺寸大小7 提取感兴趣区域、掩膜8 乘法、逻辑运算9 HSV色彩空间&#xff0c;获取特定…