天天看點

序列槽循環隊列接收緩沖區bug項目場景:問題描述:原因分析:解決方案:

項目場景:

項目場景:巡檢機器人STM32控制闆采用序列槽與工控機通信,循環隊列接收緩沖區出現bug,導緻循環擷取曆史資料包

問題描述:

巡檢機器人執行任務中出現bug,往複執行曆史指令,排查了好幾天,最後檢查上位機序列槽沒有發送資料,單片機debug也确認序列槽沒有接收到新資料。最後的最後才debug32的序列槽資料緩存循環隊列,發現代碼中Lenght變量出現了問題。 循環隊列緩沖資料代碼: 此處借用部落格代碼 [循環隊列代碼](https://blog.csdn.net/m0_47661708/article/details/106585137?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162019740716780357260766%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=162019740716780357260766&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-106585137.nonecase&utm_term=%E4%B8%B2%E5%8F%A3%E5%BE%AA%E7%8E%AF%E9%98%9F%E5%88%97)

typedef struct
{
 uint16_t Head;//頭指針
 uint16_t Tail;//尾指針
 uint16_t Lenght;//長度
 uint8_t Ring_Buff[200];//緩沖大小
}RingBuff_t;
extern RingBuff_t ringBuff;
void RingBuff_Init();緩沖區初始化
uint8_t Write_RingBuff(uint8_t data);//入隊
uint8_t Read_RingBuff(uint8_t *rData);//出隊

void RingBuff_Init(void)
{
 ringBuff.Head=0;
 ringBuff.Tail=0;
 ringBuff.Lenght=0;
}

uint8_t Write_RingBuff(uint8_t data)
{
 if(ringBuff.Lenght>=200)
 {
  return 1;
 }
 ringBuff.Ring_Buff[ringBuff.Tail]=data;
 ringBuff.Tail=(ringBuff.Tail+1)%200;
 ringBuff.Lenght++;
 return 0;
}

uint8_t Read_RingBuff(uint8_t *rData)
{
//if(ringBuff.Head==ringBuff.Tail && ringBuff.Lenght==0)//我自己的問題代碼在這!!!!
 if(ringBuff.Lenght==0)
 {
  return 1;
 }
 *rData=ringBuff.Ring_Buff[ringBuff.Head];
 ringBuff.Head=(ringBuff.Head+1)%200;
 ringBuff.Lenght--;
 return 0;
}
           

原因分析:

我們采用的隊列空判斷條件用了兩個,之前可能是為了保險,但最後出現了問題!首先剛進該if語句,判斷第一個條件,假設隊列不為空,則 ringBuff.Head==ringBuff.Tail 為false,剛好此時定時器中斷來了,解析了資料,Lenght此時已經變為0,是以代碼進入了下面這部分,Lenght-- 後變為很大的一個值,此時便出現了問題。

uint8_t Read_RingBuff(uint8_t *rData)
{
 //問題代碼!!!下面這個判斷語句
 if(ringBuff.Head==ringBuff.Tail && ringBuff.Lenght==0)
 {
  return 1;
 }
 *rData=ringBuff.Ring_Buff[ringBuff.Head];
 ringBuff.Head=(ringBuff.Head+1)%200;
 ringBuff.Lenght--;
 return 0;
}
           

解決方案:

例如:采用單個判斷條件判斷隊列的空或者滿!