giacomo56 Inserita: 24 agosto 2004 Segnala Share Inserita: 24 agosto 2004 Isr sta per Interrupt Service Routine.Suggerisco le seguenti modifiche:- Spostare le istruzioni non necessarie fuori dal ciclo while- L'istruzione set_timer(100) mi pare resetti il prescaler quindi và messa prima d'impostare quest'ultimo- E deve essere sincronizzata con il timer quindi và spostata dentro l'isr- Anche se non influente in questo caso, usare la coppia else/if#include "C:\Documenti\pic c\nuovi_progetti\prova_mpx\prova_mpx.h"#define centi PIN_A2#define deci PIN_A3#define uni PIN_A4int8 numero, cifra_on, tempoc; //tempoc è il tempo di campionamento. 1000 ms#int_rtcc noclear //routine di interruptvoid isr() { set_timer0(100); setup_timer_0 (RTCC_DIV_128|RTCC_INTERNAL); cifra_on=cifra_on+1; if (cifra_on==4) cifra_on=1; tempoc=tempoc+1; if (tempoc==50) tempoc=0; } void main() { //inizio programma principaleset_tris_a(0x00);set_tris_b(0x00);numero=0;tempoc=0;cifra_on=1;set_timer0(100); //TMR0 passa per lo 0 con una frequenza di 50 Hz//7812.5/156=50 Hzsetup_timer_0 (RTCC_DIV_128|RTCC_INTERNAL);/* imposto il prescaler a 128 divisioni in modo da ottenereuna frequenza di incremento del registro TMR0 di1 Mhz/128=7812.5 Hz */enable_interrupts(INT_RTCC); //abilito l'interrupt da tmr0enable_interrupts(GLOBAL); //abilito tutti gli interruptswhile(1) //ciclo continuo{ if (cifra_on==1) output_bit(centi, 1); else if (cifra_on==2) output_bit(deci, 1); else if (cifra_on==3) output_bit(uni, 1); //Manca l'invio del numero} //fine ciclo while} //fine mainSei d'accordo?Ciao. Link al commento Condividi su altri siti More sharing options...
bit Inserita: 2 settembre 2004 Segnala Share Inserita: 2 settembre 2004 Anch'io sto lavorando ad un tachimetro digitale.Come suggerimento, visto che mi pare che nessuno l'abbia menzionato, segnalo che come sensore funziona egregiamente (e costa poco!) anche uno di quei contatti magnetici (reed) del tipo usato per gli allarmi antiintrusione, da applicare alle finestre. Basta montare un piccolo magnetino sulla ruota e fare in modo che passi vicino al contatto magnetico.E' un contatto meccanico, ma vi assicuro che ha una velocità di risposta più che sufficente. Li ho testati fino a 600 impulsi al secondo.Inoltre ha il vantaggio di non necessitare di alimentazione, vantaggio non da poco per l'autonomia della batteria.Ciao a tutti! Link al commento Condividi su altri siti More sharing options...
giacomo56 Inserita: 3 settembre 2004 Segnala Share Inserita: 3 settembre 2004 Ciao Giorgio,come vanno le prove?Mi sono accorto adesso che nel ciclo while accendi un display ma non spegni il precedente.Ciao. Link al commento Condividi su altri siti More sharing options...
Giorgio Demurtas Inserita: 3 settembre 2004 Autore Segnala Share Inserita: 3 settembre 2004 ciao giacomo,finalmete riesco a rispondere!Una settimana fa ho aggiornato il sw, ma sul pic non funziona come dovrebbe.giusto per avere un'idea ti mando il listato, e appena ho tempo gli do una controllata (mi sa chè è vero che non spengo il precedente)scusami ma in questo momento non ho tempo... //contachilometri con display //giorgio demurtas //agosto 2004 #include "C:\Documenti\pic c\nuovi_progetti\prova_mpx\prova_mpx.h" #define centi PIN_A2 #define deci PIN_A3 #define uni PIN_A4 int8 numero, velox, cifra_on, tempoc; //tempoc è il tempo di campionamento. 1000 ms //-------------------------------------------------------------------------- #int_rtcc noclear //Interrupt Service Routine void isr() { cifra_on=cifra_on+1; if (cifra_on==4) cifra_on=1; tempoc=tempoc+1; if (tempoc==50) tempoc=0; } //-------------------------------------------------------------------------- void main() { //inizio programma principale set_tris_a(0x00); set_tris_b(0x00); numero=0; tempoc=0; cifra_on=1; output_b(0x25); //visualizza il numero 3 setup_timer_0 (RTCC_DIV_128|RTCC_INTERNAL); // imposto il prescaler a 128 divisioni in modo da ottenere // una frequenza di incremento del registro TMR0 di // 1 Mhz/128=7812.5 Hz set_timer0(100); //TMR0 passa per lo 0 con una frequenza di 50 Hz //7812.5/156=50 Hz enable_interrupts(int_rtcc); //abilito l'interrupt da tmr0 enable_interrupts(global); //abilito tutti gli interrupts while(1) //ciclo continuo { if (cifra_on==1) output_bit(centi, 1); if (cifra_on==2) output_bit(deci, 1); if (cifra_on==3) output_bit(uni, 1); /* invio del numero if (numero==0) output_b(0x03); if (numero==1) output_b(0x9F); if (numero==2) output_b(0x25); if (numero==3) output_b(0x0D); if (numero==4) output_b(0x99); if (numero==5) output_b(0x49); if (numero==6) output_b(0x41); if (numero==7) output_b(0x1F); if (numero==8) output_b(0x01); if (numero==9) output_b(0x09); */ } //fine ciclo while } //fine main a dopo Link al commento Condividi su altri siti More sharing options...
Giorgio Demurtas Inserita: 4 settembre 2004 Autore Segnala Share Inserita: 4 settembre 2004 (modificato) ma porca miseria non riesco a farlo funzionare! il watch dog timer deve essere enable?ho programmato circa una dozzina di volte due pic per provare il sw, ma adesso non ne vogliono più sapere di funzionare, certe uscite (quelle che pilotano i transistor non vanno alte per nessun motivo).ecco il listato://contachilometri con display //giorgio demurtas //agosto-settembre 2004 #include "C:\Documenti\pic c\nuovi_progetti\prova_mpx\prova_mpx.h" #define centi PIN_A2 #define deci PIN_A3 #define uni PIN_A4 //-------------------------------------------------------------------------- #int_RTCC RTCC_isr() //Interrupt Service Routine { cifra_on=cifra_on+1; if (cifra_on==4) cifra_on=1; tempoc=tempoc+1; if (tempoc==50) tempoc=0; } //-------------------------------------------------------------------------- void main() { //inizio programma principale int8 numero, velox, cifra_on, tempoc; //tempoc è il tempo di campionamento. 1000 ms set_tris_a(0x00); set_tris_b(0x00); numero=0; tempoc=0; cifra_on=1; output_b(0x25); //visualizza il numero 3 setup_timer_0 (RTCC_DIV_128|RTCC_INTERNAL); // imposto il prescaler a 128 divisioni in modo da ottenere // una frequenza di incremento del registro TMR0 di // 1 Mhz/128=7812.5 Hz set_timer0(100); //TMR0 passa per lo 0 con una frequenza di 50 Hz //7812.5/156=50 Hz enable_interrupts(int_rtcc); //abilito l'interrupt da tmr0 enable_interrupts(global); //abilito tutti gli interrupts while(1) //ciclo continuo { if (cifra_on==1) output_bit(centi, 1); else output_bit(centi, 0); if (cifra_on==2) output_bit(deci, 1); else output_bit(deci, 0); if (cifra_on==3) output_bit(uni, 1); else output_bit(uni, 0); /* invio del numero if (numero==0) output_b(0x03); if (numero==1) output_b(0x9F); if (numero==2) output_b(0x25); if (numero==3) output_b(0x0D); if (numero==4) output_b(0x99); if (numero==5) output_b(0x49); if (numero==6) output_b(0x41); if (numero==7) output_b(0x1F); if (numero==8) output_b(0x01); if (numero==9) output_b(0x09); */ } //fine ciclo while } //fine main Modificato: 4 settembre 2004 da Giorgio Demurtas Link al commento Condividi su altri siti More sharing options...
giacomo56 Inserita: 4 settembre 2004 Segnala Share Inserita: 4 settembre 2004 Quando si scrive sul registro timer0 il prescaler viene resettato (vedi datasheet) e penso che l'istruzione set_timer0(100) faccia proprio questo. Quindi prova a metterla prima di setup_timer_0 e non dopo. set_timer0(100) e setup_timer_0 devono essere ripetute ad ogni interruzione altrimenti il timer ricomincia da zero dopo la prima interruzione.Ciao. Link al commento Condividi su altri siti More sharing options...
Claudio F Inserita: 11 settembre 2004 Segnala Share Inserita: 11 settembre 2004 Io non ho capito se vuoi fare un contakm, un tachimetro... o tutti e due. Nel primo caso la periodicita' del timer non ha grande importanza, nei secondi due invece si. Come ha detto giacomo56 una scrittura nel tmr0 azzera il prescaler e ti fa perdere ogni volta quei us trascorsi dall'overflow del timer alla sua ricarica, questo non permette di ottenere periodi precisi.Per non impazzire con questo problema l'ideale e' lasciar conteggiare il tmr0 senza mai ricaricarlo (divide per 256) e giocare sul fattore di divisione del prescaler e sulla frequenza del quarzo per ottenere intervalli utili (e questa volta sicuramente precisi). Per esempio con un quarzo da 4,096MHz e prescaler che divide per 16 il timer va in overflow esattamente ogni 4mS (250Hz), per cui basta contare 250 di questi periodi per sapere che e' passato 1 secondo esatto.Lo scadere dei 4ms puo' essere controllato indifferentemente usando gli interrupt o guardando di tanto in tanto lo stato del bit T0IF (sul PIC16F84 questo e' bit 2 del registro INTCON). quando questo bit diventa 1 il tempo e' trascorso (e il bit va riazzerato a mano subito dopo il controllo):ciclo_principale BTFSC INTCON,2 CALL routines_timer CALL routines_continue GOTO ciclo_principale In questo esempio "routines_timer" viene chiamata solo allo scadere dei 4mS, e la prima istruzione che deve contenere e': BCF INTCON,2 che riazzera il bit T0IF. "routines_continue" e' invece il programma principale che viene eseguito in continuazione.Personalmente nel programma principale metterei la cattura/conteggio degli impulsi, suddividendo il conteggio in variabili BCD da 0 a 9. Nelle routines timer metterei lo scambio/visualizzazione della cifra (quindi ogni display rimane acceso per 4 mS).Per il tachimetro il discorso si fa un po' piu' complesso, perche' la scarsa quantita' di impulsi al secondo influenza molto la precisione.ciaoClaudio F Link al commento Condividi su altri siti More sharing options...
bit Inserita: 11 settembre 2004 Segnala Share Inserita: 11 settembre 2004 Per la funzione tachimetro la miglior cosa è effettuare la misura del periodo tra due impulsi successivi e calcolare poi la velocità matematicamente. Per questo forse è meglio un micro tipo il 16F628, di cui possiamo sfruttare la funzione capture per misurare il periodo tra gli impulsi.Ciao! Link al commento Condividi su altri siti More sharing options...
Giorgio Demurtas Inserita: 13 settembre 2004 Autore Segnala Share Inserita: 13 settembre 2004 ciao giacomo, claudio, bit,grazie ai vostri consilgi ho capito cose nuove e son riuscito a far funzionare il prog come si deve!Il pin RA4/rtcc (piedino 3) non da nessun segale... se cambio piedino (es il 18) funziona bene. perchè?ora c'è da sviluppare la seconda parte del sw... partiamo da una variabile di nome "velox" che contiene il valore della velocità già espressa in km/h. devo suddividerla in tre variabili "centiv", "deciv", "univ" perchè quando è acceso il diplay centi devo mandare la cifra contenuta in centiv... Come posso fare? divido per 10 e prendo il resto e ottengo le unità, poi divido nuovamente per 10 e ottengo le decine, il numero che rimane sono le centinaia. Idee migliori?grazie dell'aiutociaogiorgiops. ci vediamo al bias! Link al commento Condividi su altri siti More sharing options...
giacomo56 Inserita: 13 settembre 2004 Segnala Share Inserita: 13 settembre 2004 L'uscita del pin RA4 è del tipo 'open drain'. A portare l'uscita bassa ci pensa lui a portarla alta ci deve pensare il circuito esterno, di solito una resistenza di pull-up.Ciao. Link al commento Condividi su altri siti More sharing options...
Giorgio Demurtas Inserita: 29 settembre 2004 Autore Segnala Share Inserita: 29 settembre 2004 ok giacomo, grazie, hai ragione, ora funziona.ho visto che non mi rispondete più... nessun consiglio per la seconda parte del sw? io ho letto in parte le funzioni disponibili nel mio compilatore (PCW ccs C) ma non ho trovato niente che mi sembra possa essermi utile... dai...un'aiutino...ciaoGiorgio Link al commento Condividi su altri siti More sharing options...
wnc Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 Devi conventire la variabile in char e crearti una routine che, tramite puntatore, estragga il char relativo alle centinaia poi le decine e cosi via. Il compilatore C18 Microchip lo consente, il tuo non so. Ora non ho sottomano il codice. Se hai problemi fammi sapere. Saluti Link al commento Condividi su altri siti More sharing options...
wnc Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 Ah, dimenticavo. Vedendo la tua immagine non stai utilizzado un 18Fxxx. Comunque dovrebbe funzionare lo stesso. Link al commento Condividi su altri siti More sharing options...
dlgcom Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 Ciao Giorgio,Ti do una routine per dividere la variabile in tre digit.E' in assembler perche non ho ancora usato display in C.Puoi inserirla direttamente nel compilatore , visto che tutti i compilatori accettano pezi di prg in asm. ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * CONVERSIONE HEX BCD * ; * W [HEX] = CENT; DECINE ; UNITA [DEC] * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; QUESTA ROUTINE RICEVE UN ARGOMENTO PASSATO PER WORK E RITORNA NELLE ; VARIABILI DEZENA E UNIDADE IL VAL. BCD CORRISPONDENTE . AJUSTE_DECIMAL MOVWF AUX ; SALVA VALORE DA CONVERTIRE IN AUX CLRF UNITA CLRF DECINE ; RESETTA REGISTRI CLRF CENT MOVF AUX,F BTFSC STATUS,Z ; VALORE DA CONVERTIRE = 0 ? RETURN ; SI - RITORNA ; NO INCF UNITA,F ; INCREMENTA UNITA' MOVF UNITA,W XORLW 0X0A BTFSS STATUS,Z ; UNITA' = 10d ? GOTO $+9 ; NO ; SI CLRF UNITA ; RESETTA UNITA' INCF DECINE,F ; INCREMENTA DECINE MOVF DECINE,W XORLW 0X0A BTFSS STATUS,Z ; UNITA' = 10d ? GOTO $+3 ; NO ; SI CLRF DECINE ; RESETTA UNITA' INCF CENT,F ; INCREMENTA DECINE DECFSZ AUX,F ; FINE DELLA CONVERSIONE ? GOTO $-.14 ; NO - RITORNA O/ CONTINUARE CONVERSIONE RETURN ; SI Link al commento Condividi su altri siti More sharing options...
giacomo56 Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 La soluzione più semplice, secondo me, è quella che hai descritto tu che in C si traduce così: centi = n%10; deci = (n/10)%10; uni = n/100;dove n è il valore della variabile (<1000).Ciao. Link al commento Condividi su altri siti More sharing options...
giacomo56 Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 Scusa, ho invertito i valori, mi correggo: uni = n%10; deci = (n/10)%10; centi = n/100;Ciao. Link al commento Condividi su altri siti More sharing options...
dlgcom Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 Giacomo a ragione , in C e' semplice ma attenzione a volte il codice generato e' molto piu' grande di quello che si puo' fare in assempber.Ricordate che la fam 16f non ha la moltiplicazione hardware quindi usate moltiplicazioni e divisioni con cautela.Per esempio il CCS genera il seguente codice per fare centi = n%10;deci = (n/10)%10;uni = n/100;Usando molte piu' righe di programma e ram che in ASM.Naturalmente prendete questa a titolo didattico , non voglio dirvi come scrivere un prg era solo per segnalare alcune insidie nel scrivere in C .per pic con poca memoria come i 16f84 potrebbe dare problemi con prg grandi. 0004: MOVF 15,W 0005: CLRF 0D 0006: SUBWF 14,W 0007: BTFSC 03.0 0008: GOTO 00C 0009: MOVF 14,W 000A: MOVWF 0C 000B: GOTO 018 000C: CLRF 0C 000D: MOVLW 08 000E: MOVWF 16 000F: RLF 14,F 0010: RLF 0C,F 0011: MOVF 15,W 0012: SUBWF 0C,W 0013: BTFSC 03.0 0014: MOVWF 0C 0015: RLF 0D,F 0016: DECFSZ 16,F 0017: GOTO 00F 0018: RETLW 00 0019: CLRF 04 001A: MOVLW 1F 001B: ANDWF 03,F .................... int n,uni,deci,centi; .................... .................... .................... uni = n%10; 001C: MOVF 0F,W 001D: MOVWF 14 001E: MOVLW 0A 001F: MOVWF 15 0020: CALL 004 0021: MOVF 0C,W 0022: MOVWF 10 .................... deci = (n/10)%10; 0023: MOVF 0F,W 0024: MOVWF 14 0025: MOVLW 0A 0026: MOVWF 15 0027: CALL 004 0028: MOVF 0D,W 0029: MOVWF 14 002A: MOVLW 0A 002B: MOVWF 15 002C: CALL 004 002D: MOVF 0C,W 002E: MOVWF 11 .................... centi = n/100; 002F: MOVF 0F,W 0030: MOVWF 14 0031: MOVLW 64 0032: MOVWF 15 0033: CALL 004 0034: MOVF 0D,W 0035: MOVWF 12 .................... .................... } Link al commento Condividi su altri siti More sharing options...
dlgcom Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 Se puo' interessare questo codice e' per implementare la routine asm nel compilatore CCS.Non ho provato in pratica , ma dovrebbe funzionare. #include <16f84.h> #define STATUS 0X03 #define Z 2 int unita,decine,cent,aux; void bcd(int n){ int aux; #asm ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * CONVERSIONE HEX BCD * ; * W [HEX] = DEZENA [DEC]; UNIDADE [DEC] * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; QUESTA ROUTINE RICEVE UN ARGOMENTO PASSATO PER WORK E RITORNA NELLE ; VARIABILI DEZENA E UNIDADE IL VAL. BCD CORRISPONDENTE . MOVWF AUX ; SALVA VALORE DA CONVERTIRE IN AUX CLRF UNITA CLRF DECINE ; RESETTA REGISTRI CLRF CENT MOVF AUX,F BTFSC STATUS,Z ; VALORE DA CONVERTIRE = 0 ? RETURN ; SI - RITORNA INIZ: ; NO INCF UNITA,F ; INCREMENTA UNITA' MOVF UNITA,W XORLW 0X0A BTFSS STATUS,Z ; UNITA' = 10d ? GOTO FINE ; NO ; SI CLRF UNITA ; RESETTA UNITA' INCF DECINE,F ; INCREMENTA DECINE MOVF DECINE,W XORLW 0X0A BTFSS STATUS,Z ; UNITA' = 10d ? GOTO FINE ; NO ; SI CLRF DECINE ; RESETTA UNITA' INCF CENT,F ; INCREMENTA DECINE FINE: DECFSZ AUX,F ; FINE DELLA CONVERSIONE ? GOTO INIZ ; NO - RITORNA O/ CONTINUARE CONVERSIONE RETURN ; SI #endasm } main(){ int n; n=125; bcd(n); } Che da un codice minore 0000: MOVLW 00 0001: MOVWF 0A 0002: GOTO 01C 0003: NOP .................... MOVWF AUX ; SALVA VALORE DA CONVERTIRE IN AUX 0004: MOVWF 14 .................... CLRF UNITA 0005: CLRF 0E .................... CLRF DECINE ; RESETTA REGISTRI 0006: CLRF 0F .................... CLRF CENT 0007: CLRF 10 .................... .................... MOVF AUX,F 0008: MOVF 14,F .................... BTFSC STATUS,Z ; VALORE DA CONVERTIRE = 0 ? 0009: BTFSC 03.2 .................... RETURN ; SI - RITORNA 000A: RETURN .................... .................... INIZ: ; NO .................... INCF UNITA,F ; INCREMENTA UNITA' 000B: INCF 0E,F .................... .................... MOVF UNITA,W 000C: MOVF 0E,W .................... XORLW 0X0A 000D: XORLW 0A .................... BTFSS STATUS,Z ; UNITA' = 10d ? 000E: BTFSS 03.2 .................... GOTO FINE ; NO 000F: GOTO 018 .................... ; SI .................... CLRF UNITA ; RESETTA UNITA' 0010: CLRF 0E .................... INCF DECINE,F ; INCREMENTA DECINE 0011: INCF 0F,F .................... .................... MOVF DECINE,W 0012: MOVF 0F,W .................... XORLW 0X0A 0013: XORLW 0A .................... BTFSS STATUS,Z ; UNITA' = 10d ? 0014: BTFSS 03.2 .................... GOTO FINE ; NO 0015: GOTO 018 .................... ; SI .................... CLRF DECINE ; RESETTA UNITA' 0016: CLRF 0F .................... INCF CENT,F ; INCREMENTA DECINE 0017: INCF 10,F .................... .................... FINE: .................... DECFSZ AUX,F ; FINE DELLA CONVERSIONE ? 0018: DECFSZ 14,F .................... GOTO INIZ ; NO - RITORNA O/ CONTINUARE CONVERSIONE 0019: GOTO 00B .................... .................... RETURN ; SI 001A: RETURN .................... .................... #endasm .................... } 001B: GOTO 024 (RETURN) .................... .................... main(){ .................... 001C: CLRF 04 001D: MOVLW 1F 001E: ANDWF 03,F .................... int n; .................... .................... .................... n=125; 001F: MOVLW 7D 0020: MOVWF 12 .................... bcd(n); 0021: MOVF 12,W 0022: MOVWF 13 0023: GOTO 004 Link al commento Condividi su altri siti More sharing options...
wnc Inserita: 29 settembre 2004 Segnala Share Inserita: 29 settembre 2004 Se hai a disposizione la funzione itoa() potresti fare come di seguito:char string[Num_Display); //Dichiari l'array che conterrà le cifre. Num_Display è il n° dei displayitoa(Informazione,string); //Informazione è la variabile di interesse string[0]= Ultima_Cifra;string[1]=Penultima_Cifra;.......Le cifre cosi sono in char. Ciao Link al commento Condividi su altri siti More sharing options...
Giorgio Demurtas Inserita: 29 settembre 2004 Autore Segnala Share Inserita: 29 settembre 2004 quante risposte!ok, quindi come avevo pensato io è corretto (dal punto di vista matematico), ma ho capito (grazie dlgcom) che conviene usare una routine fatta in asm. Ho letto una parte è ho capito come funziona la routine, è un po come quando il routter ricava l'indirizzo di sotto rete di un host dal suo ind IP facendo l'end bit a bit (invece nella routine di sopra fa l'or esclusivo) con la maschera di sottorete... ok non divaghiamo ho guardato nel manuale, ma non c'è itoa().Domani provo questa parte di sw sull'hardware e comincio a pensare al resto dal sw.a prestograzie Link al commento Condividi su altri siti More sharing options...
giacomo56 Inserita: 30 settembre 2004 Segnala Share Inserita: 30 settembre 2004 Ciao a tutti.L'osservazione di dlgcom è giusta, la conclusione di Giorgio "conviene usare una routine fatta in asm", secondo me, in generale no. Mi spiego.Se decido di usare il C lo faccio per usufruire dei vantaggi che questo comporta. Se però, scritte quattro righe, comincio a chiedermi "ma se traduco questa istruzione in assembly risparmio memoria, se traduco quest'altra uso meno cicli" ecc, allora tanto vale usare l'assembly dall'inizio. E' chiaro che se io ho già una routine scritta in assembler pronta e testata mi conviene utilizzarla ma, in generale, continuerò a usare il C finchè possibile. Se ad un certo punto mi accorgo che ho problemi di spazio prima cerco di ottimizzare il codice C e dopo penso a sostituire le parti più critiche con l'assembly.Ciao. Link al commento Condividi su altri siti More sharing options...
Giorgio Demurtas Inserita: 5 ottobre 2004 Autore Segnala Share Inserita: 5 ottobre 2004 troppo facile farlo funzionare al primo colpo....infatti non funziona. ho inserito la vostra routine, ma non viene più eseguito il multiplex e compare sempe lo 0 alla cifra delle centinaia, in pratica non viene fatto l'interrupt.l'unica cosa che non mi è chiara è cos'è SATUS, potete spiegarmelo? e Z? è solo una variabile di appoggio che vine inizializzata a 2?//contachilometri con display //giorgio demurtas //agosto-settembre 2004 //il watchdog dev'essere disable #include "C:\Documenti\pic c\nuovi_progetti\ckm_numero\ckm_numero.h" #define STATUS 0X03 #define Z 2 #define uni PIN_A1 //18 #define deci PIN_A2 //1 #define centi PIN_A3 //2 int8 numero, velox, cifra_on, tempoc, UNITA, DECINE, CENT, AUX; //tempoc è il tempo di campionamento. 1000 ms //-------------------------------------------------------------------------- #int_RTCC RTCC_isr() //Interrupt Service Routine { cifra_on=cifra_on+1; if (cifra_on==4) cifra_on=1; tempoc=tempoc+1; if (tempoc==250) tempoc=0; } //-------------------------------------------------------------------------- void bcd(int8 velox) { //funzione per separare le tre cifre #asm ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * CONVERSIONE HEX BCD * ; * W [HEX] = DEZENA [DEC]; UNIDADE [DEC] * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; QUESTA ROUTINE RICEVE UN ARGOMENTO PASSATO PER WORK E RITORNA NELLE ; VARIABILI DEZENA E UNIDADE IL VAL. BCD CORRISPONDENTE . MOVWF AUX ; SALVA VALORE DA CONVERTIRE IN AUX CLRF UNITA CLRF DECINE ; RESETTA REGISTRI CLRF CENT MOVF AUX,F BTFSC STATUS,Z ; VALORE DA CONVERTIRE = 0 ? RETURN ; SI - RITORNA INIZ: ; NO INCF UNITA,F ; INCREMENTA UNITA' MOVF UNITA,W XORLW 0X0A BTFSS STATUS,Z ; UNITA' = 10d ? GOTO FINE ; NO ; SI CLRF UNITA ; RESETTA UNITA' INCF DECINE,F ; INCREMENTA DECINE MOVF DECINE,W XORLW 0X0A BTFSS STATUS,Z ; UNITA' = 10d ? GOTO FINE ; NO ; SI CLRF DECINE ; RESETTA UNITA' INCF CENT,F ; INCREMENTA DECINE FINE: DECFSZ AUX,F ; FINE DELLA CONVERSIONE ? GOTO INIZ ; NO - RITORNA O/ CONTINUARE CONVERSIONE RETURN ; SI #endasm } void main() { //inizio programma principale set_tris_a(0x00); set_tris_b(0x00); //numero=0; tempoc=0; cifra_on=1; output_b(0x03); //visualizza il numero 0 setup_timer_0 (RTCC_DIV_256|RTCC_INTERNAL); // imposto il prescaler a 128 divisioni in modo da ottenere // una frequenza di incremento del registro TMR0 di // 1 Mhz/128=7812.5 Hz //TMR0 passa per lo 0 con una frequenza di 50 Hz //7812.5/156=50 Hz enable_interrupts(int_rtcc); //abilito l'interrupt da tmr0 enable_interrupts(global); //abilito tutti gli interrupts while(1) //ciclo continuo { velox=557; bcd(velox); if (cifra_on==1) { output_bit(centi, 1); numero=CENT; } else output_bit(centi, 0); if (cifra_on==2) { output_bit(deci, 1); numero=DECINE; } else output_bit(deci, 0); if (cifra_on==3) { output_bit(uni, 1); numero=UNITA; } else output_bit(uni, 0); // invio del numero if (numero==0) output_b(0x03); if (numero==1) output_b(0x9F); if (numero==2) output_b(0x25); if (numero==3) output_b(0x0D); if (numero==4) output_b(0x99); if (numero==5) output_b(0x49); if (numero==6) output_b(0x41); if (numero==7) output_b(0x1F); if (numero==8) output_b(0x01); if (numero==9) output_b(0x09); // } //fine ciclo while } //fine main ho provato allora un programma che non contiene la vostra routine e l'interrupt viene eseguito (e di conseguenza anche il multiplex). posso mettere la routine in un'altro file e poi inserire un #include nel prog principale? come si fa? ecco il listato: //contachilometri con display //giorgio demurtas //agosto-settembre 2004 //il watchdog dev'essere disable #include "C:\Documenti\pic c\nuovi_progetti\prova_mpx\prova_mpx.h" #define uni PIN_A1 //18 #define deci PIN_A2 //1 #define centi PIN_A3 //2 int8 numero, velox, cifra_on, tempoc; //tempoc è il tempo di campionamento. 1000 ms //-------------------------------------------------------------------------- #int_RTCC RTCC_isr() //Interrupt Service Routine { cifra_on=cifra_on+1; if (cifra_on==4) cifra_on=1; tempoc=tempoc+1; if (tempoc==250) tempoc=0; } //-------------------------------------------------------------------------- void main() { //inizio programma principale set_tris_a(0x00); set_tris_b(0x00); numero=0; tempoc=0; cifra_on=1; output_b(0x41); //visualizza il numero 6 setup_timer_0 (RTCC_DIV_256|RTCC_INTERNAL); // imposto il prescaler a 256 divisioni in modo da ottenere // una frequenza di incremento del registro TMR0 di // 1 Mhz/256=3906.25 Hz //TMR0 passa per lo 0 con una frequenza di 15.2 Hz //3906.25/256=15.2 Hz enable_interrupts(int_rtcc); //abilito l'interrupt da tmr0 enable_interrupts(global); //abilito tutti gli interrupts while(1) //ciclo continuo { if (cifra_on==1) { output_bit(centi, 1); } else output_bit(centi, 0); if (cifra_on==2) { output_bit(deci, 1); } else output_bit(deci, 0); if (cifra_on==3) { output_bit(uni, 1); } else output_bit(uni, 0); // invio del numero /* if (numero==0) output_b(0x03); if (numero==1) output_b(0x9F); if (numero==2) output_b(0x25); if (numero==3) output_b(0x0D); if (numero==4) output_b(0x99); if (numero==5) output_b(0x49); if (numero==6) output_b(0x41); if (numero==7) output_b(0x1F); if (numero==8) output_b(0x01); if (numero==9) output_b(0x09); */ } //fine ciclo while } //fine main Link al commento Condividi su altri siti More sharing options...
dlgcom Inserita: 5 ottobre 2004 Segnala Share Inserita: 5 ottobre 2004 Non ho letto tutto , ma c'e' un errore .la variabile velox e' a 8 bit ma tenti di caricare in velox 557 il massimo e' 255. Link al commento Condividi su altri siti More sharing options...
giacomo56 Inserita: 5 ottobre 2004 Segnala Share Inserita: 5 ottobre 2004 STATUS indica il registro di controllo del pic d'indirizzo 0x03. Z indica il bit 2 di STATUS.Z è detto bit di zero perchè viene messo a 1 se il risultato dell'ultima istruzione eseguita è zero altrimenti Z = 0 (però non tutte le istruzioni modificano il valore di Z) e viene utilizzato nei salti condizionati.STATUS corrisponde in altri micro al registro dei flags.Ciao. Link al commento Condividi su altri siti More sharing options...
Giorgio Demurtas Inserita: 5 ottobre 2004 Autore Segnala Share Inserita: 5 ottobre 2004 ciao a tutti,si luca hai perfettamente ragione, ho corretto ma purtroppo c'è qualche altro errore...Grazie giacomo, ho capito.Ho fatto diverse prove commentando parti di sw e ho notato che se faccio la chiamata alla subroutine non viene più fatto l'interrupt. cifra_on=1; output_b(0x1F); //visualizza il numero 7 se lascio la chiamata ( bcd(velox); ) compare il numero 7 sulla cifra 1 e le altre cifre spente.se tolgo la chiamata compare il numero 7 su tutte le cifre multiplexate.luca, ho visto che la prima volta che hai postato la routine da sola ci sono delle differenze con le altre volte per es. nei GOTO oppure negli ultimi commenti (CLRF DECINE ; RESETTA UNITA'INCF CENT,F ; INCREMENTA DECINE ) ma mi sembra che l'errore sia solo nel commento quindi non cambia niente.non capisco com'è che la routine intralci l'interrupt... Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
Crea un account o accedi per commentare
Devi essere un utente per poter lasciare un commento
Crea un account
Registrati per un nuovo account nella nostra comunità. è facile!
Registra un nuovo accountAccedi
Hai già un account? Accedi qui.
Accedi ora