FreeRTOS课程设计之临沂大学停车场车位管理系统(一)

本文主要是介绍FreeRTOS课程设计之临沂大学停车场车位管理系统(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FreeRTOS课程设计之临沂大学停车场车位管理系统(一)

先看一下效果吧

1.作品要求

模拟临大停车场车位管理系统

首页显示:

欢迎来到临沂大学

空闲停车位n个(n个灯亮)

“by姓名”

按下K1(停车位数递减),显示“欢迎来到临沂大学,停车位剩余n个”。连续按n次,显示“没有空闲停车位”。

按下K2(停车位数递增),显示“欢迎再来临沂大学,停车位空余n个”。

按下K3,挂起任务1. 灯闪烁。

按下K4,恢复任务1. 灯全亮。

加分项:
功能的扩展与创意。

2.实现思路
  • 需要用到 LED、OLED、按键等外设
  • 使用FreeRTOS实时操作系统
  • 需要创建几个任务、任务之间如何安排、数据如何传递?
  • 想好这些之后,再开始敲代码之前画个图吧!

image-20201217201146378

主要创建4个任务,这4个任务如上图所示,如何把这几个任务联系起来?

当然是通过信号量了

老师说,信号量可以在任务之间传递,但我没怎么用上,偷了个懒,定义了一个chewei(车位变量),Take与Give这两个任务就是对这个变量进行操作,使其–、++。

LED_Task则是根据chewei信息及时更新LED与OLED显示。

KEY_Task则是挂起与恢复 前两个任务。

这样就是大体的思路了。

3.主要代码
3.1 任务句柄的创建
/**************************** 任务句柄 ********************************/
/* * 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄* 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么* 这个句柄可以为NULL。*/
static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */
static TaskHandle_t Take_Task_Handle = NULL;/* Take_Task任务句柄 */
static TaskHandle_t Give_Task_Handle = NULL;/* Give_Task任务句柄 */
static TaskHandle_t KEY_Task_Handle = NULL;/* KEY任务句柄 */
static TaskHandle_t LED_Task_Handle = NULL;/* LED任务句柄 */
3.2 AppTaskCreate任务
/************************************************************************ @ 函数名  : AppTaskCreate* @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面* @ 参数    : 无  * @ 返回值  : 无**********************************************************************/
static void AppTaskCreate(void)
{BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */taskENTER_CRITICAL();           //进入临界区/* 创建Test_Queue */CountSem_Handle = xSemaphoreCreateCounting(4,4);	 if(NULL != CountSem_Handle)printf("CountSem_Handle计数信号量创建成功!\r\n");/* 创建Take_Task任务 */xReturn = xTaskCreate((TaskFunction_t )Take_Task, /* 任务入口函数 */(const char*    )"Take_Task",/* 任务名字 */(uint16_t       )512,   /* 任务栈大小 */(void*          )NULL,	/* 任务入口函数参数 */(UBaseType_t    )4,	    /* 任务的优先级 */(TaskHandle_t*  )&Take_Task_Handle);/* 任务控制块指针 */if(pdPASS == xReturn)printf("创建Take_Task任务成功!\r\n");/* 创建Give_Task任务 */xReturn = xTaskCreate((TaskFunction_t )Give_Task,  /* 任务入口函数 */(const char*    )"Give_Task",/* 任务名字 */(uint16_t       )512,  /* 任务栈大小 */(void*          )NULL,/* 任务入口函数参数 */(UBaseType_t    )4, /* 任务的优先级 */(TaskHandle_t*  )&Give_Task_Handle);/* 任务控制块指针 */ if(pdPASS == xReturn)printf("创建Give_Task任务成功!\n\n");/* 创建KEY_Task任务 */xReturn = xTaskCreate((TaskFunction_t )KEY_Task,  /* 任务入口函数 */(const char*    )"KEY_Task",/* 任务名字 */(uint16_t       )512,  /* 任务栈大小 */(void*          )NULL,/* 任务入口函数参数 */(UBaseType_t    )4, /* 任务的优先级 */(TaskHandle_t*  )&KEY_Task_Handle);/* 任务控制块指针 */ if(pdPASS == xReturn)printf("创建KEY_Task任务成功!\n\n");/* 创建LED_Task任务 */xReturn = xTaskCreate((TaskFunction_t )LED_Task,  /* 任务入口函数 */(const char*    )"LED_Task",/* 任务名字 */(uint16_t       )512,  /* 任务栈大小 */(void*          )NULL,/* 任务入口函数参数 */(UBaseType_t    )4, /* 任务的优先级 */(TaskHandle_t*  )&LED_Task_Handle);/* 任务控制块指针 */ if(pdPASS == xReturn)printf("创建LED_Task任务成功!\n\n");vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务taskEXIT_CRITICAL();            //退出临界区
}
3.3 Take_Task
/*********************************************************************** @ 函数名  : Take_Task* @ 功能说明: Take_Task任务主体* @ 参数    :   * @ 返回值  : 无********************************************************************/
static void Take_Task(void* parameter)
{	BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdPASS *//* 任务都是一个无限循环,不能返回 */while (1){//如果KEY1被单击	if( 0 == HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)  )       {  delay_ms(80);if( 0 == HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)  ){/* 获取一个计数信号量 */xReturn = xSemaphoreTake(CountSem_Handle,	/* 计数信号量句柄 */0); 	/* 等待时间:0 */if(chewei!=0){chewei--;}if ( pdTRUE == xReturn ) printf( "KEY1被按下,成功申请到停车位。\n" );elseprintf( "KEY1被按下,不好意思,现在停车场已满!\n" );	}			}vTaskDelay(20);     //每20ms扫描一次		}
}
3.4 Give_Task
static void Give_Task(void* parameter)
{	 BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdPASS *//* 任务都是一个无限循环,不能返回 */while (1){//如果KEY2被单击if( 0 == HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) )  			{delay_ms(80);if( 0 == HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) ){/* 获取一个计数信号量 */xReturn = xSemaphoreGive(CountSem_Handle);//给出计数信号量  chewei++;if ( pdTRUE == xReturn ) printf( "KEY2被按下,成功释放车位!\r\n" );elseprintf( "KEY2被按下,不好意思,无可释放车位!\r\n" );	}		}vTaskDelay(20);     //每20ms扫描一次	}
}
3.5 Key_Task
static void KEY_Task(void* parameter)
{	while (1){if( 0 == HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin)){delay_ms(80);if( 1 == HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) ){/* K3 被按下 */printf("挂起任务\n");vTaskSuspend(Take_Task_Handle);/* 挂起Take任务 */vTaskSuspend(Give_Task_Handle);/* 挂起Give任务 */printf("挂起任务成功!\n");shining = 1;}}			if( 0 == HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) ){/* K4 被按下 */delay_ms(80);if( 0 == HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) ){/* K4 被按下 */printf("恢复任务!\n");vTaskResume(Take_Task_Handle);/* 恢复Take任务! */vTaskResume(Give_Task_Handle);/* 恢复Give任务! */printf("恢复任务成功!\n");shining = 0; }}vTaskDelay(20);/* 延时20个tick */}
}

