單片機模塊化程序: 數據緩存封裝-內存管理實現(內存塊長度充足版)


 

 

 

前言

  上一節使用的是環形隊列實現的數據緩存

  這節使用內存管理實現

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

 

  

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM