Sari la conținut
ELFORUM - Forumul electronistilor

Ajutooooor cu rutina matematica


Mar

Postări Recomandate

Vreau sa afisez pe un LCD tensiunea citita de un PIC, stiu starile binare trebuie convertite in zecimal dar mai intii trebuie o rutina matematica.Habar nu am sa fac aceasta rutina.Va rog, daca aveti ceva care ma poate ajuta cu aceasta rutina imi e de mare ajutor.Multumesc mult

Link spre comentariu
  • Răspunsuri 12
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Mar

    5

  • vlad_2770

    4

  • CristianC

    2

  • Pasare Dan

    1

Top autori în acest subiect

Daca am inteles bine tie iti trebuie o rutina care sa-ti converteasca un numar binar intr-un numar intreg? Eu cred ca tu vrei ca un sa afisezi un numar binar pe LCD si banuiesc ca iti trebuie sa transformi un numar din binar intr-un sir de caractere (sa zicem 220 care este format din cifrele '2', '2', '0'.). Daca vrei asa ceva uite o rutina:/* Convert integer 'i', radix 'base' to a string */void itoa(unsigned char *buf, int i, unsigned char base) { unsigned int rem; unsigned char *s,length=0; s = buf; if (i == 0) *s++ = '0'; else { if (i < 0) { if (base <=10) { *buf++ = '-'; s = buf; } i = -i; } while (i) { ++length; rem = i % base; if (rem <= 10) *s++ = rem + '0'; else if (base <= 16) *s++ = "abcdef"[rem - 10]; i /= base; } for(base=0; base

Link spre comentariu

Eu lucrez in asm. si stiu sa fac rutina care converteste o valoare binara de exempul 0x99 in zecimal '1','5','9' , dar cind citesc valoarea binara da la ADRESH, imi trebuie o rutina matematica care sa converteasca de la starile pic-ului la tensiune. De exemplu pic-ul imi citeste 3,5V. Pentru ca el poate citi maxim 5V si daca e pe 8 biti inseamna 255 stari logice. 5V impartit la 255 stari = tensiunea corespunzatoare fiecarei stari adica 0.019V pe o stare logica.Acum daca pic-ul citeste 3.5V eu am starea logica: 3.5V impartit cu 0,019V= starea 184, deci 184 inmultit cu 0.019=3,496VAceste calcule trebuie sa faca picul si apoi ma gindesc sa convertesc de la binar la zecimal.

Link spre comentariu

Nu am acum documentatia PIC-ului. Dar cred ca tu folosesti Portul A la un pic ce are A/D incorporat. Sa inteleg ca pic-ul iti ofera o valoare T pe 8 biti ce repezinta un numar intre 0 si 255 corespunzator unei tensiuni. Tu pentru a obtine aceasta tensiune trebuie sa faci o inmultire in binar nu? Adica T x 0,019V nu?Daca este asa sa-mi spui.

Link spre comentariu

Este destul de greu sa faci o astfel de inmultire cu PIC16F877 pentru ca nu are multiplicator hardware.Solutii:1. Faci o rutina care sa faca inmultirea folosind shiftari si/sau adunari repetate2. Folosesti o referinta externa de tensiune pt ADC. De exemplu 2,55V => 1unitate ADC=10mV => nu mai trebuie inmultirea (afisezi valoarea ADC si un 0 la sfarsit). Daca nu ai nevoie de o precizie foarte buna poti sa folosesti un divizor rezistiv pentru a creea referinta de 2.55V3. Folosesti un divizor rezistiv pe intrarea de masurare al carui raport sa fie convenabil pt calcul

Link spre comentariu

vezi ca pe http://www.microchip.com sunt librarii cu rutine matematice -virgula flotanta 24/32 biti si virgula fixa.

Plus rutine pentru +/-/*/: pe 16 biti integer

Eu le-am folosit (virgula mobila) pe un P16F876 si merg.

Ai grija sa incluzi si header-ele si vezi cum se aloca spatiul - cele in virgula mobila iti mananca multi registrii - spatiu ocupat -le-am incadrat in ~1k (numai inmultiri/impartiri/adunari/scaderi/converisii integer, string/int to float)

Cauta pe acolo.

Link spre comentariu

;*******************************************************************; Double Precision Multiplication;; ( Optimized for Code : Looped Code );; Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCd,ACCc ( 32 bits ); (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ); (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ); © CALL D_mpyS; (d) The 32 bit result is in location ( ACCdHI,ACCdLO,ACCdHI,ACCdLO );; Performance :; Program Memory : 21 (UNSIGNED); 52 (SIGNED); Clock Cycles : 242 (UNSIGNED :excluding CALL & RETURN); : 254 (SIGNED :excluding CALL & RETURN); Scratch RAM : 1 (used only if SIGNED arithmetic);; Note : The above timing is the worst case timing, when the; register ACCb = FFFF. The speed may be improved if; the register ACCb contains a number ( out of the two; numbers ) with less number of 1s.;; Double Precision Multiply ( 16x16 -> 32 ); ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word; in ACCd ( ACCdHI,ACCdLO ) and low word in ACCc ( ACCcHI,ACCcLO ).;********************************************************************;D_mpyS ;results in ACCd(16 msb's) and ACCc(16 lsb's); #if SIGNED CALL S_SIGN #endif; clrf count, F bsf count,4 ; set count = 16; #if MODE_FAST movpf ACCbLO,tempLo movpf ACCbHI,tempHi #else movfp ACCbLO,WREG movwf tempLo movfp ACCbHI,WREG movwf tempHi #endif clrf ACCdHI, F clrf ACCdLO, F;; shift right and addwf 16 times;mpyLoop rrcf tempHi, F rrcf tempLo, F btfss ALUSTA,C goto NoAdd ; LSB is 0, so no need to addwf movfp ACCaLO,WREG addwf ACCdLO, F ;addwf lsb movfp ACCaHI,WREG addwfc ACCdHI, F ;addwf msbNoAdd rrcf ACCdHI, F rrcf ACCdLO, F rrcf ACCcHI, F rrcf ACCcLO, F decfsz count, F goto mpyLoop; #if SIGNED btfss sign,MSB return comf ACCcLO, F incf ACCcLO, F btfsc ALUSTA,Z decf ACCcHI, F comf ACCcHI, F btfsc ALUSTA,Z decf ACCdLO, F comf ACCdLO, F btfsc ALUSTA,Z decf ACCdHI, F comf ACCdHI, F return #else return #endif;; Assemble this section only if Signed Arithmetic Needed; #if SIGNED;S_SIGN movfp ACCaHI,WREG xorwf ACCbHI,W movwf sign ; MSB of sign determines whether signed btfss ACCbHI,MSB ; if MSB set go & negate ACCb goto chek_A comf ACCbLO, F incf ACCbLO, F btfsc ALUSTA,Z ; negate ACCb decf ACCbHI, F comf ACCbHI, F;chek_A btfss ACCaHI,MSB ; if MSB set go & negate ACCa return comf ACCaLO, F incf ACCaLO, F btfsc ALUSTA,Z ; negate ACCa decf ACCaHI, F comf ACCaHI, F return; #endif; PAGE;*******************************************************************; Double Precision Multiplication;; ( Optimized for Speed : straight Line Code );; Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCd,ACCc ( 32 bits ); (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ); (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ); © CALL D_mpy; (d) The 32 bit result is in location ( ACCdHI,ACCdLO,ACCdHI,ACCdLO );; Performance :; Program Memory : 179 (UNSIGNED); 204 (SIGNED); Clock Cycles : 176 (UNSIGNED :excluding CALL & RETURN); : 183 (SIGNED :excluding CALL & RETURN);; Note : The above timing is the worst case timing, when the; register ACCb = FFFF. The speed may be improved if; the register ACCb contains a number ( out of the two; numbers ) with less number of 1s.;; The performance specs are for Unsigned arithmetic ( i.e,; with "SIGNED equ FALSE ").;; Upon return from subroutine, the input registers;;;**********************************************************; Multiplication Macro;**********************************************************;mulMac MACRO variable i variable i = 0 #if SIGNED variable MUL_LP_CNT = 15 #else variable MUL_LP_CNT = 16 #endif .while i < MUL_LP_CNT; .if i < 8 btfss ACCbLO,i ; test low byte .else btfss ACCbHI,i-8 ; test high byte .fi goto NoAdd#v(i) ; LSB is 0, so no need to addwf movfp ACCaLO,WREG addwf ACCdLO, F ;addwf lsb movfp ACCaHI,WREG addwfc ACCdHI, F ;addwf msbNoAdd#v(i) rrcf ACCdHI, F rrcf ACCdLO, F rrcf ACCcHI, F rrcf ACCcLO, F bcf ALUSTA,C variable i = i+1 .endw #if SIGNED rrcf ACCdHI, F rrcf ACCdLO, F rrcf ACCcHI, F rrcf ACCcLO, F bcf ALUSTA,C #endif; ENDM; PAGE;***************************************************************; Double Precision Negate Macros;***************************************************************AltNegMac MACRO fileRegLo,fileRegHi movfp fileRegLo,WREG negw fileRegLo, F movfp fileRegHi,WREG clrf fileRegHi, F subwfb fileRegHi, F ENDM;negMac MACRO fileRegLo, fileRegHi comf fileRegLo, F ; negate FileReg ( -FileReg -> FileReg ) incf fileRegLo, F btfsc ALUSTA,Z decf fileRegHi, F comf fileRegHi, F ENDM;NegMac32 MACRO x3,x2,x1,x0 movfp x3,WREG negw x3, F movfp x2,WREG clrf x2, F subwfb x2, F movfp x1,WREG clrf x1, F subwfb x1, F movfp x0,WREG clrf x0, F subwfb x0, F ENDM; PAGE;*******************************************************************;; Double Precision Multiply ( 16x16 -> 32 ); ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word; in ACCd ( ACCdHI,ACCdLO ) and low word in ACCc ( ACCcHI,ACCcLO ).;D_mpyF ;results in ACCd(16 msb's) and ACCc(16 lsb's); #if SIGNED; movfp ACCaHI,WREG xorwf ACCbHI,W movwf sign btfss ACCbHI,MSB ; if MSB set go & negate ACCb goto chek_A_MSB_MPY; negMac ACCbLO,ACCbHI;chek_A_MSB_MPY btfss ACCaHI,MSB ; if MSB set go & negate ACCa goto continue_MPY negMac ACCaLO,ACCaHI; #endif;continue_MPY clrf ACCdHI, F clrf ACCdLO, F bcf ALUSTA,C;; use the mulMac macro 16 times; mulMac; #if SIGNED btfss sign,MSB ; negate (ACCc,ACCd) return NegMac32 ACCcHI,ACCcLO,ACCdHI, ACCdLO return #else return #endif

Link spre comentariu

Cred ca am gasit o varianta care sa-mi afiseze pe LCD tensiunea intre 0-100V(pun pe RA1 o rezistena care scade de la 100V la 5V). Daca iau de la ADRESH si ADRESL starile logice si le convertesc in BCD imi da 1024 stari iar eu am rezolutie de 0,1V(nu mai trebuie sa fac inmultiri). Am un program pentru BCD aici dar nu inteleg instructiunea addwf 0,wStie cineva?; Program: B16TOBCD.ASM ; Revision Date: ; 1-13-97 Compatibility with MPASMWIN 1.40;;*******************************************************************;;count equ 16temp equ 17;H_byte equ 10L_byte equ 11R0 equ 12 ; RAM AssignmentsR1 equ 13R2 equ 14; include "p16c5x.inc";B2_BCD bcf STATUS,0 ; clear the carry bit movlw .16 movwf count clrf R0 clrf R1 clrf R2loop16 rlf L_byte, F rlf H_byte, F rlf R2, F rlf R1, F rlf R0, F; decfsz count, F goto adjDEC RETLW 0;adjDEC movlw R2 movwf FSR call adjBCD; movlw R1 movwf FSR call adjBCD; movlw R0 movwf FSR call adjBCD; goto loop16;adjBCD movlw 3 addwf 0,W movwf temp btfsc temp,3 ; test if result > 7 movwf 0 movlw 30 addwf 0,W :arrow: movwf temp btfsc temp,7 ; test if result > 7 movwf 0 ; save as MSD RETLW 0;;********************************************************************; Test Program;*********************************************************************main movlw 0FF movwf H_byte movwf L_byte ; The 16 bit binary number = FFFF call B2_BCD ; After conversion the Decimal Number; ; in R0,R1,R2 = 06,55,35;self goto self; org 1FF goto main; END

Link spre comentariu

Am un program pentru BCD aici dar nu inteleg instructiunea addwf 0,w

Aia e o adresare indirecta, adica operandul se afla la adresa incarcata in registrul FSR.Inca o data se vede dezavantajul utilizarii unor cifre in locul denumirilor simbolice. :)Cirip
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări