From Tony Nixon [sales at picnpoke.com] and Scott Dattalo
Tony says:
Heres a simple setup using the FSR. Averages for 8 readings though.
CBLOCK
Average: 8h
tempH
tempL
ENDC
movlw Average ; initialise FSR
movwf FSR
...
;
; PLACE A2D RESULTS INTO A ROTATING BUFFER
;
movf ADRES,W
movwf INDF
incf FSR
movlw Average + 8h
xorwf FSR,W
btfss STATUS,Z
goto NFSR
movlw Average
movwf FSR
NFSR ...
;Scott Dattalo interjects:
;If you have only 8 samples, and you were willing to align the array on a mod 8
;boundary, then advancing the pointer could be done easily:
incf fsr,w
andlw 7
addlw Average
movwf fsr
;if you don't wish to align the array, then try this instead:
incf fsr,w
addlw -Average
andlw 7
addlw Average
movwf fsr
;
; AVERAGE OUT THE 8 STORED VALUES WHEN A RESULT IS NEEDED
;
movlw Average
movwf FSR
clrf tempH
clrf tempL
avLoop movf INDF,W ; add up 8 word values
addwf tempL
btfsc STATUS,C
incf tempH
incf FSR
movlw Average +8h
xorwf FSR,W
btfss STATUS,Z
goto avLoop
movlw Average
movwf FSR
bcf STATUS,C ; div result by 8
rrf tempH
rrf tempL
bcf STATUS,C
rrf tempH
rrf tempL
bcf STATUS,C
rrf tempH
rrf tempL
....
And Scott also says:
Again, I think the best way to maintain a running average is by subtracting the oldest value and adding in the newest. Here's something I'll whip out as fast as I can type it - which means there's a good chance for a thinko.; avg_lo:avg_hi - 16bit cumulative sum of last 8 samples ; samples - a circular array that holds the last 8 samples ; assume that samples and avg_lo:avg_hi are initialized to zero ; ; FSR is initialized to the start of samples ; ; W = newest sample AVERAGE: addwf avg_lo,f ;add newest sample to the average skpnc incf avg_hi,f xorwf indf,f ; swap oldest and newest samples xorwf indf,w xorwf indf,f subwf avg_lo,f ;remove the oldest sample from the average skpc decf avg_hi,f incf fsr,w ;advance the sample pointer addlw -sample andlw 7 addlw sample movwf fsr return There - no more looping through all of the data after every sample is acquired. Now, I'm assuming that the division is not needed at every iteration. I tend to put off the difficult stuff as long as possible - often times, the intermediate calculations are more than sufficient. But, if you want, then this is how I'd do it: rrf avg_hi,w movwf temp_hi rrf avg_lo,w movwf temp_lo rrf temp_hi,f rrf temp_lo,f rrf temp_hi,f rrf temp_lo,w and if you wanted rounding: skpnc addlw 1 (You don't need to worry about clearing the carry because the average is guranteed to be less than or equal to 255.)
See:
Questions:
Interested: