home | area personale         schemi | tutorial | robotica | pic micro | recensioni         forum | chat irc         faq | contatti         store | Ordina PCB
username
password
cerca

 
FORUM: Pic Micro
Tutto quanto riguarda questi microprocessori... progetti, suggerimenti, aiuti, discussioni...ecc


contatore ballerino16f877
     
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




una ogni 10 livelli una ogni 10 livelli


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




una ogni 100 livelli
una ogni 10 livelli


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




una ogni 100 livelli
una ogni 10 livelli


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




una ogni 100 livelli
una ogni 10 livelli


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.
segui questo thread con grixFC, per questa funzione devi aver installato il software grixFC

torna su
     

Come utente anonimo puoi leggere il contenuto di questo forum ma per aprire una discussione
o per partecipare ad una discussione esistente devi essere registrato ed accedere al sito




 







 
 
indietro | homepage | torna su copyright © 2004/2024 GRIX.IT - La community dell'elettronica Amatoriale