3.5LED_Task

/*********************************************************************** @ 函数名  : LED_Task* @ 功能说明: LED_Task任务主体* @ 参数    :   * @ 返回值  : 无********************************************************************/
static void LED_Task(void* parameter)
{	 OLED_Clear();OLED_ShowChinese_Row(0,0,*huanying); OLED_ShowChinese_Row(0,2,*shengyu); while (1){pub++;switch ( chewei ) {	case 0:LED1_OFF;LED2_OFF;LED3_OFF;LED4_OFF;OLED_ShowChinese_Row(0,0,*wukongxain);OLED_ShowString(0,2,"no free parking ");OLED_ShowNum(64,4, chewei,1,15);break; case 1:LED1_OFF;LED2_OFF;LED3_OFF;LED4_ON;if(shining==1){delay_ms(500);LED4_OFF;delay_ms(500);}OLED_ShowNum(64,4, chewei,1,15);break;case 2:LED1_OFF;LED2_OFF;LED3_ON;LED4_ON;if(shining==1){delay_ms(500);LED3_OFF;LED4_OFF;delay_ms(500);}OLED_ShowNum(64,4, chewei,1,15);break;case 3:LED1_OFF;LED2_ON;LED3_ON;LED4_ON;if(shining==1){delay_ms(500);LED2_OFF;LED3_OFF;LED4_OFF;delay_ms(500);}OLED_ShowNum(64,4, chewei,1,15);break;case 4:LED1_ON;LED2_ON;LED3_ON;LED4_ON;if(shining==1){delay_ms(500);LED1_OFF;LED2_OFF;LED3_OFF;LED4_OFF;delay_ms(500);}OLED_ShowNum(64,4, chewei,1,15);break;default: break;}//大概有1分钟上传一次数据if(pub%2000==0){pub = 0;STM32DHT11_StatusReport();}vTaskDelay(20);     //每20ms扫描一次	}
}
4.遇到一些问题
4.1 按键不灵敏

按键有些不灵敏,所要进行消抖

我用的是软件延时消抖,效果还不错,延时时间为80ms

 if( 0 == HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin)){delay_ms(80);if( 1 == HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) ){/* K3 被按下 */}}

HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin)

至于为什么用这个函数?

贴一张cubeMX配置图

image-20201217203620724

一般来说,需要区分这个GPIO口用于输入还是输出。

如果是output,那个一般选择no pull,这样,引脚才能根据你的output数据,进行正确输出。

如果是input,那么需要看具体应用的默认输入值是0还是1. 如果默认是输入0,则最好配置为pull down,反之则配置为pull up.

一个接有上拉电阻的端口设为输入状态时,他的常态就为高电平,用于检测低电平的输入

这篇关于FreeRTOS课程设计之临沂大学停车场车位管理系统(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/370117

相关文章

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

STL经典案例(四)——实验室预约综合管理系统(项目涉及知识点很全面,内容有点多,耐心看完会有收获的!)

项目干货满满,内容有点过多,看起来可能会有点卡。系统提示读完超过俩小时,建议分多篇发布,我觉得分篇就不完整了,失去了这个项目的灵魂 一、需求分析 高校实验室预约管理系统包括三种不同身份:管理员、实验室教师、学生 管理员:给学生和实验室教师创建账号并分发 实验室教师:审核学生的预约申请 学生:申请使用实验室 高校实验室包括:超景深实验室(可容纳10人)、大数据实验室(可容纳20人)、物联网实验

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

FreeRTOS学习笔记(六)队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQueueReceive2.4 xQueueSendFromISR2.5 xQueueRecei

使用Spring Boot集成Spring Data JPA和单例模式构建库存管理系统

引言 在企业级应用开发中,数据库操作是非常重要的一环。Spring Data JPA提供了一种简化的方式来进行数据库交互,它使得开发者无需编写复杂的JPA代码就可以完成常见的CRUD操作。此外,设计模式如单例模式可以帮助我们更好地管理和控制对象的创建过程,从而提高系统的性能和可维护性。本文将展示如何结合Spring Boot、Spring Data JPA以及单例模式来构建一个基本的库存管理系统

FreeRTOS学习笔记(二)任务基础篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、 任务的基本内容1.1 任务的基本特点1.2 任务的状态1.3 任务控制块——任务的“身份证” 二、 任务的实现2.1 定义任务函数2.2 创建任务2.3 启动任务调度器2.4 任务的运行与切换2.4.1 利用延时函数2.4.2 利用中断 2.5 任务的通信与同步2.6 任务的删除2.7 任务的通知2

【干货分享】基于SSM的体育场管理系统的开题报告(附源码下载地址)

中秋送好礼 中秋佳节将至,祝福大家中秋快乐,阖家幸福。本期免费分享毕业设计作品:《基于SSM的体育场管理系统》。 基于SSM的体育场管理系统的开题报告 一、课题背景与意义 随着全民健身理念的深入人心,体育场已成为广大师生和社区居民进行体育锻炼的重要场所。然而,传统的体育场管理方式存在诸多问题,如资源分配不均、预约流程繁琐、数据统计不准确等,严重影响了体育场的使用效率和用户体验。