digital electronics design

I have implemented this fuction for an ohmmeter, which must do a divide (R=E/I), since it can only measure voltage and current. Here is the source for an Atmel processor. Use a fixed width font, tab space = 6 to view.

This function divides two 32-bit numbers using an 8-bit AVR processor. you will also need fuctions to store 4-registers to memory, and recall them, e.g. SQ_2_mem() and LoadSQ()

Frank Raffaeli

formatting link
************************************************************************ ;* ;* Ratio - ;* Divides const in Temp[] (dividend) by variable in SQ[] (divisor) ;* DD = dividend, VR = divisor, RM = remainder. SQ[] (divisor) stored in ;* SRAM and recalled as needed. SQ[] is then used as initial dividend. ;* result is shifted into the dividend SQ[], which returns final answer. ;* ;************************************************************************

Ratio: cbr Status, (1 SQ[] movw SQ2, Temp2 ; hi word DD -> SQ[]

clr Temp0 ; Temp[] -> lo byte RM = 0 clr Temp1 ; Temp[] -> 2nd byte RM = 0 clr Temp2 ; Temp[] -> 2nd byte RM = 0 sub Temp3, Temp3 ; 4th byte: RM=0 & clr carry

ldi EE_Addr, 33 ; use of EE_Addr as counter

divide_loop1:

rol SQ0 ; shift dividend left rol SQ1 ; carry -> byte 2 dividend rol SQ2 ; carry -> byte 3 dividend rol SQ3 ; carry -> byte 4 dividend

dec EE_Addr ; decrement counter breq ExitRatio ; bug out at end count

rol Temp0 ; shift dividend into remainder rol Temp1 ; shift RM byte 2 rol Temp2 ; shift RM byte 3 rol Temp3 ; shift RM byte 4

ldi XL, low(mem2) ; load pointer low byte mem2 ldi XH, high(mem2) ; load pointer high byte mem2 rcall SQ_2_Mem ; SQ[] (DD/result) -> mem2

ldi XL, low(mem1) ; load pointer low byte mem1 ldi XH, high(mem1) ; load pointer high byte mem1 rcall LoadSQ ; divisor from mem1 -> SQ[]

sub Temp0, SQ0 ; RM = RM - VR (low byte) sbc Temp1, SQ1 ; RM = RM - VR (carry) sbc Temp2, SQ2 ; RM = RM - VR (carry) sbc Temp3, SQ3 ; RM = RM - VR (carry) brcs add_back ; if carry, add back to RM

ldi XL, low(mem2) ; load pointer low byte mem2 ldi XH, high(mem2) ; load ptr high byte mem2 rcall LoadSQ ; DD/result: mem2 -> SQ[] sec ; set carry, '1' into DD rjmp divide_loop1

add_back: add Temp0, SQ0 ; RM = RM + VR (restore) adc Temp1, SQ1 ; RM = RM + VR (carry 2nd) adc Temp2, SQ2 ; RM = RM + VR (carry 3rd) adc Temp3, SQ3 ; RM = RM + VR (carry 4th)

ldi XL, low(mem2) ; load pointer low byte mem2 ldi XH, high(mem2) ; load pointer high byte mem2 rcall LoadSQ ; DD/result: mem2 -> SQ[] clc ; clear carry, '0' into DD

rjmp divide_loop1 ; back to start

ExitRatio: rcall RatioFilter ; smooth the data in SQ[] sbr Status, (1

Reply to
Frank Raffaeli
Loading thread data ...

Hey Srinivasa are you still around ??

Have you made any decisions about your design ???

Donald

Reply to
Donald

A look-up table and a quarter. ;-) It only uses 2/8 bits of the second one, after all. Also, you'd need yet another if you want a remainder.

Cheers! Rich

Reply to
Rich Grise

You can stick a radix point (say) after the 10 bits and use the last 6 bits for fractional results.

Often keeping *just* the fractional part is more useful than the typical HLL integer math approach of just keeping the integer partand truncating the fractional bit. That, of course, constrains the denominator to be > the numerator, which is easily achieved by prescaling (and may occur naturally anyway).

For example, if you have an ADC and measure the results of an unknown X and a reference R (each 10 bits), and want the ratio, you most likely don't want integer math y = X/R, because if X < R, it will always be 0. Fractional fixed-point math is what you want.

If you're using standard data types in something like C, you'd have to do something like...

y = (x

Reply to
Spehro Pefhany

If you need a inaccurate clock, use Linear Technology's resistor set oscillators (e.g. LTC6905).

--
Mark
Reply to
qrk

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.