Newsgroup: it.hobby.elettronica.digitale
Titolo: Routine per conteggio impulsi su PIC

Devo conteggiare gli impulsi che mi giungono in un secondo ad una delle
porte di un PIC16F876.
Non ho idea di come fare la routine che tenga diciamo aperto il conteggio
per esattamente 1 secondo, non di più ne di meno ed in modo che la possa
richiamare quando e come mi pare a me.
Mi date qualche idea?? Possiiblmente in linguaggio Mikrobasic ??
Grazie

Giovanni wrote:

Puoi usare due timer: il primo ti serve per generare la "finestra" di un 
secondo per il conteggio. L'altro timer (tipicamente il Timer1) lo 
configuri come counter con trigger esterno. In pratica il programmino è 
molto banale: avvii il processo di conteggio azzerando il timer1 e 
avviando l'altro. Allo scadere del secondo leggi il registro del timer1 
e hai finito :)
Questo in generale, non hai però specificato la frequenza del segnale di 
ingresso. Leggi il datasheet per verificare se sei dentro il range di 
frequenze accettabili.
Marco / iw2nzm

La cosa interessa anche a me:
se TMR1 lo usi per rilevare le pulsazioni, per il delay si può usare
un semplice delay_ms(1000) oppure intendi proprio utilizzare un altro
timer tipo TMR0 ?
Purtroppo non ho copiato il codice dal PC che uso in lab. Domani
magari lo posto e chio vorrà ci darà un'occhiata...
Per ora dico che con il Delay semplice ho ottenuto (modificando
l'esempio TMR1 incluso in mikrobasic) i valori a 16 bit di TMR1H e
TMR1L che con ByteToStr trasformo in stringhe da visualizzare su un
LCD. Ogni secondo si aggiornano, perciò presumo che l'interrupt ci
sia, ma i numeri non mi danno fiducia...
Infine: tu cos intendi per legger il registro di TMR1 e cosa consigli
per il delay ?
Grazie
Matteo IV3YNB

 ha scritto nel messaggio 
news:1190649163....@o80g2000hse.googlegroups.com...


 per il delay ?
Leggere i due registri low e high associati al Timer1 per avere il 
valore complessivo a 16 bit.
Ciao!
Marco / iw2nzm

 bit (TMR1H + TMR1L).
controllerò meglio !
Marco: ti chiedo gentilmente, tenedo conto che ho usato TMR1 come
counter, quale timer utilizzerebbe ? rimane TMR0 e TMR2: quale è
meglio ? come mai la routine delay_ms(1000) non è adatta ?
percorso esempi:
C:\Programmi\Mikroelektronika\mikroBasic\Examples\P16\
esempio TMR1:
'******************************************************************************
' microcontroller P16f877A
'
' Project Timer1
' This project is designed to work with PIC 16F877A
' with minor adjustments, it should work with any other PIC MCU
' taht has TIMER1.
'
' This code demonstrates using interrupts in mikroBasic.
' Program toggles leds on PORTB.
'******************************************************************************
program Timer1
dim counter as byte
sub procedure interrupt
  counter = counter + 1
  pir1.0 = 0       ' Clear TMR1IF
end sub
main:
  TRISB = 0
  T1CON = 1
  pir1.TMR1IF = 0  ' Clear TMR1IF
  PIE1 = 1         ' Enable interrupts
  PORTB = $F0
  counter = 0      ' Initialize counter
  INTCON= $C0
  while TRUE
    if counter = 152 then  ' If counter is 152, then toggle PORTB leds
and reset counter
      PORTB  = not(PORTB)
      counter = 0
    end if
  wend
end.
ed ecco il mio lavoro di ieri... da rivedere... ma non saprei dove
per esempio, io ho abilitato e poi disabilitato l'interrupt, dopo 1
secondo di attesa e di misura... logicamente, secondo me, "ci stà"...
program freq001
'******************************
' frequenzimetro con PIC16F876
'******************************
' INFO:
'
' ingresso f su TRISC RA0
' LCD su TRISB (standard)
'******************************
'
'********************
'   VARIABLES DEC.
'********************
dim counter as word
dim countxt as string[5]
dim textH as string[5]
dim textL as string[5]
'********************
'   SUB PROCEDURES
'********************
sub procedure interrupt
  counter = counter + 1
  pir1.0 = 0       	' clear TMR1IF
end sub
'********************
'********************
'   PROGRAM MAIN
'********************
'********************
main:
     trisb = 0 		'portB: tutte come uscita per LCD
     trisc = 1 		'portC: tutte come entrate per TMR1
     T1CON = $02       	'TMR1CS=1 --> Timer1=counter
     delay_ms(200)	'aspetta prima di inizializzare l'LCD
     '*************************** LCD *******************************
     lcd_init(PORTB)                       'inizializzazione LCD
     lcd_cmd(LCD_CLEAR)                    'cancella LCD
     lcd_cmd(LCD_CURSOR_OFF)               'cursore OFF
     lcd_out(1,1," frequenzimetro ")       'scrive su riga 1 posizione
1
     lcd_out(2,1,"by IV3YNB Matteo")       'scrive su riga 2 posizione
1
     delay_ms(1000)			   'aspetta 1 secondo
     lcd_cmd(LCD_CLEAR)			   'cancella LCD
     lcd_out(1,1,"H:")			   'titolo per TMR1H prima riga
     lcd_out(1,9,"L:")			   'titolo per TMR1L prima riga
     lcd_out(2,1,"Counter:")		   'titolo per COunter seconda riga
     '*************************** LCD *******************************
fre:
             T1CON = 1        'setta TMR1 come counter
             pir1.0 = 1       'setta flag TMR1IF
             PIE1 = 1         'abilita interrupt TMR1
             delay_ms(1000)   'aspetta 1 secondo
             PIE1 = 0         'disabilita interrupt TMR1
             INTCON= $C0      'setta GIE e PEIE a 1
		   'gestione registri TMR1H e TMR1L
                   ByteToStr(TMR1H, textH)     'converte valore freq
in stringa
                   ByteToStr(TMR1L, textL)     'converte valore freq
in stringa
                   lcd_out(1,3,textH)	'scrivi TMR1H
                   lcd_out(1,11,textL)  'scrivi TMR1L
                   'gestione counter
                   WordToStr(counter, countxt)
                   lcd_out(2,9,countxt)
		   counter = 0      'Initialize counter
             goto fre		    'ricalcola la frequenza
end.

...lasciate stare il mio listato... devo aver scritto un mucchio di
ca***te... :-)
riposto quando avrò qualcosa di migliore da postere...
Però i consigli saranno ben accetti...
Matteo

 end.
