zoukankan      html  css  js  c++  java
  • 单片机模块化程序: 数据缓存封装-内存管理实现(内存块长度充足版)

    前言

      上一节使用的是环形队列实现的数据缓存

      这节使用内存管理实现

      内存管理使用的是 μ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
    ";
    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
    ",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);

      

     

  • 相关阅读:
    卓京---java基础2
    GuessFist
    猜拳 GuessFist
    GuessNum
    GuessNumber
    JetBrains全系列软件激活教程激活码以及JetBrains系列软件汉化包
    两个class 之间要空两行
    ImageField 字段的使用
    max_length 属性
    null,blank,default
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/12238511.html
Copyright © 2011-2022 走看看