成人免费无码不卡毛片,亚洲AⅤ无码精品一区二区三区,国产尤物精品视频,久久精品日本亚洲,欧美成人一区三区无码乱码A片,中文字日产幕码一区二区色哟哟,亞洲日韓中文字幕網AV

  • 方案介紹
    • 一、前言
    • 二、實現思路
    • 三、 C語言實現驗證思路
    • 四、STM32串口接收
  • 附件下載
  • 相關推薦
申請入駐 產業(yè)圖譜

STM32單片機采用環(huán)形緩沖區(qū)實現串口中斷數據接收管理

05/07 10:16
1217
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

更多詳細資料請聯系.docx

共1個文件

一、前言

嵌入式系統(tǒng)開發(fā)中,與上位機進行串口通信是非常常見的場景。上位機可以通過串口發(fā)送指令或者數據給嵌入式設備,而嵌入式設備需要可靠地接收并解析這些數據,以執(zhí)行相應的操作。然而,在串口通信過程中,上位機發(fā)送數據的速率往往與嵌入式設備接收和處理數據的速率不一致,這就可能導致數據的丟失或者誤解析。

為了解決這個問題,決定設計并實現一個環(huán)形緩沖區(qū)來進行數據接收管理。環(huán)形緩沖區(qū)是一種高效的數據結構,適用于數據產生速率快于消費速率的場景。它具有固定大小的緩沖區(qū),并且可以循環(huán)利用空間,保證數據的連續(xù)存儲和有效利用。

在本項目中,選擇使用STM32微控制器來實現串口數據接收功能。STM32具有豐富的外設資源和強大的性能,非常適合用于串口通信和數據處理。通過在STM32上實現環(huán)形緩沖區(qū),可以實現以下目標:

(1)數據穩(wěn)定接收:通過使用環(huán)形緩沖區(qū),確保即使在接收數據速率慢于發(fā)送速率的情況下,數據也能夠得到穩(wěn)定的接收,避免數據丟失。

(2)數據緩存和管理:環(huán)形緩沖區(qū)可以作為一個數據緩存區(qū),將接收到的數據暫時存儲起來,以便后續(xù)處理。這樣可以降低數據處理的延遲和復雜性。

(3)數據解析和應用:通過從環(huán)形緩沖區(qū)中讀取數據,并進行解析和處理,嵌入式設備可以根據接收到的數據執(zhí)行相應的操作,如控制外部設備或響應上位機指令。

通過使用環(huán)形緩沖區(qū)管理串口接收的數據,可以實現可靠的數據接收和處理,并提高系統(tǒng)的穩(wěn)定性和可靠性。同時,該方案也適用于其他嵌入式系統(tǒng)和通信場景。

image-20230902144017003

image-20230902144051473

二、實現思路

(1)定義環(huán)形緩沖區(qū)的結構體:首先,需要定義一個表示環(huán)形緩沖區(qū)的結構體,其中包含以下成員變量:

  • 緩沖區(qū)的大?。╟apacity):表示環(huán)形緩沖區(qū)的容量,即可以存儲的最大元素數量。
  • 寫指針(write_ptr):表示當前可寫入數據的位置。
  • 讀指針(read_ptr):表示當前可讀取數據的位置。
  • 數據數組(buffer):用于存儲實際的數據。

(2)初始化環(huán)形緩沖區(qū):在使用環(huán)形緩沖區(qū)之前,需要進行初始化。初始化時,將緩沖區(qū)的大小、寫指針和讀指針都設置為初始位置,通常都是0。

(3)寫入數據:當有新的數據要寫入緩沖區(qū)時,需要執(zhí)行以下操作:

  • 檢查緩沖區(qū)是否已滿,如果已滿則無法寫入新的數據。
  • 將數據寫入當前寫指針所指向的位置。
  • 更新寫指針的位置,通常是將其加1,并考慮到環(huán)形特性,需要進行取模運算。

(4)讀取數據:當需要從緩沖區(qū)中讀取數據時,需要執(zhí)行以下操作:

  • 檢查緩沖區(qū)是否為空,如果為空則無數據可讀取。
  • 讀取當前讀指針所指向的數據。
  • 更新讀指針的位置,通常是將其加1,并考慮到環(huán)形特性,需要進行取模運算。

(5)判斷緩沖區(qū)狀態(tài):為了方便使用和管理緩沖區(qū),可以實現一些用于判斷緩沖區(qū)狀態(tài)的函數,例如:

  • is_full():判斷緩沖區(qū)是否已滿。
  • is_empty():判斷緩沖區(qū)是否為空。

實現環(huán)形緩沖區(qū)時,需要注意:

  • 寫指針和讀指針的位置計算要考慮到環(huán)形特性,即超過緩沖區(qū)容量時需要進行取模運算。
  • 緩沖區(qū)大小要合理選擇,根據實際需求確定,以充分利用內存資源并避免數據丟失。
  • 多線程或中斷環(huán)境下的并發(fā)訪問要考慮數據同步和互斥操作,以避免競爭條件和數據不一致的問題。

通過以上思路,可以在C語言中實現一個簡單高效的環(huán)形緩沖區(qū),用于存儲和管理數據,在數據收發(fā)過程中提高系統(tǒng)的穩(wěn)定性和可靠性。

三、 C語言實現驗證思路

#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE 10

typedef struct {
    int* buffer;      // 緩沖區(qū)數組指針
    int size;         // 緩沖區(qū)大小
    int head;         // 頭部索引
    int tail;         // 尾部索引
} CircularBuffer;

// 創(chuàng)建環(huán)形緩沖區(qū)
CircularBuffer* createCircularBuffer(int size) {
    CircularBuffer* cb = (CircularBuffer*)malloc(sizeof(CircularBuffer));  // 分配內存空間
    cb->buffer = (int*)malloc(sizeof(int) * size);  // 分配緩沖區(qū)數據的內存空間
    cb->size = size;   // 設置緩沖區(qū)大小
    cb->head = 0;      // 初始化頭部索引為0
    cb->tail = 0;      // 初始化尾部索引為0
    return cb;
}

// 銷毀環(huán)形緩沖區(qū)
void destroyCircularBuffer(CircularBuffer* cb) {
    free(cb->buffer);  // 釋放緩沖區(qū)數據的內存空間
    free(cb);          // 釋放緩沖區(qū)結構體的內存空間
}

// 判斷環(huán)形緩沖區(qū)是否已滿
int isCircularBufferFull(CircularBuffer* cb) {
    return ((cb->tail + 1) % cb->size == cb->head);
}

// 判斷環(huán)形緩沖區(qū)是否為空
int isCircularBufferEmpty(CircularBuffer* cb) {
    return (cb->head == cb->tail);
}

// 寫入數據到環(huán)形緩沖區(qū)
void writeData(CircularBuffer* cb, int data) {
    if (isCircularBufferFull(cb)) {  // 如果緩沖區(qū)已滿,則無法寫入數據
        printf("Circular buffer is full. Data cannot be written.n");
        return;
    }
    cb->buffer[cb->tail] = data;  // 將數據寫入緩沖區(qū)的尾部
    cb->tail = (cb->tail + 1) % cb->size;  // 更新尾部索引,循環(huán)利用緩沖區(qū)空間
}

// 從環(huán)形緩沖區(qū)讀取數據
int readData(CircularBuffer* cb) {
    if (isCircularBufferEmpty(cb)) {  // 如果緩沖區(qū)為空,則無數據可讀取
        printf("Circular buffer is empty. No data to read.n");
        return -1;  // 返回一個默認值表示讀取失敗
    }
    int data = cb->buffer[cb->head];  // 從緩沖區(qū)的頭部讀取數據
    cb->head = (cb->head + 1) % cb->size;  // 更新頭部索引,循環(huán)利用緩沖區(qū)空間
    return data;
}

int main() {
    CircularBuffer* cb = createCircularBuffer(BUFFER_SIZE);  // 創(chuàng)建大小為BUFFER_SIZE的環(huán)形緩沖區(qū)

    writeData(cb, 1);  // 寫入數據1
    writeData(cb, 2);  // 寫入數據2
    writeData(cb, 3);  // 寫入數據3

    printf("Read data: %dn", readData(cb));  // 讀取數據并打印
    printf("Read data: %dn", readData(cb));

    writeData(cb, 4);
    writeData(cb, 5);

    printf("Read data: %dn", readData(cb));
    printf("Read data: %dn", readData(cb));
    printf("Read data: %dn", readData(cb));

    destroyCircularBuffer(cb);  // 銷毀環(huán)形緩沖區(qū)

    return 0;
}

四、STM32串口接收

#define BUFFER_SIZE 256

typedef struct {
  uint8_t buffer[BUFFER_SIZE];
  uint16_t head;
  uint16_t tail;
} CircularBuffer;

// 初始化環(huán)形緩沖區(qū)
void CircularBuffer_Init(CircularBuffer* cb) {
  cb->head = 0;
  cb->tail = 0;
}

// 判斷環(huán)形緩沖區(qū)是否已滿
bool CircularBuffer_IsFull(const CircularBuffer* cb) {
  return (cb->head + 1) % BUFFER_SIZE == cb->tail;
}

// 判斷環(huán)形緩沖區(qū)是否為空
bool CircularBuffer_IsEmpty(const CircularBuffer* cb) {
  return cb->head == cb->tail;
}

// 向環(huán)形緩沖區(qū)寫入數據
bool CircularBuffer_Write(CircularBuffer* cb, uint8_t data) {
  if (CircularBuffer_IsFull(cb)) {  // 緩沖區(qū)已滿,無法寫入
    return false;
  }
  
  cb->buffer[cb->head] = data;
  cb->head = (cb->head + 1) % BUFFER_SIZE;
  return true;
}