Non ho visto l'azzeramento dei timer1 prima dell'inizio dell'acquisizione.
Ciao!
Marco / iw2nzm

 ha scritto nel messaggio 
news:0McKi.124159$U01.9...@twister1.libero.it...


 quindi utilizzabile al posto di apposita routine basata su interrupt.
Se sfrutta davvero il timer interno può essere allora affidabile. La 
verifica è molto semplice come suggerivo nell'altro post. Un toggle su 
un pin e oscilloscopio alla mano si vede subito.
Ciao!
Marco / iw2nzm





wrote:


 visualizzare questa.
[...]
Ehhh.... ho combinato e postato un casino... come s'è visto e come ho
prontamente segnalato... che figuraccia...
Ma sto pomeriggio qualcosa è cambiato; ecco la storia: basandomi (ma
capendoci ancora poco) ho cercato prima di sfruttare i suggerimenti
sul TMR1 dati dal file incluso negli "examples".
Ho fatto parecchi errori; poi oggi, rifacendo tutto passo dopo passo,
datasheet alla mano, ho fatto come hai suggerito tu in primis: da zero
avvio il conteggio, faccio passare un secondo, leggo i due byte, mando
al display, poi azzero i byte e rifaccio tutto.
Oggi, sul display, ottenevo sulla prima riga i singoli registri TMRH e
TMRL, mentre sulla seconda riga leggevo la loro somma come intuivi
pure tu.
Ovviamente tutto sotto forma di stringa. Tutto girava liscio alle
15.00. :-D
Devo dire che ho avuto parecchia soddisfazione.
Per motivi totalmente estranei all'elettronica :-) non ho il listato
con me su questo PC, ma domani mattina lo posto appena posso dal lab.
Adesso devo tentare di utilizzare un TMR che non sia la solita routine
Delay, anche se l'ho trovata pure io apparentemente affidabile. Poi
devo fare in modo di leggere un frequenza invece del numero di impulsi
(perciò dovrò ricavare prima il periodo di questi impulsi) e che
questa f sia esatta !!! perchè il tutto dovrà essere il display della
mia radio autocostruita... il 876 dovrebbe prestarsi bene a fare
questo.
La strada è lunga ma non ho fretta :-)))
A presto e grazie
Matteo IV3YNB

 questo.
Non ho ancora capito che frequenza vuoi leggere!
Ciao e buon lavoro,
Marco / iw2nzm

 Non ho ancora capito che frequenza vuoi leggere!
