环形队列中断会导致数据错误吗

主循环里面写环形队列,中断里面读取,如果主循环写数据的时候,发生了中断,写的过程被打断,那会出现数据错误吗,我的答案是不会,看看环形队列的结构

#define DEFINE_QUEUE_TYPE(NAME, TYPE, SIZE)                              \
    typedef struct {                                                     \
        TYPE data[SIZE];                                                 \
        int front;                                                       \
        int rear;                                                        \
        int size;                                                        \
        int max_size;                                                    \
    } NAME##_queue;                                                      \
                                                                         \
    void NAME##_queue_init(NAME##_queue *queue) {                        \
        queue->front = 0;                                                \
        queue->rear = -1;                                                \
        queue->size = 0;                                                 \
        queue->max_size = SIZE;                                          \
    }                                                                    \
                                                                         \
    bool NAME##_queue_is_empty(NAME##_queue *queue) {                    \
        return queue->size == 0;                                         \
    }                                                                    \
                                                                         \
    bool NAME##_queue_is_full(NAME##_queue *queue) {                     \
        return queue->size == queue->max_size;                           \
    }                                                                    \
                                                                         \
    bool NAME##_queue_push(NAME##_queue *queue, TYPE value) {            \
        if (NAME##_queue_is_full(queue)) {                               \
            return false;                                                \
        }                                                                \
        queue->rear = (queue->rear + 1) % queue->max_size;               \
        queue->data[queue->rear] = value;                                \
        queue->size++;                                                   \
        return true;                                                     \
    }                                                                    \
    bool NAME##_queue_pop(NAME##_queue *queue) {                         \
        if (NAME##_queue_is_empty(queue)) {                              \
            return false;                                                \
        }                                                                \
        queue->front = (queue->front + 1) % queue->max_size;             \
        queue->size--;                                                   \
        return true;                                                     \
    }                                                                    \
    bool NAME##_queue_front(NAME##_queue *queue, TYPE *value) {          \
        if (NAME##_queue_is_empty(queue)) {                              \
            return false;                                                \
        }                                                                \
        *value = queue->data[queue->front];                              \
        return true;                                                     \
    }

这是一个环形队列的模板,结构体里面包含数据缓存,读指针和写指针。

在主循环里面写的时候用push操作,push里面首先会检查队列是否满,如果满了,则不会进行写入操作。

while (1)
  {
    RUN_BY_LIMIT_BLOCK(2,
      for (int i = 0; i < PUSH_TIMES; i++){
          u16_queue_push(&test_queue, TEST_NUMBER1);
          u16_queue_push(&test_queue, TEST_NUMBER2);
      }
    )
  }

在中断里面读取的时候用front和pop操作,front里面会判断队列是否为空,不为空才会进行读取。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
  if (htim->Instance == TIM10) {
    RUN_BY_LIMIT_BLOCK(1000, 
      SEGGER_RTT_printf(0, "tim10 interrupt!\n")
    )
    uint16_t tmp;
    while (u16_queue_front(&test_queue, &tmp) == true) {
      u16_queue_pop(&test_queue);
      if (tmp != TEST_NUMBER1 && tmp != TEST_NUMBER2) {
        SEGGER_RTT_printf(0, "[%d]***************queue error! data: 0x%04X\n",HAL_GetTick(), tmp);
      }else {
        SEGGER_RTT_printf(0, "[%d]queue ok, data: 0x%04X!\n", HAL_GetTick(), tmp);
      }
    }
  }
}

如何在写的时候突然中断来了,写入还没完成怎么办,比如写入的是一个结构体或者u16的数据。如果这时候中断来了,主循环的现场会保存,中断里面判断空的时候,用的是size还是上一次的,因为size的变化要等到push完成后才会改变,所以读取不会发生错误,等中断结束再回到主循环,继续写入操作。

同样写入到 时候会判断是否为满,中断前不是满的,中断读取后仍然不是满的,所以写入也不会出错。

经过2天的实测,主循环2ms写入1024个数据,中断1ms读取一次,暂时还没有发现错误。

源码在此,不需要积分

https://download.csdn.net/download/weixin_30953735/89440151

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值