項目使用stm8l051f3做主控,CC2500做數據接收,不發送。
跑飛的現象就是,剛開始能運行,經過一段未知長度的時間,有可能是3分鍾,有可能是30分鍾,指示燈不再閃爍,中斷按鍵單片機無反應。
接入調試器發現跑到了一個非常大的地址,已經超過了mcu的內部flash空間。可以確定是程序跑飛。
經驗是:
程序跑飛,查條件語句是否都有做處理。
程序跑飛,查內存溢出。
查了好久,查出是內存溢出導致。
因為發送端發送的數據固定是32字節,所以在接收端只開辟了一個32字節的buffer去讀取收到的數據。
/*******************************************************************************
* @brief GDO2中斷處理函
* @param None
* @retval None ****************************************************************Author:Liming**/ void GDO2_Int(void) { uint8_t temp; unsigned char RecvBuffer[0x20]={0};//開辟32字節緩存 unsigned char RecvLength; if(EXTI_GetITStatus(EXTI_IT_Pin6) != RESET) { EXTI_ClearITPendingBit(EXTI_IT_Pin6); DelayNms(1);//等待接收完成 RecvLength = CC2500Recv(RecvBuffer); //獲取收到的數據長度 temp = ProPacketCheck(RecvBuffer,RecvLength,0x0001,0x0003);//數據完整性校驗 if((temp == 0x04)||(temp==0xff)) // 本機和廣播信息需要處理 {
//數據處理
CC2500SetState(CC2500_STATUS_POWERDOWN_LEVEL2); } else CC2500SetState(CC2500_STATUS_RECEIVE); } }
//接收數據 unsigned char CC2500Recv(unsigned char *Buffer,unsigned char Mode) { unsigned char Result=0x00,Status=0x00; switch(CC2500State) { case 0x00: case 0x01: if(CC2500State) Delayms(0x07); else Delayus(0x30); Status=CC2500SpiReadStatus(RXBYTES); if(Status&0x80)//如果數據長度超過64字節 { CC2500SpiReadBuffer(FIFO,Buffer,0x40);//讀取64字節 Result=0x40; } else if(Status&0x7F) { CC2500SpiReadBuffer(FIFO,Buffer,Status&0x7F);//讀取收到的數據 Result=Status&0x7F; } CC2500SetState(Mode); break; } return Result;//返回讀取的數據長度 }
但由於無線信號的干擾,CC2500可能會收到大於32字節的數據(雖然不是本系統需要的),
導致在從cc2500取出的時候,存入buffer的長度超過開辟的buffer空間。
解決辦法1:既然知道是32字節數據,可以在
CC2500Recv接收函數里只接收32字節。
if(Status&0x80)//如果數據長度超過64字節 { CC2500SpiReadBuffer(FIFO,Buffer,0x20);//讀取32字節 Result=0x20; } else if(Status&0x7F) { CC2500SpiReadBuffer(FIFO,Buffer,0x20);//讀取收到的數據 Result=0x20; }
解決辦法2:
GDO2_Int函數里開辟64字節空間即便是收到最多的數據也不會超出緩存空間。
unsigned char RecvBuffer[0x40]={0};//開辟64字節緩存
有了這次的程序跑飛的處理經歷,再次驗證了程序跑飛大部分都是內存溢出導致的說法。