• 消息队列缓存,以蓝牙消息服务为例


    前言

    消息队列缓存,支持阻塞、非阻塞模式;支持协议、非协议模式

    可自定义消息结构体数据内容

    使用者只需设置一些宏定义、调用相应接口即可

    这里我用蓝牙消息服务举例

    有纰漏请指出,转载请说明。

    学习交流请发邮件 1280253714@qq.com

    原理讲解

    队列采用"生产者-消费者"模式,

    当接收数据时,生产者即为外部输入,输入的消息入列;消费者即为消息处理函数,处理消息前先出列,然后消费者处理出列的消息

    当发送数据时,生产者为消息产生的任务,该任务将产生的消息入列;消费者为消息发送任务,该任务将待发送的消息出列并发送。

    接口

    接收消息接口

    以蓝牙接收消息服务为例

    接收消息处理接口

    这里我开了一个定时任务来处理消息

    待发送消息装载接口

    由任务产生消息并调用装载函数,以下提供透明传输和协议传输接口

    待发送消息发送接口

    以蓝牙发送消息服务为例,这里我先进行出列判断,如果数据成功出列,则将消息通过蓝牙的内核发送出去

    代码

    msg.h

    1. #ifndef _MSG_H
    2. #define _MSG_H
    3. #include "includes.h"
    4. #define MsgProtocol 1 //是否使用协议
    5. #define MsgBlock 1 //消息是否阻塞,即当队列已满时,是否继续入列,
    6. //入列会导致前面接收到且未来得及处理的数据被覆盖
    7. #define QueueMaxSize 5 //队列最大存放的数据个数
    8. #define MsgMaxSize 64 //单帧数据最大长度
    9. #define MsgPrefix 0xA5
    10. #define MsgStuffix 0x5A
    11. #define MsgIndexPrefix 0
    12. #define MsgIndexLen 1
    13. #define MsgIndexCmdId 2
    14. #define MsgIndexCmd 3
    15. #define MsgIndexDataBase 4
    16. typedef enum //队列当前状态
    17. {
    18. eQueueEmpty, //队列为空
    19. eQueueNormal, //队列不为空
    20. eQueueFull, //队列已满
    21. } QueueState_E;
    22. typedef enum //出列的数据情况
    23. {
    24. eDataEmpty, //数据为空
    25. eDataNormal, //数据不为空
    26. } DeQueueState_E;
    27. typedef struct //数据格式
    28. {
    29. u8 u8Len;
    30. u8 szData[MsgMaxSize];
    31. } MSG_S;
    32. typedef struct //队列结构体
    33. {
    34. u32 msgCnt;
    35. u32 msgProcCnt;
    36. MSG_S dataEnQueue;
    37. MSG_S dataDeQueue;
    38. MSG_S data[QueueMaxSize];
    39. QueueState_E state; //队列当前状态
    40. u8 front; //队头
    41. u8 rear; //队尾
    42. u8 size; //队列大小
    43. }MSG_ATTR_S;
    44. typedef struct //蓝牙消息结构体
    45. {
    46. MSG_ATTR_S stRx;
    47. MSG_ATTR_S stTx;
    48. }BLE_MSG_S;
    49. QueueState_E MsgQueueStateDetermine(MSG_ATTR_S *queue);
    50. void MsgEnQueue(MSG_ATTR_S *queue, MSG_S *data);
    51. DeQueueState_E MsgDeQueue(MSG_ATTR_S *queue);
    52. void MsgRxDataProc(void);
    53. int MsgProcCrc(u8 *pRxData);
    54. void LoadTransparentMsg(MSG_ATTR_S *queue, MSG_S *txMsg);
    55. void LoadProtocalMsg(MSG_ATTR_S *queue, MSG_S *txMsg);
    56. void BleMsgInit(void);
    57. extern MSG_ATTR_S stRxQueue;
    58. extern BLE_MSG_S stBle;
    59. #endif

    msg.c

    1. #include "includes.h"
    2. BLE_MSG_S stBle;
    3. int MsgProcCrc(u8 *pRxData)
    4. {
    5. u8 i = 0;
    6. u8 crc = 0;
    7. u8 size = pRxData[MsgIndexLen];
    8. if ((pRxData[MsgIndexPrefix] == MsgPrefix) && (pRxData[size - 1] == MsgStuffix))
    9. {
    10. for (i = 1; i <= size - 3; i++)
    11. {
    12. crc += pRxData[i];
    13. }
    14. if (crc == pRxData[size - 2])
    15. {
    16. return 0;
    17. }
    18. }
    19. return -1;
    20. }
    21. QueueState_E MsgQueueStateDetermine(MSG_ATTR_S *queue)
    22. {
    23. #if MsgBlock
    24. if (queue->size == 0)
    25. {
    26. return eQueueEmpty;
    27. }
    28. else if (queue->size == QueueMaxSize)
    29. {
    30. return eQueueFull;
    31. }
    32. else
    33. {
    34. return eQueueNormal;
    35. }
    36. #else
    37. if (queue->msgCnt == 0)
    38. {
    39. return eQueueEmpty;
    40. }
    41. else if ( queue->msgCnt > 0)
    42. {
    43. return eQueueNormal;
    44. }
    45. #endif
    46. }
    47. void MsgEnQueue(MSG_ATTR_S *queue, MSG_S *data)
    48. {
    49. #if MsgBlock
    50. if (queue->size == QueueMaxSize)
    51. {
    52. return;
    53. }
    54. #endif
    55. queue->dataEnQueue = *data;
    56. queue->data[queue->rear] = queue->dataEnQueue;
    57. queue->size++;
    58. queue->msgCnt++;
    59. queue->rear++;
    60. if (queue->rear == QueueMaxSize)
    61. {
    62. queue->rear = 0;
    63. }
    64. queue->state = MsgQueueStateDetermine(queue);
    65. }
    66. DeQueueState_E MsgDeQueue(MSG_ATTR_S *queue)
    67. {
    68. if (queue->size == 0)
    69. {
    70. return eDataEmpty;
    71. }
    72. queue->dataDeQueue = queue->data[queue->front];
    73. memset(&queue->data[queue->front], 0, sizeof(queue->data[queue->front]));
    74. queue->size--;
    75. queue->front++;
    76. if (queue->front == QueueMaxSize)
    77. {
    78. queue->front = 0;
    79. }
    80. queue->state = MsgQueueStateDetermine(queue);
    81. return eDataNormal;
    82. }
    83. void MsgRxDataProc(void)
    84. {
    85. if (stBle.stRx.state != eQueueEmpty)
    86. {
    87. if (MsgDeQueue(&stBle.stRx) != eDataEmpty)
    88. {
    89. stBle.stRx.msgProcCnt++;
    90. }
    91. }
    92. }
    93. void LoadTransparentMsg(MSG_ATTR_S *queue, MSG_S *txMsg)
    94. {
    95. MsgEnQueue(queue, txMsg);
    96. }
    97. void LoadProtocalMsg(MSG_ATTR_S *queue, MSG_S *txMsg)
    98. {
    99. u8 i;
    100. u8 checkSum = 0;
    101. MSG_S tmpMsg;
    102. memset(&tmpMsg, 0, sizeof(MSG_S));
    103. for (i = 0; i < txMsg->u8Len; i++)
    104. {
    105. checkSum += txMsg->szData[i];
    106. tmpMsg.szData[i+2] = txMsg->szData[i];
    107. }
    108. tmpMsg.szData[MsgIndexPrefix] = MsgPrefix;
    109. tmpMsg.szData[txMsg->u8Len + 3] = MsgStuffix;
    110. tmpMsg.szData[MsgIndexLen] = txMsg->u8Len + 4;
    111. checkSum += tmpMsg.szData[MsgIndexLen];
    112. tmpMsg.szData[txMsg->u8Len + 2] = checkSum;
    113. tmpMsg.u8Len = txMsg->u8Len + 4;
    114. MsgEnQueue(queue, &tmpMsg);
    115. }
    116. void BleMsgInit(void)
    117. {
    118. memset(&stBle, 0, sizeof(BLE_MSG_S));
    119. }

    一个图图

  • 相关阅读:
    DOM 文档对象模型(Document Object Model), W3C 组织推荐的处理可扩展标记语言的标准编程接口。
    Java GC
    普中51单片机学习(AD转换)
    学术论文写作以及discussions/results与conclusion的区别
    内网渗透之Windows反弹shell(二)
    context源码学习
    代码优雅之道——断言 + Springboot统一异常处理
    如何将多个PDF文件合并一步完成?
    QJsonValue的学习
    YOLO V1详解
  • 原文地址:https://blog.csdn.net/weixin_45817947/article/details/133799648