szt1993 发表于 2025-4-25 08:00

8位mcu上写一个环形队列,并给出读写操作示例

8位MCU的具体硬件细节(如中断控制寄存器)可能有所不同,因此以下代码中的中断控制部分需要根据具体的MCU型号进行调整。

//.环形队列实现

#include <stdint.h>
#include <stdbool.h>

#define QUEUE_SIZE 16 // 环形队列大小

typedef struct {
uint8_t buffer;
volatile uint8_t head;
volatile uint8_t tail;
volatile uint8_t count;
} CircularQueue;

// 初始化环形队列
void CircularQueue_Init(CircularQueue* queue) {
queue->head = 0;
queue->tail = 0;
queue->count = 0;
}

// 禁用中断(具体实现依赖于MCU)
void DisableInterrupts(void) {
// 假设有一个全局中断使能寄存器EI,写入0禁用中断
__asm("CLI"); // 示例指令,具体需根据MCU文档
}

// 启用中断(具体实现依赖于MCU)
void EnableInterrupts(void) {
// 假设有一个全局中断使能寄存器EI,写入1启用中断
__asm("SEI"); // 示例指令,具体需根据MCU文档
}

// 写入环形队列
bool CircularQueue_Write(CircularQueue* queue, uint8_t data) {
DisableInterrupts();

if (queue->count == QUEUE_SIZE) {
// 队列满
EnableInterrupts();
return false;
}

queue->buffer = data;
queue->tail = (queue->tail + 1) % QUEUE_SIZE;
queue->count++;

EnableInterrupts();
return true;
}

// 从环形队列读取
bool CircularQueue_Read(CircularQueue* queue, uint8_t* data) {
DisableInterrupts();

if (queue->count == 0) {
// 队列空
EnableInterrupts();
return false;
}

*data = queue->buffer;
queue->head = (queue->head + 1) % QUEUE_SIZE;
queue->count--;

EnableInterrupts();
return true;
}

中断和普通调用示例

#include <stdint.h>
#include <stdbool.h>

#define QUEUE_SIZE 16 // 环形队列大小

typedef struct {
uint8_t buffer;
volatile uint8_t head;
volatile uint8_t tail;
volatile uint8_t count;
} CircularQueue;

// 初始化环形队列
void CircularQueue_Init(CircularQueue* queue) {
queue->head = 0;
queue->tail = 0;
queue->count = 0;
}

// 禁用中断(具体实现依赖于MCU)
void DisableInterrupts(void) {
// 假设有一个全局中断使能寄存器EI,写入0禁用中断
__asm("CLI"); // 示例指令,具体需根据MCU文档
}

// 启用中断(具体实现依赖于MCU)
void EnableInterrupts(void) {
// 假设有一个全局中断使能寄存器EI,写入1启用中断
__asm("SEI"); // 示例指令,具体需根据MCU文档
}

// 写入环形队列
bool CircularQueue_Write(CircularQueue* queue, uint8_t data) {
DisableInterrupts();

if (queue->count == QUEUE_SIZE) {
// 队列满
EnableInterrupts();
return false;
}

queue->buffer = data;
queue->tail = (queue->tail + 1) % QUEUE_SIZE;
queue->count++;

EnableInterrupts();
return true;
}

// 从环形队列读取
bool CircularQueue_Read(CircularQueue* queue, uint8_t* data) {
DisableInterrupts();

if (queue->count == 0) {
// 队列空
EnableInterrupts();
return false;
}

*data = queue->buffer;
queue->head = (queue->head + 1) % QUEUE_SIZE;
queue->count--;

EnableInterrupts();

return true;
}


#include <avr/interrupt.h> // 假设使用AVR MCU,具体头文件根据MCU型号调整
CircularQueue queue;
// 中断服务程序示例
ISR(TIMER1_COMPA_vect) {
uint8_t data = 0xAB; // 示例数据
if (CircularQueue_Write(&queue, data)) {
// 写入成功
}
}
int main(void) {
// 初始化队列
CircularQueue_Init(&queue);

// 配置定时器中断(具体配置根据MCU型号和需求调整)
// ...

// 使能全局中断
sei(); // AVR MCU的使能全局中断指令

// 主循环
while (1) {
uint8_t data;
if (CircularQueue_Read(&queue, &data)) {
// 处理读取到的数据
}

// 其他任务...
}

return 0;
}

beacherblack 发表于 2025-5-3 22:03

8 位 MCU 的内存资源十分宝贵,要根据实际需求精确计算环形队列所需的内存大小。避免分配过大的内存空间造成浪费,同时也要防止分配过小导致队列频繁溢出。

updownq 发表于 2025-5-3 23:18

使用uint8_t表示队列中的数据,以节省内存。
使用uint16_t表示指针和计数器,以避免溢出问题。

ingramward 发表于 2025-5-4 00:51

8位MCU内存资源有限,队列大小需根据实际需求调整,避免过大占用RAM。

yorkbarney 发表于 2025-5-4 19:49

串口接收中断中仅将数据写入环形队列,而非直接处理
页: [1]
查看完整版本: 8位mcu上写一个环形队列,并给出读写操作示例