[开发工具] 8位mcu上写一个环形队列,并给出读写操作示例

[复制链接]
1136|13
 楼主| szt1993 发表于 2025-4-25 08:00 | 显示全部楼层 |阅读模式
8位MCU的具体硬件细节(如中断控制寄存器)可能有所不同,因此以下代码中的中断控制部分需要根据具体的MCU型号进行调整。

  1. //.环形队列实现

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

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

  5. typedef struct {
  6. uint8_t buffer[QUEUE_SIZE];
  7. volatile uint8_t head;
  8. volatile uint8_t tail;
  9. volatile uint8_t count;
  10. } CircularQueue;

  11. // 初始化环形队列
  12. void CircularQueue_Init(CircularQueue* queue) {
  13. queue->head = 0;
  14. queue->tail = 0;
  15. queue->count = 0;
  16. }

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

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

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

  30. if (queue->count == QUEUE_SIZE) {
  31. // 队列满
  32. EnableInterrupts();
  33. return false;
  34. }

  35. queue->buffer[queue->tail] = data;
  36. queue->tail = (queue->tail + 1) % QUEUE_SIZE;
  37. queue->count++;

  38. EnableInterrupts();
  39. return true;
  40. }

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

  44. if (queue->count == 0) {
  45. // 队列空
  46. EnableInterrupts();
  47. return false;
  48. }

  49. *data = queue->buffer[queue->head];
  50. queue->head = (queue->head + 1) % QUEUE_SIZE;
  51. queue->count--;

  52. EnableInterrupts();
  53. return true;
  54. }

  55. 中断和普通调用示例

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

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

  59. typedef struct {
  60. uint8_t buffer[QUEUE_SIZE];
  61. volatile uint8_t head;
  62. volatile uint8_t tail;
  63. volatile uint8_t count;
  64. } CircularQueue;

  65. // 初始化环形队列
  66. void CircularQueue_Init(CircularQueue* queue) {
  67. queue->head = 0;
  68. queue->tail = 0;
  69. queue->count = 0;
  70. }

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

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

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

  84. if (queue->count == QUEUE_SIZE) {
  85. // 队列满
  86. EnableInterrupts();
  87. return false;
  88. }

  89. queue->buffer[queue->tail] = data;
  90. queue->tail = (queue->tail + 1) % QUEUE_SIZE;
  91. queue->count++;

  92. EnableInterrupts();
  93. return true;
  94. }

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

  98. if (queue->count == 0) {
  99. // 队列空
  100. EnableInterrupts();
  101. return false;
  102. }

  103. *data = queue->buffer[queue->head];
  104. queue->head = (queue->head + 1) % QUEUE_SIZE;
  105. queue->count--;

  106. EnableInterrupts();

  107. return true;
  108. }


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

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

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

  125. // 主循环
  126. while (1) {
  127. uint8_t data;
  128. if (CircularQueue_Read(&queue, &data)) {
  129. // 处理读取到的数据
  130. }

  131. // 其他任务...
  132. }

  133. return 0;
  134. }

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 | 显示全部楼层
串口接收中断中仅将数据写入环形队列,而非直接处理
yeates333 发表于 2025-5-6 10:26 | 显示全部楼层
读操作前检查队列是否为空,避免读取无效数据。
1988020566 发表于 2025-5-6 12:20 | 显示全部楼层
支持一次性读写多个元素,减少函数调用次数。
yorkbarney 发表于 2025-5-6 14:08 | 显示全部楼层
优先选择占用内存小的数据类型。在 8 位 MCU 中,char类型(通常为 1 字节)是常用的选择,而尽量避免使用int(可能占用 2 字节或更多)等占用空间较大的数据类型,除非确实需要。
wangdezhi 发表于 2025-5-6 16:58 | 显示全部楼层
尽量减少不必要的函数调用和条件判断,提高代码执行效率。
fengm 发表于 2025-5-6 19:02 | 显示全部楼层
读写指针需通过模运算实现循环              
uiint 发表于 2025-5-6 21:30 | 显示全部楼层
代码应尽量避免依赖特定 8 位 MCU 的硬件特性,如特定的寄存器操作、中断向量表等。如果需要使用硬件相关的功能,应进行封装,使代码具有更好的可移植性。
timfordlare 发表于 2025-5-11 11:07 | 显示全部楼层
若需动态调整队列大小,需改用指针实现
tabmone 发表于 2025-5-11 17:06 | 显示全部楼层
需综合考虑内存限制、数据类型、溢出处理、中断安全等关键因素。
小小蚂蚁举千斤 发表于 2025-5-22 12:56 | 显示全部楼层
循环队列还是非常有必要的额
您需要登录后才可以回帖 登录 | 注册

本版积分规则

350

主题

3021

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部