|
Autore |
Messaggio |
opzioni |
graziano2000
postato il: 04.11.2017, alle ore 17:49 |
contatore ballerino16f877
salve a tutti ho un piccolo problema, vi posto il codice
#include <xc.h>
#define _XTAL_FREQ 20000000
#pragma config FOSC = XT
#pragma config WDTE = OFF
#include <delay.c>
#include <delay.h>
#include <LCD_44780.h>
#include <LCD_44780.C>
void interrupt isr ()
{
INTCONbits.T0IF=0; //AZZERA IL FLAG DEL TIMER
TMR0=100 ; //CARICA IL VALORE DI TIMER0
TMR1L=0;
TMR1H=0;
}
void main(void) {
PORTA=0b11111111;//Configuro il verso delle porte
PORTB=0b11111111;
PORTC=0b11111111;
PORTD=0b00000000;
PORTE=0b11111111;
TRISD= 0; //INIZIALIZZO LE PORTE
//setup del timer0 AFFINCHE GENERI L\'INTERRUPT 1ms
OPTION_REGbits.PSA=0;//PRESCALER ASSEGNATO AL TIMER 0 E NON AL WDT
OPTION_REGbits.PS=0b100;//VALORE DEL PRESCALER 1:32
OPTION_REGbits.T0CS =0;//CLOCK INTERNO
INTCONbits.T0IF=0; //AZZERA IL FLAG DEL TIMER
TMR0=100; //CARICA IL VALORE DI TIMER0
INTCONbits.T0IE=1 ; //abilita l\'interrupt del timer 0
INTCONbits.GIE=1 ; //ABILITA I GLOBAL INTERRUPT
//setup timer 1
T1CONbits.T1CKPS=00; //PRESCALER 1:1
T1CONbits.T1OSCEN=1;// oscillatore al quarzo abilitato
T1CONbits.TMR1CS=1;//sorgente del clock esterno
T1CONbits.T1SYNC=1;
T1CONbits.TMR1ON=1;
while(1)
{
LCD_initialize(20); // inizializzo l\'LCD
LCD_write_message(\"pz:\");
LCD_write_integer ((TMR1H <<8) + TMR1L,4,LCD_ZERO_CLEANING_ON);
}
}
funziona in parte, mi spiego meglio :
- timer0 dovrebbe scandire il tempo e generare l\'interrupt dopo 1ms
- timer1 dovrebbe contare gli impulsi
- l\'lcd mostrare il valore
sembra che tutto funzioni ma fornendo un onda quadra stabile come clock per timer 1 sull\'lcd vedo i numeri da 1 a 50 salire e scendere in modo casuale!!!
dove ho sbagliato ?
vi ringrazio in anticipo
La vita potrebbe essere divisa in tre fasi: Rivoluzione, Riflessione e Televisione.Si comincia con il voler cambiare il mondo e si finisce col cambiare i canali.
http://graziano-page.simplesite.com/ |
|
elektorplus
postato il: 06.11.2017, alle ore 17:34 |
Avendo abilitato T1OSCEN presumo che il segnale con gli impulsi sia sul pin RC1.
Effettui la lettura del TMR1 nel main mentre lo azzeri in un interrupt, questo non va bene.
Presupponiamo che il programma principale sia alla lettura del registro TMR1H nella funzione di "LCD_write_integer" (TMR1L già letto) e avviene l'interrupt del timer0.
Il main quindi si interrompe ed entra all'interno dell'interrupt, il TMR1 viene resettato e si prosegue con la funzione dell'LCD.
A questo punto però la lettura viene conclusa con un valore pari a 0, ne segue un errata visualizzazione.
Per sistemare devi disabilitare l'interrupt sul timer0 prima della funzione "LCD_Write_integer" e riabilitarlo dopo.
Inoltre bloccherei anche il conteggio sul timer1 per essere sicuro che proprio mentre viene eseguita la funzione di stampa su LCD non arrivi un impulso a sporcare i registri del conteggio.
Se la tempista di 1ms deve essere molto precisa, sapendo quanto tempo viene speso per gestire la funzione di stampa LCD si può aggiustare il preload del timer0 in modo che il reset del TMR1 sia molto vicino a quanto desiderato.
http://elektor.altervista.org/ |
|
graziano2000
postato il: 12.11.2017, alle ore 12:40 |
ti ringrazio per il cortese aiuto . appena mi libero un po provo le modifiche che mi hai consigliato e vediamo se funziona . grazie di nuovo
La vita potrebbe essere divisa in tre fasi: Rivoluzione, Riflessione e Televisione.Si comincia con il voler cambiare il mondo e si finisce col cambiare i canali.
http://graziano-page.simplesite.com/ |
|
agric
postato il: 13.11.2017, alle ore 05:32 |
Quando stampi su lcd usa la copia delle variabili del tmr1L_H, copia che aggiorni ad ogni interupt prima di azzerare il tmr1
meglio essere un granello di pepe che una cacca d'asino |
|
primok
postato il: 13.11.2017, alle ore 09:31 |
Azzero Timer1 inizialmente nel main
TMR1=0;
In Timer0 (ogni 1 msec) {
Enable_Counter^=1;//Abilta o disabilta conteggio impulsi esterni
if(Enable_Counter){ //Se vale 1
TMR1ON=1;//Accende Timer1 per conteggio impulsi
Enable_Display=0;//Disabilta visualizzazione sul display
}else{
TMR1ON=0;//Spegne Timer1
Pulse_Counter=TMR1;//Carica il contenuto del timer1 nella variabile
TMR1=0;//Azzero il valore del timer1 per un nuovo conteggio
Enable_Display=1;
}
}
Nel main
main(){
...
LCD_initialize(20); // inizializzo l\'LCD solo una volta!!!
while(1){
if( Enable_Display){
LCD_write_message(\"pz:\");
LCD_write_integer ((TMR1H <<8) + TMR1L,4,LCD_ZERO_CLEANING_ON);
}
}
}
Più piccola è la mente più grande è la presunzione. |
|
graziano2000
postato il: 18.11.2017, alle ore 17:28 |
perdonami primok, ma non mi è molto chiaro quello che mi consigli di fare !!
La vita potrebbe essere divisa in tre fasi: Rivoluzione, Riflessione e Televisione.Si comincia con il voler cambiare il mondo e si finisce col cambiare i canali.
http://graziano-page.simplesite.com/ |
|
graziano2000
postato il: 18.11.2017, alle ore 20:14 |
in ogni caso questo è quello che sono riuscito a fare , ancora non è molto preciso ma almeno fornendo un segnale a 100HZ la lettura oscilla tra 80 e 140 lo so non è normale ma almeno sono sulla buona strada #include <xc.h>
#define _XTAL_FREQ 20000000
#pragma config FOSC = XT
#pragma config WDTE = OFF
#include <delay.c>
#include <delay.h>
#include <LCD_44780.h>
#include <LCD_44780.C>
void interrupt isr ()
{
INTCONbits.T0IF=0; //AZZERA IL FLAG DEL TIMER
INTCONbits.T0IE=0;
TMR0=60; //CARICA IL VALORE DI TIMER0
LCD_initialize(20); // inizializzo l\'LCD
LCD_write_message("pz:");
LCD_write_integer ((TMR1H <<8) + TMR1L,4,LCD_ZERO_CLEANING_ON);
INTCONbits.T0IE=1;
TMR1L=0;
TMR1H=0;
}
void main(void) {
PORTA=0b11111111;//Configuro il verso delle porte
PORTB=0b11111111;
PORTC=0b11111111;
PORTD=0b00000000;
PORTE=0b11111111;
TRISD= 0; //INIZIALIZZO LE PORTE
//setup del timer0 AFFINCHE GENERI L\'INTERRUPT 10ms
OPTION_REGbits.PSA=0;//PRESCALER ASSEGNATO AL TIMER 0 E NON AL WDT
OPTION_REGbits.PS=0b111;//VALORE DEL PRESCALER 1:256
OPTION_REGbits.T0CS =0;//CLOCK INTERNO
INTCONbits.T0IF=0; //AZZERA IL FLAG DEL TIMER
TMR0=60; //CARICA IL VALORE DI TIMER0
INTCONbits.T0IE=1 ; //abilita l\'interrupt del timer 0
INTCONbits.GIE=1 ; //ABILITA I GLOBAL INTERRUPT
//setup timer 1
T1CONbits.T1CKPS=00; //PRESCALER 1:1
T1CONbits.T1OSCEN=0;// oscillatore esterno non abilitato
T1CONbits.TMR1CS=1;//sorgente del clock esterno
T1CONbits.T1SYNC=1;
T1CONbits.TMR1ON=1;
while(1)
{
}
}
ovviamente si accettano consigli
La vita potrebbe essere divisa in tre fasi: Rivoluzione, Riflessione e Televisione.Si comincia con il voler cambiare il mondo e si finisce col cambiare i canali.
http://graziano-page.simplesite.com/ |
|
primok
postato il: 18.11.2017, alle ore 20:32 |
graziano2000: perdonami primok, ma non mi è molto chiaro quello che mi consigli di fare !!
Partiamo dal presuppostto che l'inizializzazione dell'LCD e le relative funzioni funzionino bene.
Il timer0 abbiamo detto che è impostato per avere un'interrupt ogni 1 msec.
Quindi all'interno della void interrupt isr () ci va ogni 1 msec.
Nei pic 16F esiste una solo routine per l'analisi di tutti gli interrupt.In questo esempio interessa l'analisi del interrupt flag T0IF.
Quindi qualora questo va a 1 vuol dire che è trascorso 1 msec dopo l'accensione del Timer0. Quindi entrerà nella routine void interrupt isr () .
A questo punto si ricarica
INTCONbits.T0IF=0; //AZZERA IL FLAG DEL TIMER
TMR0=100 ; //CARICA IL VALORE DI TIMER0
TMR1L=0;
TMR1H=0;
sempre per avere un interrupt sempre ogni 1 msec ed in pù si analizza un flag che io ho chiamato Enable_Counter.
Con l'istruzione Enable_Counter^=1; inverto lo stato di questo flag ogni 1 msec.
Percui la prima volta va a 1 la seconda a 0 poi la terza di nuovo a 1 e così via ogni msec.
Poi sempre all'interno di questa routine posso fare 2 scelte in funzione del valore del flag Enable_Counter.
1) Se vale 1 accendo il contatore TIMER1 per contare con gli impulsi che arrivano dall'esterno e disabilito la visualizzazione sul display resettando la varabile Enable_Display=0; In questo modo si manterrà il vecchio valore misurato (numero di impulsi contati in 1 msec)
2)Trascorso 1 msec si entrerà di nuovo nella routine e a questo punto la variabile Enable_Counter cambierà di nuovo il suo stato passando da 1 a 0.
Percui verranno eseguite le istruzioni
TMR1ON=0;//Spegne Timer1
Pulse_Counter=TMR1;//Carica il contenuto del timer1 nella variabile
TMR1=0;//Azzero il valore del timer1 per un nuovo conteggio
Enable_Display=1;
cioè si ferma il conteggio degli impulsi esterni spegnedo il Timer1;
Si trasferirisce il contenuto di TMR1 in una variabile che conterra gli impulsi contati provenienti dall'esterno in 1 msec;
poi si azzera il TIMER1 per un nuovo conteggio che ripartirà dopo 1 msec.
Si abilita la visualizzazione del display.
Dopo 1 msec si ripete il conteggio e si blocca la visualizzazione.
Primok_V
Più piccola è la mente più grande è la presunzione. |
|
graziano2000
postato il: 19.11.2017, alle ore 16:48 |
perfetto grazie mille per il chiarimento.
avrei un ultima domanda : ho la necessita di memorizzare il valore massimo che raggiunge una variabile e stamparlo su LCD alla pressione di un pulsante .Per quanto riguarda lcd e pulsante non ci sono problemi,la domanda è come faccio a memorizzare questo valore ?esiste una funzione o qualcosa del genere ? grazie per l'aiuto .....
La vita potrebbe essere divisa in tre fasi: Rivoluzione, Riflessione e Televisione.Si comincia con il voler cambiare il mondo e si finisce col cambiare i canali.
http://graziano-page.simplesite.com/ |
|
primok
postato il: 20.11.2017, alle ore 09:00 |
graziano2000: perfetto grazie mille per il chiarimento.
avrei un ultima domanda : ho la necessita di memorizzare il valore massimo che raggiunge una variabile e stamparlo su LCD alla pressione di un pulsante .Per quanto riguarda lcd e pulsante non ci sono problemi,la domanda è come faccio a memorizzare questo valore ?esiste una funzione o qualcosa del genere ? grazie per l'aiuto .....
Memorizzi i valori della variabile in un array di n elementi.
Poi alla pressione del pulsante invochi una funzione che "pesca" il massimo valore tra gli elementi memorizzati.
Potrebbe essere una cosa del genere
unsigned int array[100], max_value;
unsigned int Ret_Max_value(void){
int i=0;
max_value = array[0];
for (i = 1; i < 100; i++)
{
if (array[i] > max_value)
{
max_value = array[i];
}
}
retrutn max_value;
}
Più piccola è la mente più grande è la presunzione. |
|
|