在实现STM32开发ESP8266的时候发现ESP8266串口发送的消息行数很多, 如果使用普通的数组来存储消息需要大量的存储开销, 并且数据的显示也会损耗MCU的处理速度, 故而实现对消息的传输装入一个可以动态拓展, 并且具有灵活的调用形式的容器. 链表理所当然成为首选.
关于C语言链表的相关操作本文不再详细叙述, 若有需求请移步网址:https://blog.csdn.net/morixinguan/article/details/68951912先学习链表后再来学习在STM32创建链表.
首先粘贴STM32上链表.c文件的代码:
//////roll_display.c的代码
#include "roll_display.h"
#include #include Linkedlist *creat_list(int size) //创建链表 { int i; Linkedlist *head = (Linkedlist *)malloc(sizeof(Linkedlist)); Linkedlist *temp = head; head->Data[0] = 0; for (i=0;i Linkedlist *node = (Linkedlist *)malloc(sizeof(Linkedlist)); //节点 node->next = NULL; //确保下一次迭代时为空 temp->next = node; //指向下一个节点 temp = node; //迭代 } return head; } Linkedlist *add_last_node(Linkedlist *head) { Linkedlist *node = (Linkedlist *)malloc(sizeof(Linkedlist)); //创建新的节点 Linkedlist *temp = head; node->next = NULL; while (temp->next != NULL) temp = temp->next; temp->next = node; return head; } Linkedlist *reduce_first_node(Linkedlist *head) //去除链头 { Linkedlist *new_head = (Linkedlist *)malloc(sizeof(Linkedlist)); new_head = head->next; //新链头指向下一个节点 free(head); //释放原本的旧链头 return new_head; } 接着是.h文件的代码: //////////roll_display.h文件的代码 #ifndef _ROLL_DISPLAY_H #define _ROLL_DISPLAY_H #include #include struct List //节点 { unsigned char Data[100]; struct List *next; }; typedef struct List Linkedlist; Linkedlist *creat_list(int size); Linkedlist *add_last_node(Linkedlist *head); //嵌入节点 Linkedlist *reduce_first_node(Linkedlist *head); //替代第一个节点 #endif 然后在主函数中调用代码时发现 编译会报错, 错误信息为//__use_no_semihosting was requested, but _ttywrch was 大概意思为 编译需要使用半主机模式, 原因是因为malloc函数和free函数在MCU上有些不适用, 需要进行重定义 ttywrch函数 其实重定义函数在学习usart串口通信时已经使用过, 当时重定义的是printf函数使用的fputs函数 那么本次创建链表需要重定义ttywrch函数,具体代码为在代码任意处使用定义: _ttywrch(int ch) //为了避免malloc的定义错误 半主机模式 { } 这样就将ttywrch函数定义为一个无用函数, 编译就没有错误啦. 但是! 在之后使用链表时, 比如将创建的链表中Data数组的数据在串口中打印出来时发现打印的消息和想象中完全不符合! 之后经过我大量的检查后得出结论, 可能调用函数创建链表的栈堆不够使用造成的! 然后我打开STM32的启动文件, 也就是 图中的startup_stm32f40_41xxx.c, 将其中的Heap_Size 改成了0x00002000 , 这样就是链表可使用的栈堆加大, 再次使用时就发现, 链表已经可以使用了! 至此STM32上链表的创建已经完成! 最后讲一下LCD上滚动显示串口消息的思路,: 创建一个具有10个节点的链表, 每次将新接收到的消息放在一个新的节点中, 并将其添加到链表的最后, 之后删除头节点, 成为一个新的链表, 对应LCD顺序显示每一个节点的消息, 并实现迭代. 代码如下: #include "sys.h" #include "usart.h" #include "lcd.h" #include "string.h" #include "roll_display.h" //__use_no_semihosting was requested, but _ttywrch was _ttywrch(int ch) //为了避免malloc的定义错误 半主机模式 { } u8 len,i,n; u8 line=50; //line 第几行 int main(void) { Linkedlist *head = creat_list(9); //创建链表 Linkedlist *temp = head; Linkedlist *new_temp = head; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); LCD_Init(); POINT_COLOR=RED; LCD_ShowString(50,10,210,24,16,"Data:"); while(1) { if (USART_RX_STA&0x8000) { Linkedlist *new_head = (Linkedlist *)malloc(sizeof(Linkedlist)); //迭代时生成新链作为"抛弃链" new_head = new_temp; add_last_node(new_head); //在链表最后添加一个节点 new_temp = reduce_first_node(new_head); ////去掉链表第一个节点 保存新链头并释放老链头 temp = new_temp; len = USART_RX_STA&0x3FFF; LCD_Fill(20,line,240,246,WHITE); //对动态显示行清除显示 for (i=0;temp->next != NULL;i++) { LCD_ShowString(20,line,240,12,16,temp->Data); //每次对下一行显示 temp = temp->next; line += 20; } for (n=0;n LCD_ShowString(20,line,240,12,16,temp->Data); //链表最后一行显示 line=50; //底行 USART_RX_STA=0; memset(USART_RX_BUF,0,len); //清除接收缓存 } } }
上一篇:STM32的PWM的频率和占空比设定
下一篇:对于STM32F4库函数中GPIO_PinAFConfig()函数的解读
推荐阅读最新更新时间:2024-11-13 09:15
设计资源 培训 开发板 精华推荐
- FEBFAN6224M_CP01,基于用于反激式转换器的 FAN6224M 绿色模式同步整流控制器的评估板
- NCP3901GEVB:双输入、单输出电源多路复用器
- MIC2033-05BYM6 EV,用于高精度、高侧、固定电流限制电源开关的评估板
- 无线 PIR 摄像机参考设计
- LTC6262HMS8 低功率、低失真 ADC 驱动器、运算放大器的典型应用
- ADP7156ARDZ-1.2-R7 1.2V 输出电压、1.2A、超低噪声、高 PSRR、RF 线性稳压器的典型应用
- LTC4066EUF 演示板、USB 电源管理器和锂离子充电器
- Si4113GX5-EVB,用于 Si4113GX5-BM PLL 频率合成器的评估板
- ADM7160UJ-EVALZ,用于评估 ADM7160 超低噪声、200 mA、TSOT 线性稳压器的评估板
- (c52) IV-18VFD荧光管时钟