mah... fondamentalmente non ho ancora deciso se sull'ordine dei 14 o
10 MHz
per ora mi limito a sperimentare, nel senso che devo imparare a far
fare al PIC ciò che voglio e non ciò che vuole lui...
In fondo troverai il mio listato di ieri: funziona con alcuni limiti,
ossia:
- se accendo il circuito con il segnale già in RC0 lui legge, al
variare dell f del generatore veo TMR1L, TMR1H e la loro somma
variare.
- se accendo il circuito l'LCD segnala tre volte 0, però
all'accensione del generatore di segnale non cambia nulla, come se il
PIC non riconoscesse i fronti di salita...
devo risolvere questa cosa... inoltre voglio usare il TMR0 per il
conteggio dei 1000ms
chi volesse commentare il mio listato è il benvenuto !!!
Ciao e grazie in anticipo
Matteo IV3YNB
program freq001
'******************************
' frequenzimetro con PIC16F876
'******************************
' INFO:
'
' ingresso f su TRISC RC0
' LCD su TRISB (standard)
'******************************
'********************
'   VARIABLES DEC.
'********************
dim textH as string[5]
dim textL as string[5]
dim count as byte
dim countxt as string[5]
'********************
'********************
'   PROGRAM MAIN
'********************
'********************
main:
     delay_ms(10)
     '*************************** TRISx *****************************
     trisb = 0 'portB: tutte come uscita per LCD
     trisc = 1 'portC: tutte come entrata per TMR1
     '*************************** TRISx *****************************
     '*************************** LCD *******************************
     lcd_init(PORTB)                       'inizializzazione LCD
     lcd_cmd(LCD_CLEAR)
     lcd_cmd(LCD_CURSOR_OFF)
     lcd_out(1,1," frequenzimetro ")
     lcd_out(2,1,"by IV3YNB Matteo")
     delay_ms(1000)
     lcd_cmd(LCD_CLEAR)
     lcd_out(1,1,"H:")
     lcd_out(1,9,"L:")
     lcd_out(2,1,"tot:")
     lcd_out(2,9,"f:")
     '*************************** LCD *******************************
     '*************************** TMR1 ******************************
     PIE1.0 = 0           ' TMR1IE=0 --> Disabilita interrupt di TMR1
     T1CON.1 = 1        ' TMR1CS=1 --> Timer1=counter
     T1CON.2 = 0        ' T1SYNC=0 --> Syncronize
     '*************************** TMR1 ******************************
fre:
     T1CON.0 = 1        ' TMR1ON=1 --> Abilita TMR1
        delay_ms(1000)     ' attendi 1 secondo
     T1CON.0 = 0        ' TMR1ON=0 --> Disabilita TMR1
        count = TMR1L + TMR1H       'totale counts
        ByteToStr(TMR1H, textH)     'converte registro countH in
stringa
        ByteToStr(TMR1L, textL)      'converte registro countL in
stringa
        ByteToStr(count, countxt)     'converte valore counts in
stringa
           lcd_out(1,3,textH)
           lcd_out(1,11,textL)
           lcd_out(2,5,countxt)
              TMR1L = 0         'azzera conteggio L
              TMR1H = 0         'azzera conteggio H
goto fre
end.

 conteggio dei 1000ms
Altra considerazione: perché 1 s? Che valore ti aspetteresti di leggere 
nei registri del TMR1 dopo un secondo quando all'ingresso c'è una 
frequenza di 10 MHz?
Marco / iw2nzm

 frequenza di 10 MHz?
Mi sa che si azzerano e ricominciano un sacco di volte... me ne ero
reso conto, ho lasciato stare perchè mi serviva per il momento capire
se effettivamente il PIC "sentiva" la variazione di f sul generatore
(numeri che cambiano).
Credo che la cosa migliore da fare sia ora restringere il tempo fra un
conteggio e l'altro, calcolare quanto tempo passa fra due fronti di
salita (periodo T) e poi trovare la frequenza f = 1/T
Al momento non so come calcolerò il periodo...
Per quanto riguarda la frequenza, non trovo sul datasheet un qualcosa
che mi indichi la f massima rilevabile dal PIC. Vedo che in modalità
HS (high speed ???) si possono usare quarzi fino a 20MHz
opportunamente accoppiati con i condensatori giusti. Ma una
correlazione con cosa posso leggere in ingresso non la trovo...
presumo mi sfugga, non che non ci sia...
Ultima cosa: mi consigli un quarzo da 20MHz piuttosto di quello da
4MHz che uso adesso ?
è una strada in salita.... :-)
Grazie per la tua cortesia
Matteo IV3YNB

 4MHz che uso adesso ?
A questa domanda dovresti poter rispondere tu ora :)
In generale per applicazioni del genere io tenderei a usare un clock di 
sistema elevato, ma se leggi la tabella che ti ho segnalato e il 
paragrafo relativo al timer1 come contatore vedi che da un certo punto 
di vista è poco influente la scelta del clock.
Ciao!
Marco / iw2nzm

> Ma non ha senso sommare TMR1L e TMR1H!
almeno questo problema, ora l'ho risolto!
shiftando il byte H di 8 nei 16bit di una variabile word e poi
sommando il byte L ottengo una word da 16bit.
Ho provato ed aumentando la f del generatore ho constatato che H=1 e
L=0 ottenevo la somma pari a 256.
Mi sembra corretto, no ?
Alla prossima
Matteo IV3YNB

 Mi sembra corretto, no ?
Yes!
Marco / iw2nzm

 A questa domanda dovresti poter rispondere tu ora :)
Ho trovato qualcosa... grazie
Comunque più passano i giorni e meglio mi trovo a leggere il
datasheet...
Infine, sono ottimista
Grazie ancora per l'aiuto
73 de Matteo IV3YNB