FIFO在单片机上的应用

FIFO是什么? FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

  FIFO的软件机制实现,根据RAM的容量大小及FIFO所需的空间,在RAM中开设一片缓冲空间. 设定一个FI地址指针,和一个FO的地址指针,再设定一个数据量的计数存储器.如果需要FI时,只需要将数据存入设定的地址单元,然后将计数存储器和FI地址指针加1即可.当需要FO时,只要检测到计数存储器的内容不为0,说明缓冲器内有数据需要送出.则将缓冲器的内容取出,再将FO的地址指针加一,并将计数寄存器的内容减一即可.

  FIFO有什么作用呢, 利用FIFO有时可以实现快速处理.提高控制的速度.比如,我们SPI,IIC或者UART将采集的一组数据送出去,但是这些数据传送都是需要一定时间的,有时为了不耽误数据采集的时间,就可以采集的数据直接先连续的存放在缓冲区内.数据的发送交给另外一个任务去处理.这样就不会耽误数据采集任务的时间来等待每个字节的发送完毕了.

  下面以FPPA的软件实现来进一步形象说明.该FIFO缓冲器设定在20~2F单元内.

   定义一些控制变量:

int  temp100       ;FI时用的临时变量,同任务中其他地方也可用
word fiindex       ;便于访问的指针变量,同任务中其他地方也可用
word foindex       ;便于访问的指针变量,同任务中其他地方也可用
int  temp200       ;FO输出数据存放单元
int  fifo_counter  ;数据个数计数单元
int  fi_pointer    ;FI指针控制
int  fo_pointer    ;FO指针控制

-----------------------------------------------------

FIFO使用之前也需要初始化的:

;---------------fifo initial sub program----------------------
;Name  :fifo_initial
;Input  :void
;Output  :void
;temp REG :void
;Function :
;Argument :
;------------------------------------------------------------- 
fifo_initial:
        mov    a, FIFO_START_RAM_ADDR
        mov    fi_pointer, a
        mov    fo_pointer, a
        clear  fifo_counter
        clear  hb@fiindex
        clear  hb@foindex
        ret

-------------------------------------------------

FI子程序:

;---------------fi operation sub program----------------------
;Name  :fi_data
;Input  :a
;Output  :void
;temp REG :temp100
;Function :fi operation
;Argument :temp100 save a temp,
;------------------------------------------------------------- 
fi_data:
        mov    temp100, a
        mov    a, fi_pointer
        mov    lb@fiindex, a
        mov    a, temp100
        idxm   fiindex, a
        inc    fifo_counter
        inc    fi_pointer
        mov    a, 0x2f
        and    fi_pointer, a
        ret

;------------------------------------------

FO子程序:

;---------------fo operation sub program----------------------
;Name  :fo_data
;Input  :void(fo_pointer)
;Output  :temp200
;temp REG :temp100
;Function :fo operation
;Argument :temp200 save output data,
;-------------------------------------------------------------        
fo_data:
        mov    a, fifo_counter
        t0sn   flag_z
        ret    1 ;fail, no data
        mov    a, fo_pointer
        mov    lb@foindex, a
        idxm   a, foindex
        mov    temp200, a
        inc    fo_pointer
        mov    a, 0x2f
        and    fo_pointer, a
        mov    a, fifo_counter
        t1sn   flag_z
        dec    fifo_counter        
        ret    0  ;data exist 
;-------------------------------------------------------------

FO的调用,程序中专门用了个FPP(CPU)来做串口数据发送.

;
;--------fppa 1 program---------------------
fpp1boot:
 mov   a, STACK_BOTTOM1
 mov   sp, a
 set1  fppen.2
 mov    a, BIT_CNT
 mov    tx0ShiftCnt, a
 mov    a, SUB0_BITRATE
 mov    tx0BaudRate, a  
fpp1loop: 
waitTx0Start:
        call   fo_data
        comp   a, 0x00
        t1sn   flag_z
        goto   waitTx0Start       
        mov    a, temp200
        mov    tx0DataBuf, a
        set0   TX0
        mov    a, tx0BaudRate
        add    a, 0x03
        delay  a
tx0Loop:
 sr     tx0DataBuf
 swapc  TX0
 delay  tx0BaudRate
 dzsn   tx0ShiftCnt
 goto   tx0Loop
 mov    a, BIT_CNT
 mov    tx0ShiftCnt, a 
 set1   TX0
 delay  tx0BaudRate
 goto   waitTx0Start

    而在其他地方,做FI时就不用在花时间等待了,当然在做FI时也要考虑,缓冲器的深度,不然串口发送忙不过来时,数据的处理就肯定有问题,一些需要发送的数据会被覆盖而造成丢失.

   看看我需要显示一串字符串的子程序吧:

title_table:
        ds "adc test demo#"
title_disp:
        mov    a, 0x0a
        call   fi_data
        mov    a, 0x0d
        call   fi_data
        mov a, la@title_table
        mov lb@ramindex, a
        mov a, ha@title_table
        mov hb@ramindex, a
title_disp_loop:
        ldtabl ramindex
        comp   a, ''#'0x23; ''#''
        t0sn   flag_z
        goto   title_disp_ret
        call   fi_data
        ldtabh ramindex
        comp   a, ''#''
        t0sn   flag_z
        goto   title_disp_ret
        call   fi_data
        inc    lb@ramindex
        t0sn   flag_z
        inc    hb@ramindex
        goto   title_disp_loop
title_disp_ret:
        ret       
;-----------------------------------------------------------

   从这里也可以看出一点多任务设计的一点优势了吧, 使用多任务设计,可以尽可能的帮你节省控制上的时间,以达到更精确的控制.欢迎各位多多指教,谢谢!

投 票

觉得本文不错,投一票   

评 论


验证码: 看不清?换一张