RT-Thread Studio使用邮箱发送按键状态

我们在上一个工程(RT-Thread Studio使用轮询法检测按键)的基础上,使用邮箱发送信息给另一个线程,然后对该信息进行处理

一、邮箱的介绍

邮箱是RT-Thread中的一种线程间通信方法,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的 4 字节内容(针对 32位处理系统,指针的大小即为 4 个字节,所以一封邮件恰好能够容纳一个指针)。典型的邮箱也称作交换消息,如下图所示,线程或中断服务例程把一封4 字节长度的邮件发送到邮箱中,而一个或多个线程可以从邮箱中接收这些邮件并进行处理。(引用自RT-Thread文档中心)

二、创建按键状态邮箱

我们通过动态方法创建一个邮箱
首先,定义一个邮箱控制块结构体指针

/* 定义一个按键状态邮箱控制块结构体指针*/
rt_mailbox_t key_mailbox = RT_NULL;

然后使用动态邮箱创建函数创建一个邮箱

    /* 使用动态创建方法创建一个邮箱 */key_mailbox = rt_mb_create ("key mailbox",      /* 邮箱名称 */4,                  /* 邮箱容量,即该邮箱最多可以保存几封邮件 */RT_IPC_FLAG_FIFO);  /* 采用FIFO方式进行线程等待 */

邮箱创建成功后会返回邮箱对象的句柄,如果邮箱创建失败,则返回RT_NULL

    /* 判断邮箱是否创建成功 */if( key_mailbox != RT_NULL)rt_kprintf("key mailbox create succeed. \n");elsert_kprintf("key mailbox create failure. \n");

三、发送邮件

