Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
[第二期 空气质量分析仪] 第3周作业_系统跑起来
发布于 2019-09-08 15:29:57 浏览:952
订阅该版
[tocm] # 第三周 实现异步日志、整个系统跑起来 第三周了,刚好周末抽出两小时把作业做完,也算是入门最后一个作业啦,好开森要毕业了,终于尝试用RTT做了一个小项目。 本周的作业主要有两个为以下内容: 1、实现异步日志(熟悉 IPC:邮箱的使用) 2、系统跑起来(熟悉 IPC:事件集的使用) > **任务1 实现异步日志** 这个任务是将传感器模块线程中打印数据所使用到的 rt_kprintf() 使用 mylog() 代替,实现异步打印。主要学习的是线程间通讯,使用邮箱来实现此功能。**** ``` void mylog_init(void) //动态线程分配 { rt_err_t result = RT_NULL; rt_thread_t tid = RT_NULL; result = rt_mb_init(&mb,"mylog",&mb_pool[0],sizeof(mb_pool) / 4,RT_IPC_FLAG_FIFO); if(result != RT_NULL) { rt_kprintf("mylog init success
"); } /* 创建线程 1 */ tid = rt_thread_create("app_mylog", mylog_entry, (void*)1, APP_MYLOG_STACK_SIZE, APP_MYLOG_THREAD_PRIORITY, APP_MYLOG_TIMESLICE); if (tid != RT_NULL) { rt_thread_startup(tid); } } ``` 上面是mylog的初始化,新建立一个邮箱,一直死等邮箱到来 ``` void mylog_entry(void *param) { char *str; while(1) { if(rt_mb_recv(&mb,(rt_ubase_t *)&str, RT_WAITING_FOREVER) == RT_EOK) { rt_kprintf("%s
",str); } } } ``` 一直在mylog线程内等待接收邮件,接收完成后打印。 ``` void mylog(char* TAG, char* data) { char str[128]; strcpy(str,TAG); strcat(str,"--->"); strcat(str,data); rt_mb_send(&mb,(rt_ubase_t)&str); } ``` 其他线程可以调用mylog输入 输入参数为字符串,其中,TAG可以自定义标签主要区分打印内容,在mylog中发送邮件交给mylog线程来打印。 > **任务2 系统跑起来** 之前做的系统还只是各个模块能运行,模块间没关联。现在要做的就是实现整个体统:。 每次系统中只有一种传感器模块在获取数据,每秒获取一次。key1 按下(奇数次),温湿度传感器开始读数据。当数据正常时,在每秒的开始,闪烁两下,表示正常读取数据。当读取的数据超过设定的范围时,led 一直常亮,表示报警。key1 再次按下(偶数次),温湿度传感器停止读数据。led 熄灭**** 这个任务主要也是为了实现线程间通讯的方式,当然老师推荐使用事件集,来实现此功能。 代码实现 ``` void led_init(void) //动态线程分配 { rt_thread_t tid = RT_NULL; rt_err_t result; alert_info_init(); rt_timer_init(&alert_led, "alert_led", led_link_CallBack, RT_NULL, 200, RT_TIMER_FLAG_PERIODIC); rt_timer_start(&alert_led); /* 初始化事件对象 */ result = rt_event_init(&event, "event", RT_IPC_FLAG_FIFO); if (result != RT_EOK) { rt_kprintf("init event failed.
"); } /* 创建线程 1 */ tid = rt_thread_create("app_led", led_entry, (void*)1, APP_LED_STACK_SIZE, APP_LED_THREAD_PRIORITY, APP_LED_TIMESLICE); //优先级为 5 main的优先级为 10 finish优先级为 20 时间片轮为10tick if (tid != RT_NULL) { rt_thread_startup(tid); } } ``` 启用了一个LED灯的线程,在这个线程内主要是接收事件,若发生了以下任意事件,则会进行时间触发。 ``` #define EVENT_FLAG_TEMP (1 << 1) #define EVENT_FLAG_TEMP_REC (1 << 2) #define EVENT_FLAG_HUMI (1 << 3) #define EVENT_FLAG_HUMI_REC (1 << 4) #define EVENT_FLAG_PM25 (1 << 5) #define EVENT_FLAG_PM25_REC (1 << 6) #define EVENT_FLAG_HCHO (1 << 7) #define EVENT_FLAG_HCHO_REC (1 << 8) ``` 其中后缀为REC的为正常事件,表示数据没有到达告警阀值 ``` void led_bink(uint32_t value) { switch(value) { case EVENT_FLAG_TEMP : mylog("APP_LED","TEMP ALERT"); Atemp = _ALERT; break; case EVENT_FLAG_TEMP_REC : Atemp = _NORMAL; break; case EVENT_FLAG_HUMI : mylog("APP_LED","HUMI ALERT"); Ahumi = _ALERT; break; case EVENT_FLAG_HUMI_REC : Ahumi = _NORMAL; break; case EVENT_FLAG_PM25 : mylog("APP_LED","PM25 ALERT"); Apm25 = _ALERT; break; case EVENT_FLAG_PM25_REC : Apm25 = _NORMAL; break; case EVENT_FLAG_HCHO : mylog("APP_LED","HCHO ALERT"); Ahcho = _ALERT; break; case EVENT_FLAG_HCHO_REC : Ahcho = _NORMAL; break; default : break; } } void led_entry(void *param) { rt_uint32_t e; while(1) { if (rt_event_recv(&event, ( EVENT_FLAG_TEMP | EVENT_FLAG_TEMP_REC | EVENT_FLAG_HUMI | EVENT_FLAG_HUMI_REC | EVENT_FLAG_PM25 | EVENT_FLAG_PM25_REC | EVENT_FLAG_HCHO | EVENT_FLAG_HCHO), RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &e) == RT_EOK) { led_bink(e); } } } ``` 上述函数若收到告警事件并使用mylog进行打印,然后相应的告警flag位,_ALERT,然后初始化的soft time会检测到此flag,正常状态下为200ms闪烁,告警状态下常亮。 ``` void led_link_CallBack(void *value) { static uint8_t led_s[4]= {RT_FALSE,RT_FALSE,RT_FALSE,RT_FALSE}; rt_base_t led_c[4] = {PIN_LED_R,PIN_LED_B,PIN_LED_G,PIN_LED_O}; if(Sys.Temp_State == _RUN) { if(Atemp == _NORMAL) { led_s[0] = ~led_s[0]; rt_pin_write(led_c[0], led_s[0]); } else { rt_pin_write(led_c[0], RT_FALSE); } } if(Sys.Humi_State == _RUN) { if(Ahumi == _NORMAL) { led_s[1] = ~led_s[1]; rt_pin_write(led_c[1], led_s[1]); } else { rt_pin_write(led_c[1], RT_FALSE); } } if(Sys.PM2_5_State == _RUN) { if(Apm25 == _NORMAL) { led_s[2] = ~led_s[2]; rt_pin_write(led_c[2], led_s[2]); } else { rt_pin_write(led_c[2], RT_FALSE); } } if(Sys.HCHO_State == _RUN) { if(Ahcho == _NORMAL) { led_s[3] = ~led_s[3]; rt_pin_write(led_c[3], led_s[3]); } else { rt_pin_write(led_c[3], RT_FALSE); } } } ``` 然后,按键带有使能传感器采集奇数为开启采集,偶数为关闭采集,之前使用1个按键的回调这个使用了4个按键回调,不过,潘多拉板子up键是上升沿中断,其他按键是下降沿中断,回调函数内对应的flag置位,按键内的flag变量是全局变量,这个考虑的是按键触发次数比较少,因此没有使用互斥保护全局变量,代码如下: ``` void key_init(void) { /* 按键0引脚为输入模式 */ rt_pin_mode(PIN_KEY_UP, PIN_MODE_INPUT); /* 绑定中断,下降沿模式,回调函数名为beep_on */ rt_pin_attach_irq(PIN_KEY_UP, PIN_IRQ_MODE_RISING, key_up_CallBack, RT_NULL); /* 使能中断 */ rt_pin_irq_enable(PIN_KEY_UP, PIN_IRQ_ENABLE); rt_pin_mode(PIN_HUMI_KEY2, PIN_MODE_INPUT); rt_pin_attach_irq(PIN_HUMI_KEY2, PIN_IRQ_MODE_FALLING, key_humi_CallBack, RT_NULL); rt_pin_irq_enable(PIN_HUMI_KEY2, PIN_IRQ_ENABLE); rt_pin_mode(PIN_PM25_KEY1, PIN_MODE_INPUT); rt_pin_attach_irq(PIN_PM25_KEY1, PIN_IRQ_MODE_FALLING, key_pm25_CallBack, RT_NULL); rt_pin_irq_enable(PIN_PM25_KEY1, PIN_IRQ_ENABLE); rt_pin_mode(PIN_HCHO_KEY0, PIN_MODE_INPUT); rt_pin_attach_irq(PIN_HCHO_KEY0, PIN_IRQ_MODE_FALLING, key_hcho_CallBack, RT_NULL); rt_pin_irq_enable(PIN_HCHO_KEY0, PIN_IRQ_ENABLE); } ``` ``` if(Sys.Temp_State == _RUN) { temperature = aht10_read_temperature(dev); if(temperature >= 30) { rt_event_send(&event, EVENT_FLAG_TEMP); } else { rt_event_send(&event, EVENT_FLAG_TEMP_REC); } rt_sprintf(str,"temp: %d.%d",(int)temperature, (int)(temperature * 10) % 10); mylog("APP_T&H",str); } if(Sys.Humi_State == _RUN) { humidity = aht10_read_humidity(dev); if(humidity >= 75) { rt_event_send(&event, EVENT_FLAG_HUMI); } else { rt_event_send(&event, EVENT_FLAG_HUMI_REC); } rt_sprintf(str,"humi %d.%d %%",(int)humidity, (int)(humidity * 10) % 10); mylog("APP_T&H",str); } ``` 上述代码为在温湿度内做阀值判断,并发送对应的事件, 实现的全功能如下图所示 ![](http://ww1.sinaimg.cn/large/a2920a34ly1g6s51fjl8qj20pw0i2t9w.jpg) 温度30度告警,湿度75%告警,告警后LED灯常亮,告警恢复后LED灯200ms频率闪烁。潘多拉对应的4个按键对应不同的传感器数据。可以使能或失能采集。 # END,第二期的作业看起来已经做完啦,期待RTT的下一期的加强训练营。
查看更多
0
个回答
默认排序
按发布时间排序
暂无答案,快来添加答案吧
撰写答案
登录
注册新账号
关注者
0
被浏览
952
关于作者
Mrp_Young
这家伙很懒,什么也没写!
提问
4
回答
32
被采纳
0
关注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
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
2
RT-Thread EtherKit开源以太网硬件正式发布
3
如何在master上的BSP中添加配置yml文件
4
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
5
RT-Thread 发布 EtherKit开源以太网硬件!
热门标签
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
keil_MDK
rt_mq_消息队列_msg_queue
MicroPython
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
15
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部