tlwh163 发表于 2024-6-26 20:17:40

聊天中无聊说起先进先出队列,手搓了1个

''先进先出队列(用数组做缓存区)
Type FIFO_LONG
    Buff() As Long
    xSizeAs Long
    CountAs Long
    Head   As Long
End Type

Dim Fifo As FIFO_LONG

Sub FIFO_INIT(ByVal nSize As Long)
    If nSize <= 8 Then nSize = 8
    ReDim Fifo.Buff(0 To nSize - 1)
    Fifo.xSize = nSize
    Fifo.Head= 0
    Fifo.Count = 0
End Sub

Function FIFO_PUSH(ByRef x As Long) As BOOLEAN '压入数据(尾部)
    If Fifo.Count = Fifo.xSize Then Exit Function
    Dim i As Long : i = Fifo.Head + Fifo.Count
    If i >= Fifo.xSize Then i = i - Fifo.xSize
    Fifo.Count = Fifo.Count + 1
    Fifo.Buff(i) = x : FIFO_PUSH = True
End Function

Function FIFO_SHIFT(ByRef x As Long) As BOOLEAN '吐出数据(头部)
    If Fifo.Count = 0 Then Exit Function
    Dim i As Long : i = Fifo.Head
    Fifo.Head = Fifo.Head + 1
    If Fifo.Head = Fifo.xSize Then Fifo.Head = 0
    Fifo.Count = Fifo.Count - 1
    x = Fifo.Buff(i) : FIFO_SHIFT = True
End Function

0xAA55 发表于 2024-7-3 09:30:47

你能不能做一个能一下子吐出很多数据、一下子压入很多数据的 FIFO?一个数据一个数据地压入、吐出,对 IO 效率很不友好。尤其是像单片机实现 USB CDC 转串口 TTL 这块就需要 FIFO 能做到数据的批量读入写出(因为可以用到 DMA)。

tlwh163 发表于 2024-7-3 19:57:40

本帖最后由 tlwh163 于 2024-7-3 19:59 编辑

有点草率 只能说对简单数据类型 勉强可以用 请指正!

Type FIFO_LONG
    As Long Buff()   '队列空间
    As Long xSize      '缓存容量
    As Long iHead      '数据首的下标
    As Long Count      '有效数据长度
End Type

Dim Fifo As FIFO_LONG

Sub FIFO_INIT(ByVal nSize As Long)
    If nSize < 8 Then nSize = 8'最小容量8
    ReDim Fifo.Buff(0 To nSize + nSize - 1) '多1倍空间便于操作
    Fifo.xSize = nSize : Fifo.iHead = 0 : Fifo.Count = 0
End Sub

'尾部压入数据(源数据地址,申请数量)返回:实际装入数量
Function FIFO_PUSH(ByVal xPtr As Long, ByVal xCount As Long) As Long
    If xPtr = 0 Or xCount <= 0 Or Fifo.Count = Fifo.xSize Then
      FIFO_PUSH = 0 : Exit Function
    End If
    If (Fifo.Count + xCount) > Fifo.xSize Then'装不下了
      xCount = (Fifo.xSize - Fifo.Count)      '多的数据丢弃
    End If
    Dim k As Long : k = (Fifo.iHead + Fifo.Count)
    If k >= Fifo.xSize Then k = k - Fifo.xSize'队列的插入点下标   
    memcpy Varptr(Fifo.Buff(k)), xPtr, xCount * LenB(Fifo.Buff(0))
    Fifo.Count = Fifo.Count + xCount    '修正队列计数器
    FIFO_PUSH = xCount                  '返回实际接收多少个数据
    k = k + xCount - Fifo.xSize
    If k > 0 Then   '队列空间外的数据(如果有),移动到队列下标0
      k = k * LenB(Fifo.Buff(0))
      memcpy Varptr(Fifo.Buff(0)), Varptr(Fifo.Buff(Fifo.xSize)), k
    End If
End Function

''头部吐出数据(目标地址,请求数量)返回:实际吐出数量
Function FIFO_SHIFT(ByVal xPtr As Long, ByVal xCount As Long) As Long
    If xPtr = 0 Or xCount <= 0 Or Fifo.Count = 0 Then
      FIFO_SHIFT = 0 : Exit Function
    End If
    If Fifo.Count < xCount Then xCount = Fifo.Count'能吐多少吐多少
    Dim k As Long : k = Fifo.iHead + xCount
    If k >= Fifo.xSize Then k = k - Fifo.xSize'新的队列首下标
    If k > 0 Then   '需要将队列头部的数据,搬一些到队列空间的尾部
      memcpy Varptr(Fifo.Buff(Fifo.xSize)), Varptr(Fifo.Buff(0)), k * LenB(Fifo.Buff(0))
    End If
    memcpy xPtr, Varptr(Fifo.Buff(Fifo.iHead)), xCount * LenB(Fifo.Buff(0))
    Fifo.Count = Fifo.Count - xCount '修正队列计数器
    Fifo.iHead = k                   '修正队列首下标
    FIFO_SHIFT = xCount            '返回实际吐出多少个数据
End Function
页: [1]
查看完整版本: 聊天中无聊说起先进先出队列,手搓了1个