在按键被按下时,我们向邮箱中发送对应的邮件,使用非等待方式发送邮件

 if (rt_pin_read(PIN_WK_UP) == PIN_HIGH){/* 按键WK_UP按下,按键按下处理*/rt_kprintf("WK_UP pressed!\n");/* 发送"WK_UP pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"WK_UP pressed!");}else if (rt_pin_read(PIN_KEY0) == PIN_LOW){/* 按键KEY0按下,按键按下处理*/rt_kprintf("KEY0 pressed!\n");/* 发送"KEY0 pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"KEY0 pressed!");}else if (rt_pin_read(PIN_KEY1) == PIN_LOW){/* 按键KEY0按下,按键按下处理*/rt_kprintf("KEY1 pressed!\n");/* 发送"KEY1 pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"KEY1 pressed!");}else if (rt_pin_read(PIN_KEY2) == PIN_LOW){/* 按键KEY0按下,按键按下处理*/rt_kprintf("KEY2 pressed!\n");/* 发送"KEY2 pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"KEY2 pressed!");}

其中,邮件发送函数rt_mb_send(),第一个参数为邮箱对象句柄的结构体指针,第二个参数为邮件内容。若邮箱已满,则将该邮件直接丢弃。

四、接收邮件

为了方便,我们直接在主线程中接收邮件,然后对邮件进行处理,我们将超时时间设置为永久等待。

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>/* defined the LED0 pin: PE7 */
#define LED0_PIN    GET_PIN(E, 7)void app_key_init(void);
extern rt_mailbox_t key_mailbox;int main(void)
{int count = 1;rt_ubase_t * str;  /* 用以存放邮件 *//* set LED0 pin mode to output */rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);app_key_init();while (count++){/* 从邮箱中收取邮件 */if (rt_mb_recv(key_mailbox, (rt_ubase_t *)&str, RT_WAITING_FOREVER) == RT_EOK){rt_kprintf("main: %s \n",(char *)str);}//rt_kprintf("Hello warld! \n");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;
}

其中要特别注意的是接收邮件函数的第二个参数,需要填入的是我们用来接收邮件的变量的地址,因为我们的邮件是一个字符串指针,所以该参数应该为一个字符串指针的指针,即要在字符串指针变量前加入取地址符&

五、实现效果


可以看到,邮箱创建成功,同时在main线程中也接收到了邮件,且接收正确。

六、代码

最后,把app_key.c的代码贴上:

/** Copyright (c) 2006-2020, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2020-04-06     william       the first version*/#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>/* 使用静态方法线程创建*/
//#define STATIC_METHON#ifndef STATIC_METHON
/* 定义一个按键检测线程句柄结构体指针 */
static rt_thread_t key_thread = RT_NULL;
/* 定义一个按键状态邮箱控制块结构体指针*/
rt_mailbox_t key_mailbox = RT_NULL;
#else
/*定义一个按键检测静态线程栈*/
static char key_thread_stack[256];
/*定义一个按键检测静态线程句柄*/
static struct rt_thread key_thread;
#endif/* 获取相应的引脚编号 */
#define PIN_WK_UP   GET_PIN(C, 13)
#define PIN_KEY0    GET_PIN(D, 10)
#define PIN_KEY1    GET_PIN(D, 9)
#define PIN_KEY2    GET_PIN(D, 8)/* 按键检测线程入口函数*/
static void key_thread_entry(void *parameter)
{static rt_uint8_t key_up = 1;   /* 按键松开标志 *//* 初始化按键 */rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT);rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT);rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT);rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT);while (1){/* 检测按键是否按下 */if (key_up && ((rt_pin_read(PIN_WK_UP) == PIN_HIGH) ||(rt_pin_read(PIN_KEY0) == PIN_LOW)    ||(rt_pin_read(PIN_KEY1) == PIN_LOW)    ||(rt_pin_read(PIN_KEY2) == PIN_LOW) )       ){rt_thread_mdelay(50);   /* 延时消抖*/key_up = 0;if (rt_pin_read(PIN_WK_UP) == PIN_HIGH){/* 按键WK_UP按下,按键按下处理*/rt_kprintf("WK_UP pressed!\n");/* 发送"WK_UP pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"WK_UP pressed!");}else if (rt_pin_read(PIN_KEY0) == PIN_LOW){/* 按键KEY0按下,按键按下处理*/rt_kprintf("KEY0 pressed!\n");/* 发送"KEY0 pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"KEY0 pressed!");}else if (rt_pin_read(PIN_KEY1) == PIN_LOW){/* 按键KEY0按下,按键按下处理*/rt_kprintf("KEY1 pressed!\n");/* 发送"KEY1 pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"KEY1 pressed!");}else if (rt_pin_read(PIN_KEY2) == PIN_LOW){/* 按键KEY0按下,按键按下处理*/rt_kprintf("KEY2 pressed!\n");/* 发送"KEY2 pressed!"字符串地址到key_mailbox邮箱中 */rt_mb_send(key_mailbox, (rt_uint32_t)&"KEY2 pressed!");}}else if((rt_pin_read(PIN_WK_UP) == PIN_LOW) &&(rt_pin_read(PIN_KEY0) == PIN_HIGH) &&(rt_pin_read(PIN_KEY1) == PIN_HIGH) &&(rt_pin_read(PIN_KEY2) == PIN_HIGH)     ){key_up = 1;     /* 按键已松开 */}rt_thread_mdelay(100);}}void app_key_init(void)
{rt_err_t rt_err;
#ifndef STATIC_METHON/* 创建按键检测线程*/key_thread = rt_thread_create(  "key thread",       /* 线程的名称 */key_thread_entry,   /* 线程入口函数 */RT_NULL,            /* 线程入口函数的参数   */256,                /* 线程栈大小,单位是字节  */5,                  /* 线程的优先级,数值越小优先级越高*/10);                /* 线程的时间片大小 *//* 如果获得线程控制块,启动这个线程 */if (key_thread != RT_NULL)rt_err = rt_thread_startup(key_thread);elsert_kprintf("key thread create failure !!! \n");/* 判断线程是否创建成功 */if( rt_err == RT_EOK)rt_kprintf("key thread startup ok. \n");elsert_kprintf("key thread startup err. \n");/* 使用动态创建方法创建一个邮箱 */key_mailbox = rt_mb_create ("key mailbox",      /* 邮箱名称 */4,                  /* 邮箱容量,即该邮箱最多可以保存几封邮件 */RT_IPC_FLAG_FIFO);  /* 采用FIFO方式进行线程等待 *//* 判断邮箱是否创建成功 */if( key_mailbox != RT_NULL)rt_kprintf("key mailbox create succeed. \n");elsert_kprintf("key mailbox create failure. \n");#else/* 初始化按键检测线程,名称是thread2,入口是thread2_entry */rt_err = rt_thread_init(&key_thread,                /* 线程句柄 */"key thread",                /* 线程的名称 */key_thread_entry,            /* 线程入口函数 */RT_NULL,                     /* 线程入口函数的参数   */&key_thread_stack[0],        /* 线程栈起始地址*/sizeof(key_thread_stack),    /* 线程栈大小,单位是字节*/5,                           /* 线程的优先级,数值越小优先级越高*/10);                         /* 线程的时间片大小 *//* 如果线程创建成功,启动这个线程 */if (rt_err == RT_EOK)rt_err = rt_thread_startup(&key_thread);elsert_kprintf("key thread init failure !!! \n");/* 判断线程是否启动成功 */if( rt_err == RT_EOK)rt_kprintf("key thread startup ok. \n");elsert_kprintf("key thread startup err. \n");
#endif
}