// 從環(huán)形緩沖區(qū)讀取數據
bool CircularBuffer_Read(CircularBuffer* cb, uint8_t* data) {
  if (CircularBuffer_IsEmpty(cb)) {  // 緩沖區(qū)為空,無數據可讀取
    return false;
  }
  
  *data = cb->buffer[cb->tail];
  cb->tail = (cb->tail + 1) % BUFFER_SIZE;
  return true;
}

// 獲取環(huán)形緩沖區(qū)剩余大小
uint16_t CircularBuffer_GetRemainingSize(const CircularBuffer* cb) {
  if (cb->head >= cb->tail) {
    return BUFFER_SIZE - (cb->head - cb->tail);
  } else {
    return cb->tail - cb->head - 1;
  }
}

// 獲取環(huán)形緩沖區(qū)已寫入大小
uint16_t CircularBuffer_GetWrittenSize(const CircularBuffer* cb) {
  if (cb->head >= cb->tail) {
    return cb->head - cb->tail;
  } else {
    return BUFFER_SIZE - (cb->tail - cb->head - 1);
  }
}

// 從環(huán)形緩沖區(qū)讀取指定長度的數據
bool CircularBuffer_ReadData(CircularBuffer* cb, uint8_t* data, uint16_t length) {
  if (CircularBuffer_GetWrittenSize(cb) < length) {
    return false;  // 緩沖區(qū)中的數據不足
  }
  
  for (uint16_t i = 0; i < length; ++i) {
    if (!CircularBuffer_Read(cb, &data[i])) {
      return false;  // 讀取數據出錯
    }
  }
  
  return true;
}

// 向環(huán)形緩沖區(qū)寫入指定長度的數據
bool CircularBuffer_WriteData(CircularBuffer* cb, const uint8_t* data, uint16_t length) {
  if (CircularBuffer_GetRemainingSize(cb) < length) {
    return false;  // 緩沖區(qū)剩余空間不足
  }
  
  for (uint16_t i = 0; i < length; ++i) {
    if (!CircularBuffer_Write(cb, data[i])) {
      return false;  // 寫入數據出錯
    }
  }
  
  return true;
}



// 示例:STM32串口接收中斷處理函數
void USART_Receive_IRQHandler(void) {
  uint8_t data = USART_ReceiveData(USART1);  // 獲取接收到的數據
  if (!CircularBuffer_Write(&rxBuffer, data)) {
    // 緩沖區(qū)已滿,處理錯誤
  }
}


在代碼中,定義了一個名為CircularBuffer的結構體來表示環(huán)形緩沖區(qū)。包含了一個具有固定大小的數組buffer用于存儲數據,以及頭部指針head和尾部指針tail用于管理數據的讀寫位置。

接下來,實現了一些函數來對環(huán)形緩沖區(qū)進行操作。CircularBuffer_Init函數用于初始化環(huán)形緩沖區(qū);CircularBuffer_IsFullCircularBuffer_IsEmpty函數分別判斷緩沖區(qū)是否已滿和是否為空;CircularBuffer_Write函數用于向緩沖區(qū)寫入數據;CircularBuffer_Read函數用于從緩沖區(qū)讀取數據。

CircularBuffer_GetRemainingSize函數用于獲取環(huán)形緩沖區(qū)的剩余大小,即還能寫入多少個字節(jié)的數據;CircularBuffer_GetWrittenSize函數用于獲取已經寫入到緩沖區(qū)的字節(jié)數;CircularBuffer_ReadData函數用于從環(huán)形緩沖區(qū)讀取指定長度的數據,將其存儲到提供的數據數組中;CircularBuffer_WriteData函數用于向環(huán)形緩沖區(qū)寫入指定長度的數據,從提供的數據數組中復制相應的字節(jié)。

使用這些方便函數,可以更方便地管理環(huán)形緩沖區(qū),實現數據的讀取和寫入。

最后,給出了一個示例,展示在STM32串口接收中斷處理函數中將接收到的數據寫入環(huán)形緩沖區(qū)。在中斷處理函數中,通過USART_ReceiveData函數獲取接收到的數據,調用CircularBuffer_Write函數將數據寫入緩沖區(qū)。

  • 更多詳細資料請聯系.docx
    下載

相關推薦

凤山市| 涟源市| 东莞市| 宝丰县| 石台县| 积石山| 娄烦县| 团风县| 右玉县| 西安市| 瑞安市| 徐水县| 黑河市| 永胜县| 南投县| 东平县| 长寿区| 驻马店市| 家居| 华容县| 安新县| 泗水县| 安泽县| 武胜县| 蓝田县| 宁晋县| 扎兰屯市| 连南| 台东市| 平南县| 镇原县| 突泉县| 河曲县| 台山市| 常山县| 宜良县| 金湖县| 遂昌县| 陈巴尔虎旗| 成都市| 玉山县|