FIFO在单片机上的应用506078058
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
;-----------------------------------------------------------
从这里也可以看出一点多任务设计的一点优势了吧, 使用多任务设计,可以尽可能的帮你节省控制上的时间,以达到更精确的控制.欢迎各位多多指教,谢谢!
数据正在载入中..