Guest Popescu Marius Posted October 22, 2013 Share Posted October 22, 2013 Va salut !Lucrez de ceva la un computer de bord pt Opel Astra G (uC atmega32). Intampin o problema , am o variabila total_inj de tip unsigned long int , dar valoarea de overflow este de 65535 , desi ar trebui sa fie mult mai mare .O mica parte din cod :#include #include #include #include #include bit old_state=0;char text[16];unsigned long int benzina_binar,dist_km=0,front_crescator,timer1, total_inj=0, benzina_consumata_cc;unsigned char index_menu=1,litri, cnt=0,cnt2=0,consum_mediu,benzina_consumata_litri,secunde_inj=0,indice=0; // External Interrupt 0 service routineinterrupt [EXT_INT0] void ext_int0_isr(void){if (PIND.2==1){front_crescator=(unsigned long int)TCNT1;} else{ timer1=(unsigned long int) TCNT1+(unsigned long int)cnt*65536-front_crescator; cnt=0; total_inj=total_inj+timer1; if (total_inj>=250000) {benzina_consumata_cc=benzina_consumata_cc+191; total_inj=0;} } } .................Compilatorul este Codevisionavr vers 2.05.0 .Are vreo setare care permite sau nu lucrul cu variabile pe 32 de biti? Link to comment
ratza Posted October 23, 2013 Share Posted October 23, 2013 Salut. Pune variabila ca unsigned long, nu unsignel long int. În altă ordine de idei, am impresia că faci un computer de bord pentru maşină, ca să vezi consumul instantaneu. Dacă mai aştepţi cîteva zile, pun proiectul meu, are multe chestii din care te poţi inspira. Link to comment
Guest Popescu Marius Posted October 23, 2013 Share Posted October 23, 2013 @ratza: Da , scuze , asa e declarata variabila , unsigned long .(am trimis mesajul de pe laptop, proiectul este pe celalalt PC ) . Tot cu codevisionavr e facut ? Link to comment
ratza Posted October 23, 2013 Share Posted October 23, 2013 Eu am proiectul făcut cu ATmega324P şi CodeVision 2.05.5a. Link to comment
Guest Popescu Marius Posted October 24, 2013 Share Posted October 24, 2013 Nu reusesc sa-i dau de cap, eu declar variabila unsigned long , iar ea la 65535 se da peste cap, face overflow . Instalez atmel studio 6 si-l las naiba codevisionavr-ul . Daca e cineva totusi care a lucrat cu variabile pe 32 biti cu codevisionavr il rog sa-mi dea si mie o indicatie .Seara buna ! Link to comment
ratza Posted October 25, 2013 Share Posted October 25, 2013 Cred că se întîmplă ceva necurat aici: timer1=(unsigned long int) TCNT1+(unsigned long int)cnt*65536-front_crescator;Ţi-am ataşat codul meu (fără librării). E comentat în engleză, fiindcă vreau să-l fac open source cînd va fi gata. Link to comment
red93 Posted October 25, 2013 Share Posted October 25, 2013 Cred că ratza are dreptate. Problema ar putea fi că în loc să citești repede TCNT1 tu pierzi timp cu o comparație și se resetează timerul rezultatul operațiilor fiind 0 ... în data sheet se recomandă să citești imediat timerul fără să pierzi timp pentru că se poate schimba TCNT1L și ai erori la calcule.Cel mai simplu este să declari două variabile de tip unsigned long int:timer_value și temp_var și să rescrii codul ceva de genul ăsta.interrupt [EXT_INT0] void ext_int0_isr(void){ timer_value = TCNT1;if (PIND.2==1) { front_crescator=timer_value; }else { temp_var = cnt; temp_var = temp_var<<16; (pentru a face înmulțirea cu 65536) timer1 = timer_value + temp_var - front_crescator; cnt=0; ....... Link to comment
ratza Posted October 25, 2013 Share Posted October 25, 2013 Mai bine ar fi să foloseşti ICP, aşa ştii sigur că ai exact valoarea timerului. Nu am înţeles de ce trebuie înmulţit cu 65536. Poţi explica, te rog? Link to comment
Guest Popescu Marius Posted October 25, 2013 Share Posted October 25, 2013 Salutare .Rutina de intrerupere externa se executa la "any change " pe pin INT0 .Fac comparatia pentru a sti daca ma aflu pe front crescator sau descrescator . Cand ma aflu pe front crescator memorez valoarea de "start injectie" , cand ma aflu pe front descrescator scad din valoarea actuala a timerului pe cea de start . E posibil ca in timp ce injecteaza benzina ca timerul sa faca overflow , de aceea am in program o rutina de intrerupere la timer1 overflow care incrementeaza pe cnt daca timerul s-a dat peste cap . Pe frontul descrescator se inmulteste cnt cu 65536 tocmai pt asta . Problema mea reala este faptul ca eu orice variabila ce o declar unsigned long( chiar si una care nu o folosesc in program , ci doar de proba ) , daca ii atribui o valoare de peste 16 biti ,de ex sa zicem 65538, programul o vede ca fiind 2(sau 3 , nu mai stiu exact), deci nu pot folosi variabile mai mari ca 65535 , desi sunt declarate unsigned long . O sa incerc cu alt controller cu memorie mai mare(acum am atmega32) , sau cu atmel studio 6. Deci da , ai dreptate cu treaba comparatiei inaintea momorarii lu TCNT1 ,pentru ca rutina incepe si eu fac altceva decat sa memorez imediat , dar sa o lasam deoparte pt ca oricum folosesc un prescaler destul de mare(quartul e de 16 MHz , iar Timer1 are 250khz), desi fac cateva instructiuni timerul am impresia ca nu se incrementeaza , ma deranjeaza mai mult treaba cu limitarea pe 16 biti .Am preferat intrerupere externa INT0 in locul timer1 capture pt ca are prioritate mult mai mare in executie prima .Multumesc pt implicare ! :)Stima! Link to comment
ratza Posted October 25, 2013 Share Posted October 25, 2013 Prioritatea să ştii că nu e chiar aşa de importantă. În orice caz, e ciudat rău. Cum verifici dacă trece peste 0xFFFF? Link to comment
Guest Popescu Marius Posted October 25, 2013 Share Posted October 25, 2013 @ratza Te referi la timer1 cum verific ca a trecut de 0xFFFF? generez intrerupere la timer1 overflow . Link to comment
ratza Posted October 25, 2013 Share Posted October 25, 2013 Mă refer la variabilă, timerul e clar că dă overflow la 0xFFFF. Link to comment
Guest Popescu Marius Posted October 25, 2013 Share Posted October 25, 2013 Am urmarit in proteus pas cu pas , total_inj nu depaseste 65535 , daca are 65200 sa zicem si ii este adunata o valoare de 400 , noua valoare este de 64 si nu 65600 cum ar trebui . In plus , am declarat o variabila "prob", de tip unsigned long si am scris "prob=66000" , dar prob ia valoarea 494 , lucru vazut si in Proteus si in montaj fizic . Link to comment
ratza Posted October 26, 2013 Share Posted October 26, 2013 Urmăreşte cu simulatorul din AVR Studio. Hai să vedem ce dă asta:timer1=(unsigned long int) TCNT1+(unsigned long int)cnt*65536-front_crescatorSă zicem că:TCNT1 = 64.000front_crescator = 65.000cnt = 400timer1 = 64.000 + 400 * 65.536 - 65.000 = 26.214.300Mie mi se pare în regulă rezultatul, deşi nu-i înţeleg logica. Care e scopul expresiei? Link to comment
Guest Popescu Marius Posted October 28, 2013 Share Posted October 28, 2013 Salut!Am atasat un desen cu logica . Hai sa facem abstractie de la formula , ca nu asta e beleaua . Precum am zis , daca declar o variabila unsigned long si-i atribui in program o valoare sa zicem 65538 si atat nu o mai folosesc in alte calcule , doar de proba , de fapt ea este 3 , asa o vede programul . Numai bine !Later edit :Mda...am simulat cu atmel studio 6 si da calculul ala cu 65000,64000,400. Deci programul este scris si compilat cu codevision si simulat cu proteus nu e ok , da rezultat 64536 , dar in atmel studio debuging da rezultatul corect... Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now