Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
[第三期 空气质量分析仪]第3周作业
发布于 2019-10-31 23:05:14 浏览:918
订阅该版
* 本帖最后由 yangdehuan 于 2019-10-31 23:27 编辑 * 第三周目标: 1、实现异步日志(熟悉 IPC:邮箱的使用) 2、系统跑起来(熟悉 IPC:事件集的使用) 目标1:**邮箱的使用** 在使用前先了解邮箱的管理方式:![VJL~48A4[PO~M)HZIBD(Y%K.png](/uploads/201910/31/215051utuajovoqvazqoj0.png)详细资料要看[线程间通信](https://www.rt-thread.org/document/site/programming-manual/ipc2/ipc2/) ①、创建邮箱:分两种方式创建邮箱,一种是动态创建邮箱还有就是静态创建。动态创建邮箱对象时会先从对象管理器中分配一个邮箱对象,然后给邮箱动态分配一块内存空间用来存放邮件。静态创建邮箱跟动态创建邮箱类似与动态创建邮箱不同的是,静态邮箱对象的内存是在系统编译时由编译器分配的,一般放于读写数据段或未初始化数据段中,其余的初始化工作与动态创建邮箱时相同。 ②、发送邮件:线程或者中断服务程序可以通过邮箱给其他线程发送邮件。“例如:A线程需要传递数据到B线程” ③、邮件接收:查询在指定时间内有无邮件。 ④、删除邮箱:不需要使用时删除邮箱回收内存。 目标1实现任务 : ```#include
#include
#include
#include "mylog.h" /* 用于放邮件的内存池 */ //static char mb_pool[128]; /* 邮箱控制块 */ rt_mailbox_t mb; /*定义传送数据结构体*/ typedef struct msg{ char* tag; void* data; }mbMsg; /** * 函数名:mylog(char *tag,rt_uint32_t data) * 描述: //向mb对象的句柄发送邮件 * 参数: 数据类型 数据大小 * * 返回: 无 */ void mylog(char *tag,void* data) { mbMsg *mb_data_send; //定义结构体 mb_data_send = (mbMsg*)rt_malloc(sizeof(mbMsg)); //申请内存 mb_data_send->tag = tag; //数据类型 mb_data_send->data = data; //数据大小 rt_mb_send(mb,(rt_ubase_t)mb_data_send); //发送邮件 rt_free(mb_data_send); //释放内存 } /** * 函数名:mylog_entry(void *parameter) * 描述: 邮箱线程,接收邮件消息并打印 * 参数: parameter * * 返回: 无 */ void mylog_entry(void *paran) { mbMsg *mb_data_send; //定义结构体 while(1) { if(rt_mb_recv (mb,(rt_ubase_t *)&mb_data_send, RT_WAITING_FOREVER) == RT_EOK) { rt_kprintf("[%s] data is:%s
",mb_data_send->tag , mb_data_send->data); } } } /** * 函数名:mylog_init() * 描述: 创建邮箱,创建邮箱接收线程 * 参数: parameter * * 返回: 无 */ rt_err_t mylog_init(void) { // // rt_err_t result; //邮箱标志位 rt_thread_t tid3 = RT_NULL;//线程结构体 //-----------------------------------创建邮箱------------------- /*静态创建邮箱*/ // result = rt_mb_init(&mb, //邮箱对象的句柄 // "mbt", //邮箱名称 // &mb_pool[0], //缓冲区指针 // sizeof(mb_pool) / 4, //邮箱容量 // RT_IPC_FLAG_FIFO); //先进先出模式 /*动态创建邮箱*/ mb = rt_mb_create("mbt", //邮箱名称 128, //邮箱容量 RT_IPC_FLAG_FIFO); //先进先出模式 if(RT_NULL == mb) //创建消息队列失败 { rt_kprintf("创建动态邮箱失败
"); //打印创建失败 return -RT_ERROR; //返回错误标志 } rt_kprintf("创建动态邮箱成功
"); //打印创建成功 //----------------------------------创建动态邮箱接收线程-------------- tid3 = rt_thread_create("mylog", //线程名字 mylog_entry, //线程函数 RT_NULL, //线程入口参数 1024, //线程栈大小 22, //优先级 20); //时间片 ```目标1实现的效果:与目标二同时实现。 ![MGVQ`{_VIT7]X]Y)C13N]$V.png](https://oss-club.rt-thread.org/uploads/201910/31/223106qlvxvxyv3yu3z33x.png) ![1BP93CBT(S232535PS7F~GL.png](https://oss-club.rt-thread.org/uploads/201910/31/225745sabd8rdzrunbvvdm.png)
查看更多
4
个回答
默认排序
按发布时间排序
yangdehuan
2019-10-31
这家伙很懒,什么也没写!
键盘线程发送状态事件集给SHT20传感器 ``` #include "key.h" #include "temp_humi.h" #define KEY1_PIN GET_PIN(C, 11) //注册PIN #define KEY2_PIN GET_PIN(C, 12) #define KEY3_PIN GET_PIN(D, 2 ) #define KEY4_PIN GET_PIN(C, 13) rt_bool_t key_falg = 0; //按键触发标志位 rt_bool_t key_data = 0; //键盘奇偶标志位 void key1_cb(void *args) //键盘中断回调函数 { key_falg = 1; rt_thread_resume(args); //恢复键盘线程"恢复线程到就绪状态" } void key2_cb(void *args) //键盘中断回调函数 { key_falg = 1; rt_thread_resume(args); //恢复键盘线程"恢复线程到就绪状态" } void key3_cb(void *args) //键盘中断回调函数 { key_falg = 1; rt_thread_resume(args); //恢复键盘线程"恢复线程到就绪状态" } void key4_cb(void *args) //键盘中断回调函数 { key_falg = 1; rt_thread_resume(args); //恢复键盘线程"恢复线程到就绪状态" } /** * 函数名:Read_Key_Data() * 描述: 键盘数据读取"读取IO电平" * 参数: 无 * * 返回: key_pin_data->返回4个键盘的状态 */ rt_uint8_t Read_Key_Data(void) { rt_int8_t key_pin_data; key_pin_data = rt_pin_read(KEY4_PIN); key_pin_data <<=1; key_pin_data |= rt_pin_read(KEY3_PIN); key_pin_data <<=1; key_pin_data |= rt_pin_read(KEY2_PIN); key_pin_data <<=1; key_pin_data |= rt_pin_read(KEY1_PIN); return key_pin_data; } /*------------------------------创建键盘线程---------------------------*/ void key_entry(void *param) { rt_int8_t key_pin_data; rt_thread_t key_tid; while(1) { if(key_falg == 1) { key_falg = 0;//清除按键中断触发标志位 /*关闭按键中断*/ rt_pin_irq_enable(KEY1_PIN,PIN_IRQ_DISABLE); rt_pin_irq_enable(KEY2_PIN,PIN_IRQ_DISABLE); rt_pin_irq_enable(KEY3_PIN,PIN_IRQ_DISABLE); rt_pin_irq_enable(KEY4_PIN,PIN_IRQ_DISABLE); /*读取按键数据*/ key_pin_data = Read_Key_Data(); /*延时滤波*/ rt_thread_mdelay(10); switch(key_pin_data)//按键识别 { case 0x0E: if(key_data & 0x01) { key_data &= 0xfe; rt_event_send(sht20_event, SHT20_EVENT_FLAG2); }else{ key_data |= 0x01; rt_event_send(sht20_event, SHT20_EVENT_FLAG1); } break; default: break; } for(;0x0f != Read_Key_Data();)//等待按键抬起 { rt_thread_mdelay(10); } /*开启按键中断*/ rt_pin_irq_enable(KEY1_PIN,PIN_IRQ_ENABLE); rt_pin_irq_enable(KEY2_PIN,PIN_IRQ_ENABLE); rt_pin_irq_enable(KEY3_PIN,PIN_IRQ_ENABLE); rt_pin_irq_enable(KEY4_PIN,PIN_IRQ_ENABLE); } key_tid = rt_thread_self();//获取键盘线程句柄"获得当前线程" rt_thread_suspend(key_tid);//挂起键盘线程"该函数将挂起指定的线程。" } } /** * 函数名:key_init() * 描述: 初始化键盘 * 参数: * * 返回: RT_EOK ->初始化成功 -RT_ERROR->初始化失败 */ rt_err_t key_init(void) { rt_thread_t key_tid; /*动态创建按键线程*/ key_tid = rt_thread_create("irq_key", key_entry, RT_NULL, 500, 23, 10); if(key_tid == RT_NULL)//如果创建失败则打印失败信息并返回 { rt_kprintf("初始化外部中断键盘失败\n"); return -RT_ERROR; } rt_thread_startup(key_tid);//启动键盘线程"启动一个线程并将其放入系统就绪队列" rt_pin_mode(KEY1_PIN,PIN_MODE_INPUT_PULLUP); //设置键盘引脚模式 rt_pin_attach_irq(KEY1_PIN,PIN_IRQ_MODE_FALLING , key1_cb,key_tid); //绑定引脚中断回调函数(下降沿触发模式 ) rt_pin_irq_enable(KEY1_PIN,PIN_IRQ_ENABLE); //启动引脚中断 rt_pin_mode(KEY2_PIN,PIN_MODE_INPUT_PULLUP); //设置键盘引脚模式 rt_pin_attach_irq(KEY2_PIN,PIN_IRQ_MODE_FALLING , key2_cb,key_tid); //绑定引脚中断回调函数(下降沿触发模式 ) rt_pin_irq_enable(KEY2_PIN,PIN_IRQ_ENABLE); rt_pin_mode(KEY3_PIN,PIN_MODE_INPUT_PULLUP); //设置键盘引脚模式 rt_pin_attach_irq(KEY3_PIN,PIN_IRQ_MODE_FALLING , key3_cb,key_tid); //绑定引脚中断回调函数(下降沿触发模式 ) rt_pin_irq_enable(KEY3_PIN,PIN_IRQ_ENABLE); rt_pin_mode(KEY4_PIN,PIN_MODE_INPUT_PULLUP); //设置键盘引脚模式 rt_pin_attach_irq(KEY4_PIN,PIN_IRQ_MODE_FALLING , key4_cb,key_tid); //绑定引脚中断回调函数(下降沿触发模式 ) rt_pin_irq_enable(KEY4_PIN,PIN_IRQ_ENABLE); return RT_EOK; } ```
yangdehuan
2019-10-31
这家伙很懒,什么也没写!
[i=s] 本帖最后由 yangdehuan 于 2019-10-31 23:23 编辑 [/i] SHT20传感器接收到按键事件“奇数:读取温湿度”,“偶数:停止读取温湿度”。SHT20传感器发送事件给LED线程“显示传感器状态”,如果读取数据成功发送邮件给异步日志线程
yangdehuan
2019-10-31
这家伙很懒,什么也没写!
``` #include "temp_humi.h" #include "mylog.h" #include "led.h" #include
/*sht20 registers define */ #define TRIG_TEMP_MEASUREMENT_HM 0xE3 #define TRIG_HUMI_MEASUREMENT_HM 0xE5 #define TRIG_TEMP_MEASUREMENT_POLL 0xF3 #define TRIG_HUMI_MEASUREMENT_POLL 0xF5 #define USER_REG_W 0xE6 #define USER_REG_R 0xE7 #define SOFT_RESET 0xFE #define SHT20_ADDR 0x40 #define SHT20_I2C_BUS_NAME "i2c1" /* 传感器连接的I2C总线设备名称 */ struct rt_event *sht20_event;//sht20事件集句柄 rt_bool_t sht20_read_start; rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf) { struct rt_i2c_msg msgs[2]; msgs[0].addr = SHT20_ADDR; msgs[0].flags = RT_I2C_WR; msgs[0].buf = ® msgs[0].len = 1; msgs[1].addr = SHT20_ADDR; msgs[1].flags = RT_I2C_RD; msgs[1].buf = buf; msgs[1].len = len; if (rt_i2c_transfer(bus, msgs, 2) == 2) { return RT_EOK; } else { return -RT_ERROR; } } rt_err_t write_regs(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t buf) { struct rt_i2c_msg msgs[2]; msgs[0].addr = SHT20_ADDR ; msgs[0].flags = RT_I2C_WR; msgs[0].buf = ® msgs[0].len = 1; msgs[1].addr = SHT20_ADDR; msgs[1].flags = RT_I2C_WR; msgs[1].buf = &buf; msgs[1].len = 1; if (rt_i2c_transfer(bus, msgs, 2) == 2) { return RT_EOK; } else { return -RT_ERROR; } } rt_device_t SHT20_hw_init(const char *i2c_bus_name) { struct rt_i2c_bus_device *bus; /* 查找I2C总线设备,获取I2C总线设备句柄 */ bus = (struct rt_i2c_bus_device*)rt_i2c_bus_device_find(i2c_bus_name); if (bus == RT_NULL) { rt_kprintf("获取I2C总线设备句柄失败\n"); return RT_NULL; } rt_kprintf("获取I2C总线设备句柄成功\n"); return (rt_device_t)bus; } float SHT20_read_temp(struct rt_i2c_bus_device *bus) { rt_uint8_t temp[2]; float current_temp = -46.85; if(RT_EOK == read_regs(bus,TRIG_TEMP_MEASUREMENT_HM,2,temp)) { current_temp = -46.85 + (temp[1] | temp[0] << 8) * 175.72 / (1 << 16); } return current_temp; } float SHT20_read_humi(struct rt_i2c_bus_device *bus) { rt_uint8_t temp[2]; float current_humi = 0.00; if(RT_EOK == read_regs(bus,TRIG_HUMI_MEASUREMENT_HM,2,temp)) { current_humi = -6 + (temp[1] | temp[0] << 8) * 125.0 / (1 << 16); }else{ } return current_humi; } rt_err_t SHT20_reset(struct rt_i2c_bus_device *bus) { struct rt_i2c_msg msgs[1]; rt_uint8_t SHT20_rest_Falg[1]; SHT20_rest_Falg[0] = SOFT_RESET; msgs[0].addr = SHT20_ADDR; msgs[0].flags = RT_I2C_WR; msgs[0].buf = SHT20_rest_Falg; msgs[0].len = 1; /* 调用I2C设备接口传输数据 */ if (rt_i2c_transfer(bus, msgs, 1) == 1) { rt_kprintf("SHT20复位成功\n"); return RT_EOK; }else{ rt_kprintf("SHT20复位失败\n"); return -RT_ERROR; } } rt_err_t SHT20_read_user(struct rt_i2c_bus_device *bus,rt_uint8_t *buf) { if( read_regs(bus,USER_REG_R,1,buf) == RT_EOK) { return RT_EOK; } return -RT_ERROR; } rt_err_t SHT20_write_user(struct rt_i2c_bus_device *bus,rt_uint8_t STH20_USER_DATA) { rt_uint8_t write_user_Falg[1]; if(SHT20_read_user(bus,write_user_Falg) != -RT_ERROR) { if(STH20_USER_DATA == write_user_Falg[0]) { rt_kprintf("SHT20用户寄存器与写入数据相等 \n"); return RT_EOK; } if(write_regs(bus,USER_REG_W,1,STH20_USER_DATA) == RT_EOK) { rt_kprintf("SHT20写用户寄存器成功 \n"); return RT_EOK; }else{ rt_kprintf("SHT20写用户寄存器失败 \n"); return -RT_ERROR; } }else { rt_kprintf("SHT20写用户寄存器失败 \n"); return -RT_ERROR; } } //*************************************创建线程**************************************** void temp_humi_entry(void *param) { float sht20_temperature_Date = 0.00; //温度缓存 float sht20_humidity_Date = 0.00; //湿度缓存 char str[2]; //字符缓存 while (1) { /*读取按键事件*/ if(rt_event_recv(sht20_event,SHT20_EVENT_FLAG1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 10,RT_NULL) == RT_EOK ) { sht20_read_start = 1; } /*读取按键事件*/ if(rt_event_recv(sht20_event,SHT20_EVENT_FLAG2, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 10,RT_NULL) == RT_EOK ) { sht20_read_start = 0; /*如果按键是事件是偶数*/ rt_event_send(&alarm_event, EVENT_FLAG3);//发送事件 } /*如果按键是事件是奇数*/ if(sht20_read_start == 1)//启动温度读取 { sht20_temperature_Date = SHT20_read_temp(param); //读取温度 sht20_humidity_Date = SHT20_read_humi(param); //读取湿度 if((sht20_temperature_Date != 0.0)&&(sht20_humidity_Date != 0.0)) //判断温湿度是否读取成功 { rt_event_send(&alarm_event, EVENT_FLAG1); //发送 if((sht20_temperature_Date >= 27)||(sht20_humidity_Date >= 50))//如果温度大于27°C或湿度小于50发送报警事件 { rt_event_send(&alarm_event, EVENT_FLAG2); //发送事件 } sprintf(str, "%.2f", sht20_temperature_Date); //把浮点数转成字符打印字符缓存器(保留两位小数) mylog("sht20温度",&str); sprintf(str, "%.2f", sht20_humidity_Date); //把浮点数转成字符打印字符缓存器(保留两位小数) mylog("sht20湿度",&str); }else{ rt_kprintf("sht20读取温湿度失败: \n\n"); } rt_thread_mdelay(1000); //延时(出让CPU资源) } } } rt_err_t temp_humi_init(void) { struct rt_i2c_bus_device *bus; rt_thread_t tid1 = RT_NULL; /*动态创建温湿度事件*/ sht20_event = rt_event_create("sht20_event", RT_IPC_FLAG_FIFO); if(sht20_event == RT_NULL)//如果创建失败打印失败信息并返回 { rt_kprintf("创建温湿度事件失败\n"); return -RT_ERROR; } bus = (struct rt_i2c_bus_device *)SHT20_hw_init(SHT20_I2C_BUS_NAME);//初始化I2C总线 /*动态创建温湿度线程*/ tid1 = rt_thread_create("temp_humi1", temp_humi_entry, bus, 500, 24, 15); if(tid1 == RT_NULL) { rt_kprintf("创建温湿度线程失败\n"); return -RT_ERROR; } if(rt_thread_startup(tid1) != RT_EOK )//启动线程 { rt_kprintf("启动温湿度检测线程失败\n"); return -RT_ERROR; } return RT_EOK; } ```
yangdehuan
2019-10-31
这家伙很懒,什么也没写!
LED线程接收来自SHT20线程并显示 ``` #include "led.h" #define LED0_RED GET_PIN(C, 7) struct rt_event alarm_event;//报警事件集句柄 /** * 函数名:led_on() * 描述: 点亮LED * 参数: 无 * * 返回: 无 */ void led_on(void) { rt_pin_write(LED0_RED, PIN_LOW); //点亮 led } /** * 函数名:led_off() * 描述: 关闭LED * 参数: 无 * * 返回: 无 */ void led_off(void) { rt_pin_write(LED0_RED, PIN_HIGH); //熄灭 led } /** * 函数名:led_blink(rt_int32_t led_delay,rt_bool_t Start_stop) * 描述: LED闪烁 * 参数: led_delay->闪烁时间 Start_stop->闪烁的次数 * * 返回: 无 */ void led_blink(rt_int32_t led_delay,rt_bool_t Start_stop) { while(Start_stop) { Start_stop --; led_on(); rt_thread_mdelay(led_delay); led_off(); rt_thread_mdelay(led_delay); } } /*----------------------------创建LED线程--------------------------*/ void led_entry(void *param) { while(1) { if(rt_event_recv(&alarm_event,EVENT_FLAG1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 100,RT_NULL) == RT_EOK ) { led_blink(200,1);//闪烁一次 } if(rt_event_recv(&alarm_event,EVENT_FLAG2, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 100,RT_NULL) == RT_EOK ) { led_on();//led亮 } if(rt_event_recv(&alarm_event,EVENT_FLAG3, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 100,RT_NULL) == RT_EOK ) { led_off();//led灭 } rt_thread_mdelay(100); } } /** * 函数名:led_init() * 描述: LED初始化 * 参数: 无 * * 返回: RT_EOK->初始化成功 -RT_ERROR ->初始化失败 */ rt_err_t led_init(void) { rt_err_t result; rt_thread_t led_tid; rt_pin_write (LED0_RED , PIN_HIGH); //LED置高点位(防止启动时闪烁) rt_pin_mode (LED0_RED ,PIN_MODE_OUTPUT);//设置LED模式 result = rt_event_init(&alarm_event, //事件集对象句柄 "event", //事件集名称 RT_IPC_FLAG_FIFO);//先进先出模式 if(result != RT_EOK) //如果创建失败 { rt_kprintf("创建LED接收事件集失败\n"); return -RT_ERROR; } rt_kprintf("创建LED接收事件集成功\n"); led_tid = rt_thread_create("led", //线程名称 led_entry, //线程入口函数 RT_NULL, //线程入口函数参数 1024, //线程栈大小 1, //线程优先级 10); //线程时间片大小 if(led_tid == RT_NULL) { rt_kprintf("创建LED接收事件集线程失败\n"); return -RT_ERROR; } rt_kprintf("创建LED接收事件集线程成功\n"); if(rt_thread_startup(led_tid) != RT_EOK)//启动LED接收事件集线程如果失败 { rt_thread_delete(led_tid); //删除LED接收事件集线程 rt_kprintf("启动LED接收事件集线程失败\n"); return -RT_ERROR; } rt_kprintf("启动LED接收事件集线程成功\n"); return RT_EOK; } ```
撰写答案
登录
注册新账号
关注者
0
被浏览
918
关于作者
yangdehuan
这家伙很懒,什么也没写!
提问
6
回答
15
被采纳
1
关注TA
发私信
相关问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
开源共生 商业共赢 | RT-Thread 2024开发者大会议程正式发布!
2
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
3
RT-Thread EtherKit开源以太网硬件正式发布
4
如何在master上的BSP中添加配置yml文件
5
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
a1012112796
20
个答案
3
次被采纳
张世争
12
个答案
3
次被采纳
踩姑娘的小蘑菇
7
个答案
3
次被采纳
rv666
9
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
6
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部