串口环形缓冲区实验1.1 实验简介 最简单的串口数据处理机制是数据接收并原样回发的机制是:成功接收到一个数,触发进入中断,在中断函数中将数据读取出来,然后立即。这一种数据处理机制是“非缓冲中断方式”,虽然这种数据处理方式不消耗时间,但是这种数据处理方式严重的缺点是:数据无缓冲区,如果先前接收的的数据如果尚未发送完成(处理完成),然后串口又接收到新的数据,新接收的数据就会把尚未处理的数据覆盖,从而导致“数据丢包”。 对于“数据丢包”,最简单的办法就是使用一个数组来接收数据:每接收一个数据,数组下标偏移。虽然这样的做法能起到一定的“缓冲效果”,但是数组的空间得不到很好的利用,已处理的数据仍然会占据原有的数据空间,直到该数组“满载”(数组的每一个元素都保存了有效的数据),将整个数组的数据处理完成后,重新清零数组,才能开启新一轮的数据接收。 那么,有什么好的数据接收处理机制既能起到“缓冲”效果,又能有效地利用“数组空间”?答案是:有的,那就是“环形缓冲区”。 环形缓冲区就是一个带“头指针”和“尾指针”的数组。“头指针”指向环形缓冲区中可读的数据,“尾指针”指向环形缓冲区中可写的缓冲空间。通过移动“头指针”和“尾指针”就可以实现缓冲区的数据读取和写入。在通常情况下,应用程序读取环形缓冲区的数据仅仅会影响“头指针”,而串口接收数据仅仅会影响“尾指针”。当串口接收到新的数组,则将数组保存到环形缓冲区中,同时将“尾指针”加1,以保存下一个数据;应用程序在读取数据时,“头指针”加1,以读取下一个数据。当“尾指针”超过数组大小,则“尾指针”重新指向数组的首元素,从而形成“环形缓冲区”!,有效数据区域在“头指针”和“尾指针”之间。如下图所示。
当然,环形缓冲区的“头指针”和“尾指针”可以用“头变量”和“尾变量”来代替,因为切换数组的元素空间,除了可以用“指针偏移法”之外,还可以用“素组下标偏移法”。当串口接收到新的数组,则将数组保存到环形缓冲区中,同时将“尾变量”加一,以保存下一个数据;应用程序在读取数据时,“头变量”加一,以读取下一个数据。 “环形缓冲区”数据接收处理机制的好处在于:利用了队列的特点,一头进,一头出,互不影响,在数据进去(往里存)的时候,另一边也可以把数据读出来,而读出来的数据,留下的空位,又可以增加多的存储空间,从而避免一边接收数据且一边处理数据会在数据量密集的时候而导致的丢掉数据或者数据产生冲突的问题。 如果仅有一个线程读取环形缓冲区的数据,只有一个串口往环形缓冲区写入数据,则不需要添加互斥保护机制就可以保证数据的正确性。 需要注意的是,如果串口每接收x个字节的数据才处理一次,则环形缓冲区的缓冲数组的大小必须是x的N倍,具体N为多少,需要结合具体的数据接收速率以及处理速率,适当调节。这就好比喻,水壶永远大于水杯,这样子水壶才能存放很多杯水。 如果觉得前文隐晦难懂,那么下面我们来一起讨论一下环形队列的具体状态以及实现。下文构建的环形队列采用的是“头变量”“尾变量”来控制队列的存储和读取。
|