| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> STM32MP157资源扩展板驱动移植篇12:FreeRTOS列表和列表项 -> 正文阅读 |
|
[嵌入式]STM32MP157资源扩展板驱动移植篇12:FreeRTOS列表和列表项 |
写在前面: 本文章为《STM32MP157资源扩展板驱动移植篇》系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板)。资源扩展板是FS-MP1A开发板的扩展模块,主要包含了10余种主流传感器、执行器件、总线控制器件,非常方便项目扩展用。可拓展开发智慧家庭、智能医疗、智能安防、工业控制、图像识别、环境检测等方向的10个左右综合项目,华清远见开发板也将配套提供所有项目的说明文档、实验源码、应用程序等资料。 针对FS-MP1A开发板,除了资源扩展板驱动移植篇外,还包括其他多系列教程,包括Cortex-A7开发篇、Cortex-M4开发篇、FreeRTOS篇、Linux应用开发篇、Linux系统移植篇、Linux驱动开发篇、硬件设计篇、人工智能机器视觉篇、Qt应用编程篇、Qt综合项目实战篇等。欢迎关注,更多stm32mp157开发教程及视频,可加技术交流Q群459754978,感谢关注。 FS-MP1A开发板详情介绍: 资源扩展板介绍硬件介绍资源扩展板可开发项目FreeRTOS列表和列表项列表和列表项简介学习FreeRTOS,肯定少不了列表和列表项,列表和列表项是FreeRTOS的一个数据结构,它是FreeRTOS的基石。 列表被用来跟踪FreeRTOS中的任务,在list.h文件中定义了列表结构体List_t如下 typedef struct xLIST { listFIRST_LIST_INTEGRITY_CHECK_VALUE configLIST_VOLATILE UBaseType_t uxNumberOfItems; ListItem_t * configLIST_VOLATILE pxIndex; MiniListItem_t xListEnd; listSECOND_LIST_INTEGRITY_CHECK_VALUE } List_t; 第一行和第五行都是用来检查列表完整性,需要将宏 uxNumberOfItems用来记录列表中列表项的数量。 pxIndex用来记录当前列表项索引号,用于遍历列表。 xListEnd表示列表中最后一个列表项,用来表示列表结束。 列表项就是存放在列表中的项目,其定义如下 struct xLIST_ITEM { listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE configLIST_VOLATILE TickType_t xItemValue; struct xLIST_ITEM * configLIST_VOLATILE pxNext; struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; void * pvOwner; void * configLIST_VOLATILE pvContainer; listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE }; typedef struct xLIST_ITEM ListItem_t; 第一行和第七行同列表一样,都是用来检查列表项完整性。 xItemValue为列表项值。 pxNext指向下一个列表项。 pxPrevious指向前一个列表项,与pxNext相配合。 pvOwner记录此列表项归谁拥有,通常是任务控制块。 pvContainer用来记录此列表项归哪个列表。 另外还有一种迷你列表项,其定义如下 struct xMINI_LIST_ITEM { listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE configLIST_VOLATILE TickType_t xItemValue; struct xLIST_ITEM * configLIST_VOLATILE pxNext; struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; }; typedef struct xMINI_LIST_ITEM MiniListItem_t; 第一行同样用于检查迷你列表项的完整性。 xItemValue记录列表项值。 pxNext指向下一个列表项。 pxPrevious指向前一个列表项。 在这里之所以弄个迷你列表项,是因为有些情况下,我们不需要列表项那么全的功能,可能只需要其中的某几个成员变量,此时用列表项的话可能会造成内存浪费。 列表与列表项函数2.2.1列表与列表项初始化新创建或者定义的列表都需要对其做初始化处理,对列表的初始化函数为vListInitialise(),其函数原型如下: void vListInitialise ( List* const pxList) 参数: pxList: 要进行初始化的列表。 返回值:无 对列表项的初始化函数为vListInitialiseItem(),其函数原型如下: void vListInitialiseItem ( ListItem_t * const pxItem) 参数: pxItem: 要进行初始化的列表。 返回值:无 在此不对初始化函数的具体代码做描述了,有兴趣的可以去list.c文件中查看。 2.2.2 列表项插入列表项的插入函数为vListInsert(),其函数原型如下: void vListInsert( List* const pxList, ListItem_t * const pxNewListItem) 参数: pxList: 列表项要插入的列表。 pxNewListItem: 要插入的列表项。 返回值:无 2.2.3列表项末尾插入列表在末尾插入列表项的函数为vListInsertEnd(),其函数原型如下: void vListInsertEnd( List * const pxList, ListItem_t * const pxNewListItem) 参数: pxList: 列表项要插入的列表。 pxNewListItem: 要插入的列表项。 返回值:无 2.2.4 列表项删除有插入那么必然有删除,列表项的删除函数为uxListRemove(),其函数原型如下: UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) 参数: pxItemToRemove: 要删除的列表项。 返回值: 返回删除列表项以后的列表剩余列表项数目。 列表项的删除只是将指定的列表项从列表中删除掉,并不会将列表项的内存给释放掉。 操作实验2.3.1实验设计本次设计中创建了一个列表以及三个列表项,通过中断采集按键状态,当KEY1按下时,依次将三个列表项添加到列表中,当KEY2按下时,删除第2条列表项,当KEY3按下时,再将第2条列表项从末尾插入。 可参考12.3.2章节进行导入已有工程,工程存放路径【华清远见-FS-MP1A开发资料\02-程序源码\ARM体系结构与接口技术\FreeRTOS\7_MP1A-FreeRTOS-List】 任务及其功能如下: StartTask02(): 进行列表与列表项的初始化并打印,然后采集按键状态,根据不同的按键结果进行不同处理。 StartDefaultTask(): 让LED3循环闪烁,提示系统正常运行。 2.3.2实验过程与分析首先,根据之前几章内容配置好CubeMX,按照上一节配置“FREERTOS”,完成后生成代码。 在StartDefaultTask() 与StartTask02()中添加代码如下。 void?StartDefaultTask(void?*argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { LED_3_TOG(); osDelay(1000); } /* USER CODE END 5 */ } void?StartTask02(void?*argument) { /* USER CODE BEGIN StartTask02 */ /* Infinite loop */ //初始化列表和列表项 vListInitialise(&TestList); vListInitialiseItem(&ListItem1); vListInitialiseItem(&ListItem2); vListInitialiseItem(&ListItem3); ListItem1.xItemValue=40;?//ListItem1列表项值为40 ListItem2.xItemValue=60;?//ListItem2列表项值为60 ListItem3.xItemValue=50;?//ListItem3列表项值为50 //打印列表和其他列表项的地址 printf("project address \r\n"); printf("TestList %#x \r\n",(int)&TestList); printf("TestList->pxIndex %#x \r\n",(int)TestList.pxIndex); printf("TestList->xListEnd %#x \r\n",(int)(&TestList.xListEnd)); printf("ListItem1 %#x \r\n",(int)&ListItem1); printf("ListItem2 %#x \r\n",(int)&ListItem2); printf("ListItem3 %#x \r\n",(int)&ListItem3); for(;;) { if(key == EVENTBIT_1) { //向列表TestList添加列表项ListItem1,并通过串口打印所有 //列表项中成员变量pxNext和pxPrevious的值,通过这两个值观察列表 //项在列表中的连接情况。 vListInsert(&TestList,&ListItem1);?//插入列表项ListItem1 printf("project address \r\n"); printf("TestList->xListEnd->pxNext %#x \r\n",(int)(TestList.xListEnd.pxNext)); printf("ListItem1->pxNext %#x \r\n",(int)(ListItem1.pxNext)); printf("/***********Connect the divider front and back 1************/\r\n"); printf("TestList->xListEnd->pxPrevious %#x \r\n",(int)(TestList.xListEnd.pxPrevious)); printf("ListItem1->pxPrevious %#x \r\n",(int)(ListItem1.pxPrevious)); printf("/**************************end****************************/\r\n"); //向列表TestList添加列表项ListItem2,并通过串口打印所有 //列表项中成员变量pxNext和pxPrevious的值,通过这两个值观察列表 //项在列表中的连接情况。 vListInsert(&TestList,&ListItem2);?//插入列表项ListItem2 printf("project address \r\n"); printf("TestList->xListEnd->pxNext %#x \r\n",(int)(TestList.xListEnd.pxNext)); printf("ListItem1->pxNext %#x \r\n",(int)(ListItem1.pxNext)); printf("ListItem2->pxNext %#x \r\n",(int)(ListItem2.pxNext)); printf("/***********Connect the divider front and back 2************/\r\n"); printf("TestList->xListEnd->pxPrevious %#x\r\n", (int)(TestList.xListEnd.pxPrevious)); printf("ListItem1->pxPrevious %#x \r\n",(int)(ListItem1.pxPrevious)); printf("ListItem2->pxPrevious %#x \r\n",(int)(ListItem2.pxPrevious)); printf("/***************************end*****************************/\r\n"); //向列表TestList添加列表项ListItem3,并通过串口打印所有 //列表项中成员变量pxNext和pxPrevious的值,通过这两个值观察列表 //项在列表中的连接情况。 vListInsert(&TestList,&ListItem3);?//插入列表项ListItem3 printf("project address \r\n"); printf("TestList->xListEnd->pxNext %#x \r\n",(int)(TestList.xListEnd.pxNext)); printf("ListItem1->pxNext %#x \r\n",(int)(ListItem1.pxNext)); printf("ListItem3->pxNext %#x \r\n",(int)(ListItem3.pxNext)); printf("ListItem2->pxNext %#x \r\n",(int)(ListItem2.pxNext)); printf("/************Connect the divider front and back 3************/\r\n"); printf("TestList->xListEnd->pxPrevious %#x \r\n",(int)(TestList.xListEnd.pxPrevious)); printf("ListItem1->pxPrevious %#x \r\n",(int)(ListItem1.pxPrevious)); printf("ListItem3->pxPrevious %#x \r\n",(int)(ListItem3.pxPrevious)); printf("ListItem2->pxPrevious %#x \r\n",(int)(ListItem2.pxPrevious)); printf("/***************************end*****************************/\r\n"); } if(key == EVENTBIT_2) { //删除ListItem2,并通过串口打印所有列表项中成员变量pxNext和Previous的值,通过这两个值观察列表项在列表中的连接情况。 uxListRemove(&ListItem2);?//删除ListItem2 printf("/**************Delete list items ListItem2*************/\r\n"); printf("project address \r\n"); printf("TestList->xListEnd->pxNext %#x \r\n",(int)(TestList.xListEnd.pxNext)); printf("ListItem1->pxNext %#x \r\n",(int)(ListItem1.pxNext)); printf("ListItem3->pxNext %#x \r\n",(int)(ListItem3.pxNext)); printf("/***********Connect the divider front and back 2************/\r\n"); printf("TestList->xListEnd->pxPrevious %#x \r\n",(int)(TestList.xListEnd.pxPrevious)); printf("ListItem1->pxPrevious %#x \r\n",(int)(ListItem1.pxPrevious)); printf("ListItem3->pxPrevious %#x \r\n",(int)(ListItem3.pxPrevious)); printf("/*************************end****************************/\r\n"); } if(key == EVENTBIT_3) { //末尾添加ListItem2,并通过串口打印所有列表项中成员变量pxNext和Previous的值, //通过这两个值观察列表项在列表中的连接情况。 TestList.pxIndex=TestList.pxIndex->pxNext;?//Index向后移一项,这样pxIndex就会指向ListItem1。 vListInsertEnd(&TestList,&ListItem2);?//列表末尾添加列表项ListItem2 printf("/***********Add the list at the end of ListItem2***********/\r\n"); printf("project address \r\n"); printf("TestList->pxIndex %#x \r\n",(int)TestList.pxIndex); printf("TestList->xListEnd->pxNext %#x \r\n",(int)(TestList.xListEnd.pxNext)); printf("ListItem2->pxNext %#x \r\n",(int)(ListItem2.pxNext)); printf("ListItem1->pxNext %#x \r\n",(int)(ListItem1.pxNext)); printf("ListItem3->pxNext %#x \r\n",(int)(ListItem3.pxNext)); printf("/************Connect the divider front and back 2*************/\r\n"); printf("TestList->xListEnd->pxPrevious %#x \r\n",(int)(TestList.xListEnd.pxPrevious)); printf("ListItem2->pxPrevious %#x \r\n",(int)(ListItem2.pxPrevious)); printf("ListItem1->pxPrevious %#x \r\n",(int)(ListItem1.pxPrevious)); printf("ListItem3->pxPrevious %#x \r\n",(int)(ListItem3.pxPrevious)); printf("/***************************end*****************************/\r\n"); } key = 0; osDelay(100); } /* USER CODE END StartTask02 */ } 编写按键中断回调函数如下 void?HAL_GPIO_EXTI_Rising_Callback(uint16_t?GPIO_Pin) { switch(GPIO_Pin) { case?GPIO_PIN_8: if(HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_8) ==?GPIO_PIN_SET)?/* read KEY3 PF8 state */ key = EVENTBIT_3; break; case?GPIO_PIN_7: if(HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_7) ==?GPIO_PIN_SET)?/* read KEY2 PF7 state */ key = EVENTBIT_2; break; case?GPIO_PIN_9: if(HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_9) ==?GPIO_PIN_SET)?/* read KEY1 PF9 state */ key = EVENTBIT_1; break; } } 烧录程序以后,打开串口,可以发现显示内容如下 当按下KEY1键时,将列表项添加到列表中,串口显示如下 当KEY2键按下时,删除第2条列表项,剩余结果如下 此时按下KEY3键,将第2条列表项从末尾插入,最终结果如下 硬件平台:华清远见FS-MP1A开发板(STM32MP157) 部分开发教程下载:加QQ群459754978,群文件里有。 部分视频课程收看: 淘宝购买链接: 手机淘宝分享码:复制本行文字打开手淘?T4FPXn3YYJ2? |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 22:49:03- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |