在嵌入式專案開發中,經常會涉及到資料的互動,比如汽車電子產品中的CAN通信,資料的收發經常是偶發的,一般有事件產生,就會回觸發一些網路資料,這些網路資料在總線上往往是偶爾產生的,而且可能會集中觸發,但是對于單個處理器,是不能及時處理多個集中觸發的任務的,因此必須要借助資料緩沖技術,當然首先需要硬體資源支持,再才能通過軟體依次處理這些緩沖資料,
我們先來看一下CAN總線系統:

我們還是以實際專案舉例,比如選用NXP KEA128的單片機,其CAN接收、發送緩沖區特性描述如下:
? 采用FIFO 存盤方案的5個接識訓沖區
? 3 個發送緩沖區,采用“本地優先級”概念進行內部排序
這里相當于接收有5個緩沖區,發送有3個緩沖區,接收一般多于發送,因為發送是主動的,可控的;而接收是被動的,不可控的,
接收報文緩沖采用如下的結構:

從Rx0到Rx4,采用FIFO也就是先進先出的原則,硬體接識訓沖器有5個,也就是說這款處理器,在一個處理周期內,底層最多存放5個資料幀,也就是說同一時間內只能接收5個資料幀,多了就會被覆寫掉,
接收報文中斷函式
void MSCAN_RX_Handler(void)
{
stMsgBuf * pBuf;
......
pBuf = &(RxMsgBuf[RMB_i]);
pBuf->Dat[0] = MSCAN_REDSR0;
pBuf->Dat[1] = MSCAN_REDSR1;
pBuf->Dat[2] = MSCAN_REDSR2;
pBuf->Dat[3] = MSCAN_REDSR3;
pBuf->Dat[4] = MSCAN_REDSR4;
pBuf->Dat[5] = MSCAN_REDSR5;
pBuf->Dat[6] = MSCAN_REDSR6;
pBuf->Dat[7] = MSCAN_REDSR7;
pBuf->DatLen = (MSCAN_RDLR & 0x0F);
pBuf->IDReg[0] = MSCAN_RSIDR0;
pBuf->IDReg[1] = MSCAN_RSIDR1;
RMB_i++;
if (RMB_i >= 5)
{
RMB_i = 0;
}
......
}
依靠中斷函式接收到的所有報文,盡量要在一個時間片里全部處理完成,如果處理不完,就必須用到二級快取,二級快取的空間可以比實際硬體快取空間定義得大一點,比如這里的RxMsgBuf[RMB_i],可以定義8到16個緩沖空間,那么接收中斷函式就可以改成:
void MSCAN_RX_Handler(void)
{
stMsgBuf * p2Buf;
......
p2Buf = &(RxMsg2Buf[RM2B_i]);
p2Buf->Dat[0] = MSCAN_REDSR0;
p2Buf->Dat[1] = MSCAN_REDSR1;
p2Buf->Dat[2] = MSCAN_REDSR2;
p2Buf->Dat[3] = MSCAN_REDSR3;
p2Buf->Dat[4] = MSCAN_REDSR4;
p2Buf->Dat[5] = MSCAN_REDSR5;
p2Buf->Dat[6] = MSCAN_REDSR6;
p2Buf->Dat[7] = MSCAN_REDSR7;
p2Buf->DatLen = (MSCAN_RDLR & 0x0F);
p2Buf->IDReg[0] = MSCAN_RSIDR0;
p2Buf->IDReg[1] = MSCAN_RSIDR1;
RM2B_i++;
if (RM2B_i >= 16)
{
RM2B_i = 0;
}
......
}
這里的“二級快取”,實際上是一個純軟體概念,就是為了解決如果一個時間片處理不完當前收到的所有報文,是可以累積到下個時間片再處理的,中斷函式只負責把收到的報文往二級快取里放,當然這里放滿了16個的話,也會產生二級快取溢位,所以應用層的處理函式也需要及時去提取報文做處理,
與之相對應的發送報文緩沖采用如下的結構:

其實和接收報文的緩沖原理上差不多,只是優先級可以自己配置,相對接收實作起來會比較簡單,也不需要建立二級快取,因為完全可以自己控制發送流量,
原文:https://www.toutiao.com/i6951918761750315553/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/281712.html
標籤:其他