RT-Thread Studio入门(4)— 使用邮箱发送按键状态相关推荐

  1. rt thread studio使用QBOOT和片外flash实现OTA升级

    我们这里要使用单片机外部flash作为OTA的下载分区,外部flash硬件连接关系 PB3-->SPI3_CLK PB4-->SPI3_MISO PB5-->SPI3_MOSI PE ...

  2. RT Thread Studio 配置IIC并读取AS5600角度

    RT Thread Studio 配置IIC并读取AS5600角度 一.RT Thread Studio 配置IIC 1.在RT Thread Seting 中开启IIC功能 并保存 一定要保存才能更 ...

  3. RT Thread利用STM32CUBEMX和RT Thread studio来创建模板工程

    (1)RT Thread利用STM32CUBEMX来创建模板工程 1.参考文档: 基于 CubeMX 移植 RT-Thread Nano:RT-Thread 文档中心 注意:串口2必须使能异步模式(启 ...

  4. xpt 2046的触摸屏 rt thread设备驱动框架

    1 基于rtt 开发触摸屏驱动 准备使用rtt 框架 , 驱动xpt 2046的触摸屏, 翻阅大量资料发现, 大部分文章强调的是时序图, 而且很多代码要么直接操作寄存器, 要么是io 口模拟, 只能用 ...

  5. RT Thread Free Modbus移植问题整理

    RT Thread Free Modbus移植问题整理 问题描述: 在读写寄存器中,写数据正常,只能读1个寄存器的值,多个值会异常. 在移植过程中发现串口(或RS485)数据接收长度异常. 一.环境描 ...

  6. Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32

    1.前言     [2014年4月重写该博文]     经过若干时间的努力终于搞定了STM32+LwIP和yeelink平台的数据互通,在学习的过程中大部分时间花在以太网协议栈学习上,但是在RT Th ...

  7. RT Thread之 Uart2 操作

    官网连接:https://docs.rt-thread.org/#/rt-thread-version/rt-thread-standard/programming-manual/device/uar ...

  8. 基于rt thread smart构建EtherCAT主站

    我把源码开源到到了gitee,https://gitee.com/rathon/rt-thread-smart-soem 有兴趣的去可以下载下来跑一下 软件工程推荐用vscode 打开.rt thre ...

  9. stm32f407单片机rt thread 片外spi flash OTA升级配置示例

    参考地址https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/ 第一步,生成Boot ...

最新文章

  1. 我对软件行业及大数据的理解
  2. 自定义log4j2配置文件地址
  3. hubbledotnet 远程连接提示:无法从传输连接中读取数据:远程主机强迫关闭一个现有的连接...
  4. Memcached - In Action
  5. 【译】Why Decentralized AI Matters Part I: Economics and Enablers
  6. 这都2021年了,还不会Feign性能调优?Feign性能调优之gzip压缩实现-自娱自乐篇
  7. 交换系统接媒体服务器,基于软交换的媒体服务器的设计与实现
  8. android平台的s5pc110触摸屏驱动分析
  9. matlibplot 一张图画多个曲线_热重法实验条件设定与曲线解析 第53部分 热重实验方案设计与曲线解析常见问题之热重仪选择中常见问题分析...
  10. 使用devops的团队_具有DevOps心态的团队的蓝图
  11. Ubuntu,QT5连接MySQL
  12. 有没有不用加班的程序员?如何衡量程序员的工作量?
  13. 服务器系统管理维护,服务器操作系统的管理维护
  14. Python-random函数用法
  15. R及R Studio下载及简单介绍(界面+R语言)
  16. 清华物理系与计算机系哪个好,兰州大学现在还有物理系吗?
  17. VMware安装centOS镜像
  18. 1. Java EE简介 - JavaEE基础系列
  19. 《强化学习》学习(一)——强化学习的来源:学习
  20. c 编程替换语言,巧用typedef替换类型名称

热门文章

  1. Quartz动态改变Cron表达式,来实现动态执行Spring定时任务
  2. 从首个智能产业经济带,看“工业河北”如何牵手百度走向“科技河北”
  3. python异常处理输入不是整数_Python异常处理
  4. Laravel上传文件时getRealPath()返回public文件夹
  5. 使用MQTT实现简单命令控制
  6. 销售行业如何用智能名片高效拓客?
  7. 2022年第十三届蓝桥杯省赛C++B组
  8. 良好的沟通是团队协作的基石
  9. 公务员—行测总体分析
  10. 去水印无限代理版本小程序源码+无授权+去水印解析接口