UDAR Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 (editat) Vă salut. M-am lovit de următoarea problemă : În linia de cod de mai jos durata este unsigned long iar celelalte sunt char. durata=(TMR1OF*65536)+(CPHfin*256)+CPLfin; Rezultatul este greșit pentru că la transformarea lui TMR1OF din char în unsigned - ca sa aducă la tipul dat de 65536 - în loc să pună 0 în octetul superior, compilatorul pune valoarea din adresa superioară a lui TMR1OF . Am rezolvat problema declarând și pe TMR1OF unsigned deși nu era nevoie. Unde greșesc ? Editat Aprilie 6, 2020 de UDAR Link spre comentariu
UDAR Postat Aprilie 6, 2020 Autor Partajează Postat Aprilie 6, 2020 Scuze că nu am menționat . Toate sunt variabile - TMR1OF, CPHfin, CPLfin . Le-am denumit așa ca să știu ce conține fiecare - overflow la TMR1 respectiv octetii de la captură. E un capacimetru . Durata totală e dată de numărul de depășiri a lui TMR1 + ce am în registrii de la captură . Link spre comentariu
Liviu M Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 Cum adica transformi TMR1OF din char in unsigned? Ma uit acum la tipurile de date din MikroC si (unsigned) char 1 0 .. 255 adica la mikroc char e deja unsigned. Se comporta la fel si daca in loc de TMR1OF*65536 faci TMR1OF<<16 Link spre comentariu
Bandi Szasz Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 Ce face compilatorul este corect si logic. Acolo tu faci o operatie matematica (TMR1OF*65536)" si cu parantezele ii zici sa le execute separat, din moment ce TMR1OF este "char" operatia de inmultire se va executa la nivel de char pe care il da peste cap la 256 respectiv 128 depinde daca e unsigned sau nu. Ori il declari si pe el unsigned long ori faci cast la operatia de inmultire " ((unsigned long)TMR1OF*65536)" si ii zici compilatorului ca in ciuda faptului ca tu acolo ai un char vrei ca operatia de inmultire sa se execute la nivel de unsigned long. Link spre comentariu
Liviu M Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 (editat) gcc sub linux calculeaza corect. Program: #include <stdio.h> int main(void){ unsigned char a; unsigned long b; a = 3; b = (a * 65536) + 2; printf("0x%x * 65536 + 2 = 0x%x\n", a, b); } rezultatul rularii: 0x3 * 65536 + 2 = 0x30002 Editat Aprilie 6, 2020 de Liviu M Link spre comentariu
UDAR Postat Aprilie 6, 2020 Autor Partajează Postat Aprilie 6, 2020 (editat) Cred că e mai elocvent dacă pun și segmentul de asm : Deci compilatorul transformă TMR1OF din char în int si îl deplasează cu 16 biți dar în loc să facă : CLRF R8+3 MOVF _TMR1OF, 0 MOVWF R8+2 CLRF R8+1 CLRF R8 cu alte cuvinte în octetul cel mai semnificativ al rezultatului ( R8+3) în loc să pună 0 pune valoarea găsită la adresa _TMR1OF + 1 care apartine unei alte variabile, oarecare. Declarând TMR1OF ca unsigned am fortat mentinerea libera a locatiei respective . În fine, am rezolvat cum am zis dar eram curios unde e greseala - sunt incepator in ale PIC-ului ( și mai incepator in ale C-ului ) ! Editat Aprilie 6, 2020 de UDAR Link spre comentariu
Liviu M Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 Si xc8 al lui microchip calculeaza corect. Program (am inlocuit 2 cu o variabila unsigned char, ca sa evit vreo conversie ciudata a compilatorului) #include <xc.h> void main(void) { unsigned char a; unsigned char b; unsigned long c; a = 3; b = 2; c = (a * 65536) + b; a = 4; return; } Link spre comentariu
djvas Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 Am testat in mikropascal si calculeaza corect.... Link spre comentariu
Liviu M Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 Acum 6 minute, UDAR a spus: Deci compilatorul transformă TMR1OF din char în int si îl deplasează cu 16 biți... cu alte cuvinte în octetul cel mai semnificativ al rezultatului ( R8+3) în loc să pună 0 pune valoarea găsită la adresa _TMR1OF + 1 care apartine unei alte variabile, oarecare. Daca compilatorul chiar transforma char in int, sunt sanse sa fie OK, ca facand compilatorul din 1 byte 2, eu ma astept ca adresa _TMR1OF + 1 sa fie MSB-ul noului int, care ar trebui sa fie 0. Link spre comentariu
UDAR Postat Aprilie 6, 2020 Autor Partajează Postat Aprilie 6, 2020 Așa și MikoC-ul face corect pentru că face calculele direct in compilator , nu le emuleaza cu adevarat. Dupa cum se vede el pune niște ”literale” ( MOVLW ) pe care le știe deja, nu citeste locațiile de memorie ale variabilelor. În fine , când o să am timp și chef o să mai încerc. Acum 8 minute, Liviu M a spus: Daca compilatorul chiar transforma char in int, sunt sanse sa fie OK, ca facand compilatorul din 1 byte 2, eu ma astept ca adresa _TMR1OF + 1 sa fie MSB-ul noului int, care ar trebui sa fie 0. Așa am presupus și eu . Eu am înșelat cumva compilatorul ( fără să vreau ) dar mă așteptam ca el să se prindă că dacă faci dintr-un byte doi cel mai semnificativ e zero - putem numi asta un bug ? Link spre comentariu
Liviu M Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 Daca esti sigur ca compilatorul "strica" alte variabile, clar e bug. Sau, cu alte cuvinte, daca esti sigur ca rezultatul final e eronat (cum ziceam, la mine si gcc si xc8 par sa livreze rezultatul corect fara ajutor), atunci e clar, e bug. Link spre comentariu
UDAR Postat Aprilie 6, 2020 Autor Partajează Postat Aprilie 6, 2020 Nu strică alte variabile ci introduce conținutul variabilei respective in octetul mai semnificativ al variabilei mele . Nu pricepeam nicicum se se întâmplă - l-am pus să afișeze valoarea ”durata” și am văzut că e mult mai mare decât trebuie . El în loc să înmulțească 31( cât era TMR1OF ) cu 65536 înmulțea X31 ( adică X*256+31) cu 65536 . Noroc că mi-a picat fisa să mă uit în .lst. În fine, bine că am rezolvat și pot avansa cu proiectul. Mulțumesc pentru interes. Link spre comentariu
Liviu M Postat Aprilie 6, 2020 Partajează Postat Aprilie 6, 2020 Pai de unde pacatele mele il lua pe X? Ca si daca ar fi facut vreo promotie, eu zic ca compilatorul ar fi trebuit sa puna 0 in MSB. Acum ai rezolvat problema, da' altfel ai fi putut sa aplici o masca inainte de adunare: durata=((TMR1OF*65536) & 0x00FF0000) + (CPHfin*256) + CPLfin; In felul asta, stii sigur ca pastrezi doar ce-ti trebuie. Eventuel maschezi si ceilalti termeni ai adunarii. Link spre comentariu
UDAR Postat Aprilie 7, 2020 Autor Partajează Postat Aprilie 7, 2020 Da, excelentă ideea cu masca ! În ce-l privește pe X - să zicem că TMR1OF era la adresa 00B9 - compilatorul când citea TMR1OF+1 citea 00BA unde era conținutul altei variabile. Și eu zic la fel că trebuia să pună zero nu să citească . Link spre comentariu
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum