前言 上一节使用的是环形队列实现的数据缓存 这节使用内存管理实现 内存管理使用的是 μC/OS-II 里面的内存管理程序
使用说明 一,内存管理意味着有许多的内存块 内存块的长度假设定义的足够大,可以放入每条数据 二,定义一个数组,作为内存分区 data_type_t CommTxPart[BlocksNumber][BlocksSize]; 所有的封装到了 MemManage文件里面,如果用户想了解实质 请自行学习,我只说明怎么应用!
注意:
data_type_t : 代表内存 存储的数据类型 ,请定义成这种类型
默认按照char型数据存储,请自行修改 BlocksNumber : 数组的行数(内存块数量) BlocksSize : 数组的列数(每个内存块长度)
提醒: 提醒: 提醒: BlocksNumber :也代表最大管理的数据的条数,当前是3 BlocksSize : 代表着每条数据最大存储的数据个数,不得超过 此个数,否则数组溢出,造成程序崩溃 实际上就是用多维的数组存储数据 数组的行数代表最大储存的数据条数 数组的列用于存储每一条数据,一条数据最大500个
三,定义一个管理变量
mem_manage_struct mem_manage_struct1;
四,创建
五,插入数据
MemManageWrite(&mem_manage_struct1,temp,17,&err);
五,如果缓存区有数据,则取出来打印
六:整体程序
#include "include.h"
#include "MemManage.h"
data_type_t CommTxPart[BlocksNumber][BlocksSize];
mem_manage_struct mem_manage_struct1;
INT8U err;
char temp[17]="111111111111111\r\n";
data_type_t *Data;
uint32_t DataLen;
int main(void)
{
NVIC_Configuration();
uart_init(115200); //串口初始化为115200
GpioInit();
DelayInit();
MemManageCreate(&mem_manage_struct1,CommTxPart,BlocksNumber,BlocksSize,&err);
if(err!=0){printf("MemManageCreate err=%d\r\n",err);}
while(1)
{
if(SysTickCntMs>=3000)
{
MemManageWrite(&mem_manage_struct1,temp,17,&err);
SysTickCntMs=0;
}
Data = MemManageRead(&mem_manage_struct1,&DataLen);
if(DataLen>0)
{
UsartOutStr(Data,DataLen);
MemManageFree(&mem_manage_struct1);
}
// if(Usart1ReadFlage)//串口接收到数据
// {
// Usart1ReadFlage=0;
// }
}
}
运行测试 一直判断是否缓存了数据,如果有缓存的数据,则打印缓存的数据 因为是每隔3S插入一次数据,所以每隔3S打印一次
测试2每隔3S插入两份数据:用来模拟不定期插入多份数据 为看出是一条数据一条数据取出来的,加了500ms延时
扩展:使用串口中断发送缓存的数据 一,首先先说明处理思路 如果缓存区没有数据,则每隔1ms查询一次 如果查询到了有数据,则提取出来,然后交由中断处理 然后查询间隔变为10ms (该间隔可调节) 10ms便是发送每一条数据之间的时间间隔 二,1Ms定时器增加以下程序
if(mem_manage_struct1.SendLen == 0)//没有数据正在发送
{
mem_manage_struct1.Cnt++;
if(mem_manage_struct1.Cnt>=10)//10Ms
{
mem_manage_struct1.Cnt = 0;
//查询是不是有数据需要发送
mem_manage_struct1.DataPtr = MemManageRead(&mem_manage_struct1,&(mem_manage_struct1.SendLen));
if(mem_manage_struct1.SendLen>0)//有数据需要发送
{
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//使能串口发送
}
else//没有数据需要发送的时候降低检测时间
{
mem_manage_struct1.Cnt=10;
}
}
}
三,串口中断里面
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
{
if(mem_manage_struct1.SendLen>0)//发送的数据个数大于0
{
USART_SendData(USART1, *mem_manage_struct1.DataPtr);//发送
mem_manage_struct1.DataPtr++;
mem_manage_struct1.SendLen -- ;//发送的数据个数减一
}
else//发送字节结束
{
mem_manage_struct1.SendLen = 0;
MemManageFree(&mem_manage_struct1);
USART_ClearITPendingBit(USART1,USART_IT_TXE);
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
USART_ITConfig(USART1, USART_IT_TC, ENABLE);
}
}
//发送完成
if (USART_GetITStatus(USART1, USART_IT_TC) != RESET)
{
USART_ClearITPendingBit(USART1,USART_IT_TC);
USART_ITConfig(USART1, USART_IT_TC, DISABLE);
}
四,效果 主函数还是每隔3S插入两条数据
扩展:使用DMA串口发送缓存的数据 一,我先留给大家去完善,我给大家一些提示 简而言之:如果有数据需要发送,就设置下数据地址和数据个数,然后启动DMA 详细方案1: 每次存入数据以后,判断下DMA是否传输完成,如果传输完成,则重新赋值以后启动 在DMA发送完成中断里面判断是否有数据需要发送 如果有,则重新赋值以后启动 详细方案2: 上述方案有个问题在于每条数据之间没有了固定的时间间隔 有可能造成粘包. 咱还是利用定时器,把以下红框改为: 重新赋值DMA以后启动DMA. 别忘了在DMA发送完成中断里面: mem_manage_struct1.SendLen = 0; MemManageFree(&mem_manage_struct1);
|