项目中使用到rt—thread就会涉及到对操作系统的一个软件框架的搭建过程思路,这里拿已经完成城的项目做一些分享,希望对读者有些启发。
项目要求:读取温湿度,串口打印,数据定时发送,lcd显示,平台上传,按键设置,SD 卡存储等
系统涉及到的硬件由以下几部分组成:
1.交互输入部分:按键
2. 输出部分:TFTLCD屏幕显示,SD卡存储,led灯报警
3. 传感器采集:DHT11温湿度采集
4. 通讯部分:串口,wifi模块
5. 计时部分:RTC时钟计时
硬件连接示意图根据硬件的连接与系统要求实现的功能来看:
1.首先要做的就是根据硬件电路写好底层驱动(HAL)
2.进行函数的划分与封装,将应用层需要的函数封装好
3.进行中断函数的撰写与封装(可以将该这一步与第2步同时进行)
4.由于中断的优先级比任何的线程优先级都要高因此需要统筹线程与中断的关系
5.继续线程的规划,线程优先级定义及应用层函数的撰写
软件程序结构:
项目系统要求定期发送数据到平台,其中在定时器超函数中周期性采集温湿度信息,并发送消息队列到处理缓存传感器信息的线程和超温处理线程,同时发布采集到一次传感器的事件。
超温处理线程接收消息判断是否超过温度,wifi模块通过串口2将温湿度信息发送给wifi模块,由wifi模块实时上传到服务器。同时串口温度上传任务同时接收定时器发送的事件和PC机通过串口1发送的获取温度标志所触发的事件。当采集到传感器信息且上位机要求获取温湿度信息的事情同时发生时,通过串口1向PC发送温湿度信息。由于SD卡存储缓慢,所以由温湿度信息缓存线程在内存池中申请内存,并将获取到的温湿度信息缓存到内存中,同时更新LCD曲线绘制的历史温湿度信息缓存。
LCD处理线程处理IO口中断发送过来的标志信息,并据此显示相应的菜单,温度湿度信息,显示所设定采样频率与阈值的情况等。
SD卡存储任务作为后台任务,从缓存存储温湿度信息的内存中读取温湿度信息,并通过FATFS文件系统将相应的温湿度信息存入SD卡,同时根据每片内存的头部时间信息以及定时器采样频率推算本片内存中其他数据的时间信息,并将采样时间一起保存到SD卡中。在存储完一片内存片后,释放该内存到内存池之中。流程图如下所示:
代码部分这里贴出主函数中的基本逻辑框架:
int main(void)
{
/***********************挂载SD卡并打开文件*******************************/
while(SD_Init())//检测不到SD卡
{
LCD_ShowString(30,150,200,16,16,"SD Card Error!");
LCD_ShowString(50,150,200,16,16,"Please Check! ");
}
//*****************消息队列创建 *****************************************/
//申请内存池
//初始化控制块
rt_mp_init(&tem_mp, "temmp", &temmempool[0], sizeof(temmempool), mem_slice);
rt_mp_init(&hum_mp, "hummp", &hummempool[0], sizeof(hummempool), mem_slice);
rt_err_t result2;
/* 初始化消息队列 */
result= rt_mq_init(& mq_DHT11_tem,
" mq_DHT11_tem",
&msg_DHT11_pool_tem[0], /* msg_pool */
sizeof(tem), /* 每个消息的大小*/
sizeof(msg_DHT11_pool_tem), /* msg_pool大小*/
RT_IPC_FLAG_FIFO);
result2 = rt_mq_init(& mq_DHT11_hum,
" mq_DHT11_hum",
&msg_DHT11_pool_hum[0], /* msg_pool */
sizeof(hum), /* 每个消息的大小*/
sizeof(msg_DHT11_pool_hum), /* msg_pool大小*/
RT_IPC_FLAG_FIFO);
//定时器线程
/* DHT11 TIMER */
DH11_timer = rt_timer_create("DHT11_get", timeout1,
RT_NULL, samp_freq,
RT_TIMER_FLAG_PERIODIC);
/* 启动*/
if (DH11_timer != RT_NULL)
flag=rt_timer_start(DH11_timer );
if(flag==RT_EOK)
rt_kprintf("DH11_timer start successfull\n");
//***********************事件处理线程*******************************************/
uart_deal_event = /* 线程控制块指针 */
rt_thread_create( "usart_deal_event", /* 线程名字 */
uart_deal_thread_entry, /* 线程入口函数 */
RT_NULL, /* 线程入口函数参数 */
256, /* 线程栈大小 */
2, /* 线程的优先级 */
20); /* 线程时间片 */
/* 启动线程,开启调度 */
if (uart_deal_event != RT_NULL)
rt_thread_startup(uart_deal_event);
else
rt_kprintf("led_thread_creat_error");
////*******************创建内存任务线程***********************************************************//
for (j = 0; j < 48; j++) ptr[j] = RT_NULL;
//创建线程
recevDHT11 = rt_thread_create("recevDHT11", recevDHT11_entry, RT_NULL,
512,
4 ,20);
if (recevDHT11 != RT_NULL)
rt_thread_startup(recevDHT11);
//*******************创建释放内存堆写入SD卡线程***********************************************************//
thread_mp_release = rt_thread_create("thread_mp_release", thread_mp_release_entry, RT_NULL,
1024,
4, 20);
if (thread_mp_release != RT_NULL)
rt_thread_startup(thread_mp_release);
///*******************创LCD 显示绘图线程***********************************************************//
lcd_show= rt_thread_create("lcd_showwave", lcd_show_entry, RT_NULL,
512,
3, 30);
if (lcd_show != RT_NULL)
rt_thread_startup(lcd_show );
//*******************超温处理线程的创建***********************************************************//
over_temhum = rt_thread_create("over_temhum ", overtem_entry, RT_NULL,
256,
1, 20);
if (lcd_show != RT_NULL)
rt_thread_startup(over_temhum );
//*******************wifi线程创建***********************************************************//
wifi= rt_thread_create("wifi ", wifi_entry, RT_NULL,
128,
2, 20);
if (wifi != RT_NULL)
rt_thread_startup(wifi);
//*************测试wifi模块************************************************************************//
}
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !