對環形緩沖區進行進一步的優化和功能擴展,以應對更復雜的實際應用場景,特別是針對 CAN 總線消息處理的場景。
一、優化點
1:動態配置環形緩沖區大小在原始實現中,我們固定了緩沖區大小為 RINGBUFF_LEN = 64。這種方式雖然簡單,但在實際應用中缺乏靈活性。例如,在資源受限的嵌入式系統中,我們可能需要根據內存情況和數據流量動態調整緩沖區大小。
我們通過修改初始化函數,引入動態緩沖區容量配置:
void ring_buffer_init(can_ring_buffer_t *rb, can_receive_message_struct *buffer, uint32_t capacity, uint8_t mode)
{
rb->buffer = buffer;
rb->in_index = 0;
rb->out_index = 0;
rb->length = 0;
rb->capacity = capacity; // 動態配置緩沖區大小
rb->mode = mode;
}
在 main 函數中,我們可以通過調整傳入的 capacity 參數,輕松設置緩沖區大小:
can_receive_message_struct recv_buf[50]; can_ring_buffer_t can_ring_buffer;ring_buffer_init(&can_ring_buffer, recv_buf, 50, RING_BUFFER_MODE_NORMAL);
這種方式使緩沖區大小完全可控,能夠適應不同場景下的需求。
二、優化點
2:增強錯誤處理機制在實際系統運行中,緩沖區溢出或數據丟失是常見的問題。我們對寫入函數進行了改進,增加了對緩沖區狀態的詳細檢查和處理:
int ring_buffer_write(can_ring_buffer_t *rb, can_receive_message_struct *msg)
{
if (rb->length < rb->capacity)
{
rb->buffer[rb->in_index] = *msg;
rb->in_index = (rb->in_index + 1) % rb->capacity;
rb->length++;
return 1;
}
else
{
if (rb->mode == RING_BUFFER_MODE_OVERWRITE) {
rb->buffer[rb->in_index] = *msg;
rb->in_index = (rb->in_index + 1) % rb->capacity;
rb->out_index = (rb->out_index + 1) % rb->capacity;
return 1;
}
else
{
return 0; // 在正常模式下,丟棄數據
}
}}
在緩沖區滿的情況下,根據模式決定是否覆蓋舊數據。
我們還提供了狀態檢查函數:
int ring_buffer_is_empty(can_ring_buffer_t *rb)
{
return rb->length == 0;
}
int ring_buffer_is_full(can_ring_buffer_t *rb)
{
return rb->length == rb->capacity;
}
這些函數可以幫助開發者實時監控緩沖區狀態,及時發現潛在問題。
三、優化點
3:提供緩沖區狀態監控功能為了更好地理解緩沖區的使用情況,我們增加了緩沖區占用百分比計算功能:
float ring_buffer_occupancy(can_ring_buffer_t *rb) {
return (float)rb->length / rb->capacity * 100.0f;
}
在 main 函數中,我們可以通過以下方式輸出緩沖區占用情況:
printf("Buffer occupancy: %.2f%%\n", ring_buffer_occupancy(&can_ring_buffer));
這個功能對于系統調優和資源分配具有重要意義。
四、優化點
4:改進消息處理流程我們完善了消息讀取和處理函數,使其能夠批量處理緩沖區中的消息:
int read_messages_from_buffer(can_ring_buffer_t *rb)
{
can_receive_message_struct msg;
int read_count = 0;
while (!ring_buffer_is_empty(rb))
{
if (ring_buffer_read(rb, &msg))
{
// 處理讀取到的 CAN 消息
printf("Received CAN message:\n"); printf("SFID: 0x%X, EFID: 0x%X, FF: %d, FT: %d, DLEN: %d\n", msg.rx_sfid, msg.rx_efid, msg.rx_ff, msg.rx_ft, msg.rx_dlen);
printf("Data: ");
for (int i = 0; i < msg.rx_dlen; i++)
{
printf("%d ", msg.rx_data[i]);
}
printf("\n");
read_count++;
}
}
return read_count;
}
在 main 函數中調用:
int read_count = read_messages_from_buffer(&can_ring_buffer);
printf("Total messages read: %d\n", read_count);
這種批量處理方式提高了系統效率。
五、完整代碼實現
以下是優化后的完整代碼實現:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> // 用于動態內存分配#define RING_BUFFER_MODE_OVERWRITE 1
#define RING_BUFFER_MODE_NORMAL 0// CAN接收消息結構體
typedef struct
{
uint32_t rx_sfid; /*!< standard format frame identifier */
uint32_t rx_efid; /*!< extended format frame identifier */
uint8_t rx_ff; /*!< format of frame, standard or extended format */
uint8_t rx_ft; /*!< type of frame, data or remote */
uint8_t rx_dlen; /*!< data length */
uint8_t rx_data[8]; /*!< receive data */
uint8_t rx_fi; /*!< filtering index */}
can_receive_message_struct;// 環形緩沖區結構體
typedef struct
{
can_receive_message_struct *buffer; // 指向緩沖區的指針
uint32_t in_index;
uint32_t out_index;
uint32_t length;
uint32_t capacity;
uint8_t mode;
} can_ring_buffer_t;// 初始化環形緩沖區void ring_buffer_init(can_ring_buffer_t *rb, can_receive_message_struct *buffer, uint32_t capacity, uint8_t mode)
{
rb->buffer = buffer;
rb->in_index = 0;
rb->out_index = 0;
rb->length = 0;
rb->capacity = capacity; // 動態配置緩沖區大小
rb->mode = mode;
}// 寫入數據int ring_buffer_write(can_ring_buffer_t *rb, can_receive_message_struct *msg)
{
if (rb->length < rb->capacity)
{
rb->buffer[rb->in_index] = *msg;
rb->in_index = (rb->in_index + 1) % rb->capacity;
rb->length++;
return 1;
}
else
{
if (rb->mode == RING_BUFFER_MODE_OVERWRITE) {
rb->buffer[rb->in_index] = *msg;
rb->in_index = (rb->in_index + 1) % rb->capacity;
rb->out_index = (rb->out_index + 1) % rb->capacity;
return 1;
}
else
{
return 0; // 在正常模式下,丟棄數據
}
}
}// 讀取數據int ring_buffer_read(can_ring_buffer_t *rb, can_receive_message_struct *msg)
{
if (rb->length > 0)
{
*msg = rb->buffer[rb->out_index];
rb->out_index = (rb->out_index + 1) % rb->capacity;
rb->length--;
return 1;
}
else
{
return 0; // 如果沒有數據,返回0
}
}// 檢查是否為空int ring_buffer_is_empty(can_ring_buffer_t *rb)
{
return rb->length == 0;
}// 檢查是否已滿int ring_buffer_is_full(can_ring_buffer_t *rb) {
return rb->length == rb->capacity;}// 獲取緩沖區占用的百分比float ring_buffer_occupancy(can_ring_buffer_t *rb) {
return (float)rb->length / rb->capacity * 100.0f;
}// 讀取并處理緩沖區中的消息int read_messages_from_buffer(can_ring_buffer_t *rb)
{
can_receive_message_struct msg;
int read_count = 0; while (!ring_buffer_is_empty(rb))
{
if (ring_buffer_read(rb, &msg))
{
// 處理讀取到的 CAN 消息
printf("Received CAN message:\n");
printf("SFID: 0x%X, EFID: 0x%X, FF: %d, FT: %d, DLEN: %d\n", msg.rx_sfid, msg.rx_efid, msg.rx_ff, msg.rx_ft, msg.rx_dlen);
printf("Data: "); for (int i = 0; i < msg.rx_dlen; i++)
{
printf("%d ", msg.rx_data[i]);
}
printf("\n");
read_count++;
}
} return read_count;}// 模擬接收CAN消息的中斷處理函數void CAN1_IRQHandler(can_ring_buffer_t *rb) {
can_receive_message_struct temp; // 模擬從硬件獲取 CAN 消息
temp.rx_sfid = 0x123;
temp.rx_efid = 0x1ABC;
temp.rx_ff = 0;
temp.rx_ft = 1;
temp.rx_dlen = 8;
for (int i = 0; i < 8; i++)
{
temp.rx_data[i] = i;
}
temp.rx_fi = 1;
if (rb->length < rb->capacity)
{
ring_buffer_write(rb, &temp);
}
else
{
if (rb->mode == RING_BUFFER_MODE_OVERWRITE) {
ring_buffer_write(rb, &temp);
}
}
}int main(void)
{
// 定義接收緩存數組,容量為50
can_receive_message_struct recv_buf[50]; // 初始化環形緩沖區,設置容量為50,正常模式
can_ring_buffer_t can_ring_buffer;
ring_buffer_init(&can_ring_buffer, recv_buf, 50, RING_BUFFER_MODE_NORMAL); // 模擬接收10條CAN消息
for (int i = 0; i < 10; i++)
{
CAN1_IRQHandler(&can_ring_buffer);
} // 輸出緩沖區的占用情況
printf("Buffer occupancy: %.2f%%\n", ring_buffer_occupancy(&can_ring_buffer)); // 讀取并處理緩沖區中的消息
int read_count = read_messages_from_buffer(&can_ring_buffer);
printf("Total messages read: %d\n", read_count); return 0;}
六、未來擴展方向
- 支持多線程環境:在多線程系統中,我們可以在寫入和讀取操作時添加互斥鎖(mutex),防止數據競爭。例如:
// 在寫入函數中添加鎖保護
pthread_mutex_lock(&rb->mutex);// 寫入操作
pthread_mutex_unlock(&rb->mutex);
- 進一步優化消息處理:可以根據 CAN 消息的內容添加過濾和優先級處理。例如,對特定 ID 的消息進行優先處理。
- 錯誤日志和統計:可以添加日志記錄功能,記錄緩沖區溢出、數據丟失等事件,便于系統調試和優化。通過這些優化和擴展,我們的環形緩沖區實現變得更加健壯和實用,能夠更好地適應實際嵌入式系統中的 CAN 消息處理需求。