V.O 21/02/2019
rev 25/08/2022
PIC 18F27K42
SMT1 Compteur 24 bits
SMT1 compteur (Timer)
24 bits résolution +-1cycle (2021...PLABX
XC8)
SMT1
Timer utilisé en Chronomètre (compteur 24 bits résolution ..+-16nS)
(2022 ..MikroC 7.60)
SMT1
en Frequencemetre, Mode 10 : Fenetre 1sec avec Q10MHz , TMR0 RC5<->RC1
(MikroC ...10 nov 2021)
SMT1 en
Frequencemetre, Mode 10 : Fenetre 1Sec avec TMR4 et SOSC 32768 Hz (MikroC ...20
nov 2021)
SMT1 en
Periodemetre, Mode 3, Mesures Etat Haut et Etat Bas ( MikroC ...11 nov 2021)
SMT1 en
Periodemetre, Mode 2, Mesures etat Haut et Periode (avec NCO1 + interface operateur...13/11/2021)
SMT1 compteur 24bits
Compteur pouvant utiliser directement FOSC 64MHz
!
soit une resolution proche de + - 0.015625 µS
sur une plage de durée maxi de 262mS, sans overflow.
utilisé , par exemple ,pour chronometrage de l'execution d'une
portion de code
SMT1 Init ( via MPLAB!)
Usage :
exemple test fonction delay 10mS
CPrint(" Test compteur 24 bits SMT1
sur FOSC=64MHz \r\n");
CPrint(" Resolution compteur +- 16 nanoSec (maxima= 262mS)\r\n");
ST=&SMT1_Measure; // pointeur Byte sur debut entier long 32
bits
CPrint(" Start SMT1 for test delay 10mS\r\n");
SMT1_Measure=0;
SMT1STATbits.RST=1;
SMT1CON1bits.SMT1GO=1;
__delay_ms(10);
SMT1CON1bits.SMT1GO=0;
txt=&TEXTE[0];
*(ST)=SMT1TMRL;
*(ST+1)=SMT1TMRH;
*(ST+2)=SMT1TMRU;
*(ST+3)=0;
CPrint( " Stop. SMT1 tics avec ultoa -> ");
ultoa(txt,SMT1_Measure,10);
Print(txt);
sprintf(txt," , et (via sprintf) -> %lu uS ",SMT1_Measure>>6);
Print(txt); CRLF1();
résultat :
Test compteur 24 bits SMT1 sur FOSC=64MHz
Resolution compteur +- 16 nanoSec (maxima= 262mS)
Start SMT1 for test delay 10mS
Stop. SMT1 tics avec ultoa -> 640004 , et (via sprintf) -> 10000
uS
Test Acquistion de 128 mesures ADC
12bits
Start SMT1 pour 128 mesures ADC12 bits
Stop SMT1 tics avec ultoa -> 328124 , soit (avec sprintf) ->
5126 uS
pour 1 mesure ADC12bit + stockage => 40 uS
(mesure ADC non optimisée !)
-----------------------------------------------------------------------
Test SMT1 en chronometre (
version MikroC rev 08-2022)
Mesure via le compteur 24Bits SMT1 , avec comme source FOSC=64MHz
!
Tres utile pour mesurer la durée d'exécution d'un morceau de
programme ou d'une fonction.
L'init du SMT1 :
void Init_SMT1(void)
{
CPrint(" Test SMT compteur 24 bits (résumé des registres
en page 364) \r\n");
//TABLE 25-3: SUMMARY OF REGISTERS ASSOCIATED WITH SMT1 page 405
// REGISTER 25-4: SMT1CLK: SMT CLOCK SELECTION REGISTER
// 001=FOSC 010=HINTOSC 000=FOSC/4
SMT1CLK.CSEL2= 0;
SMT1CLK.CSEL1= 0;
SMT1CLK.CSEL0= 1;
// REGISTER 25-7: SMT1TMRL: SMT TIMER REGISTER LOW BYTE
SMT1TMRL=0;
SMT1TMRH=0;
SMT1TMRU=0;
//REGISTER 25-10: SMT1CPRL: SMT CAPTURED PERIOD REGISTER
LOW BYTE
SMT1CPRL=0;
SMT1CPRH=0;
SMT1CPRU=0;
// registre SMT1CON0
SMT1CON0.WPOL=0; // Window Polarity
SMT1CON0.SPOL=0; // Signal Polarity
SMT1CON0.CPOL=0; // Clock Polarity
SMT1CON0.SMT1PS1=0; // PS<1:0>: SMT Prescale Select bits
SMT1CON0.SMT1PS0=0; // 11=1/8 10=1/4 01=1/2 00=1/1
SMT1CON0.SMT1EN =1; // SMT enabled
SMT1CON0.SMT1STP=0; // 0 =reset 1=STOP;
SMT1CON1.SMT1GO=0; // 1= suit l'entrée 0=stop suivi
SMT1CON1.SMT1REPEAT=0; // 0= Single Acquisition 1=repeat mode
// REGISTER 25-3: SMT1STAT: SMT STATUS REGISTER
//WS: SMT1WIN Value Status bit
// 1 =SMT window is open , 0= SMT window is closed
// AS: SMT_signal Value Status bit ,
// 1= SMT acquisition is in progress , 0=SMT acquisition is not
in progress
// 25.7.1 PW (Pulse Width) AND PR (Periode Read) ACQUISITIONI
NTERRUPTS
PIR1.SMT1PRAIF=0;
PIE1.SMT1PRAIE=0;
// 25.7.2 PERIOD MATCH INTERRUPT
PIR1.SMT1IF=0;
PIE1.SMT1IE=0;
// decomposition unsigned long 32 bits ..24 utiles
SMT1PRU=0xFF;
SMT1PRH=0xFF;
SMT1PRL=0xFF;
// MODE de fonctionnement
SMT1CON1.B3=0;
SMT1CON1.B2=0;
SMT1CON1.B1=0;
SMT1CON1.B0=0;
SMT1CON1.SMT1REPEAT=0;
ST=&SMT1_Measure; // pointeur Byte sur debut entier long 32
bits
SMT1_Measure=0L;
}
variables :
unsigned long SMT1_Measure;
unsigned char *ST;
Exemple d'usage :
ST=&SMT1_Measure; // pointeur Byte sur debut entier long 32
bits
CPrint(" Start SMT1 for test delay 10mS\r\n");
SMT1_Measure=0;
SMT1STAT.RST=1;
SMT1CON1.SMT1GO=1; // start
Delay_ms(10);
SMT1CON1.SMT1GO=0; // stop
txt=&TEXTE[0];
*(ST)=SMT1TMRL;
*(ST+1)=SMT1TMRH;
*(ST+2)=SMT1TMRU;
*(ST+3)=0;
CPrint( " Stop.\r\n SMT1 tics -> ");
if (SMT1_Measure>3) SMT1_Measure=SMT1_Measure-4;
LongWordToStr(SMT1_Measure,CRam1); Print(CRam1);
if (SMT1_Measure>63)
{
SMT1_Measure=SMT1_Measure>>6 ;
sprintf(txt," , et (via sprintf) -> %lu uS ",SMT1_Measure);
}
else
{
F1=(float) SMT1_Measure* 0.015625;
sprintf(txt," ,et (via sprintf) -> %3.3f uS ",F1);
}
Print(txt);
CRLF1();
Cas particulier si on est inférieur à la µS :
sachant que 64 tics correpondent à un temps écoulé de 1µS
1 tic -> 0.015625µS
si le nombre de tics est inferieur à 64, on passe en calcul
flottant ,pour l'affichage en µS
Software :
_18F27K42_Tests_SMT1_chronometre_2022_0825.zip
PIC18F27K42_test_SMT1_Chronometre_UART_IVT_2022_0825.c
18F27K42_Tests_SMT1_chronometre_2022_0825.hex
Mesure
de Frequence avec STM1 compteur
24 bits,
avec RTC DS3231
Test SMT1 en mode 10 : mode 1010
windowed counter
* Version sans quartz sur le PIC , usage de FOSC
interne 64Mhz!
mais avec le 1Hz sortie SQWE de la RTC DS3231 comme base de temps
fenetre temporelle de 1 sec --> aiguillage sur SMT1WIN=0; //00000
= SMTxWINPPS .... soit RC0
signal à mesurer ------------> aiguillage sur SMT1SIG=0; //
SMTxSIGPPS ... soit RC1
FIGURE 25-22: WINDOWED COUNTER MODE SINGLE ACQUISITION TIMING
DIAGRAM
MCU : 18F27K42
Power supply: 3.6 à 5V
Directory : C:\_MikroC\_MesProjets_MikroC\_18F27K42_Test_SMT1_24bits_counter
Projet : Base_18F27K42_Test_SMT1_Windowed_single_as_Freqmeter_2021_11.mcppi
Source : Base_18F27K42_Fosc_interne_64Mhz_UART1_SMT_Freqmeter_Test__2021-1109.c
CONFIG : P18F27K42_Fosc_interne_with_PLL_64MHz_with_Vectored_IT.cfgsch
FOSC : 64MHz
IVT Interrupt mode !
HARDWARE :
SMT1WIN = RC0 = Base de temps 1sec SMT1SIG= RC1= signal à
mesurer
Check Reglage OSCTUNE, avec Freqmeter sur RA6
Clock initiale in Khz = 64000
Initiale TMR0 at 1sec
Test SMT compteur 24 bits (résumé des registres en page 364)
Test pointeur ST : 007FFF
Test SMT1 en mode 10 : mode 1010 windowed counter
Init Interrupt UART RX
test
avec boite Generateur à Quartz (25Khz et 2,5Khz)
$* Freq= 24999, Hz
$* Freq= 25000, Hz
$* Freq= 25000, Hz
$* Freq= 2500, Hz,
$* Freq= 2500, Hz
sur
pin de sortie 32K de la RTC
$* Freq= 32711, Hz,
$* Freq= 32711, Hz,
$* Freq= 32710, Hz,
$* Freq= 32711, Hz
$* Freq= 32711, Hz,
Duty= 50.00%
10/11/2021
test ave oscillateur EPSON 2-E197G 25MHz dip8 4 pins at TAmb=19°C
1=O.E. 4=Gnd 5 = Output 8=+Vcc suivi d'un DM74LS93
Bonne precision .. testé up to 12,5MHz
Usage des interruptions vectorisées
les 2 caracteres $* montrent que les 2
interruptions suivantes sont sollicitées
Init
des pointeurs :
unsigned long SMT1_Measure ;
unsigned char *ST1;
unsigned long SMT1_Haut ;
unsigned char *ST2;
ST1=&SMT1_Measure;
ST2=&SMT1_Haut;
void
Interrupt_STM1_PRA() iv IVT_SMT1PRA ics ICS_AUTO
{
U1TXB='*' ;
PIR1.SMT1PRAIF=0; // PIR1.B7
*(ST1)= SMT1CPRL;
*(ST1+1)= SMT1CPRH;
*(ST1+2)= SMT1CPRU;
*(ST1+3)=0 ;
*(ST2)= SMT1CPWL;
*(ST2+1)= SMT1CPWH;
*(ST2+2)= SMT1CPWU;
*(ST2+3)=0 ;
SMT1CON1.SMT1GO=0; // ARRET
SMT1EN_bit=0;
}
void Interrupt_STM1_PRW() iv IVT_SMT1PRW
ics ICS_AUTO
{
U1TXB='$' ;
*(ST2)= SMT1CPWL;
*(ST2+1)= SMT1CPWH;
*(ST2+2)= SMT1CPWU;
*(ST2+3)=0 ;
SMT1PWAIF_bit=0;
}
Le résultat de la 2me Interruption SMT1PRA
est suffisant pour récupérer les 2 infos :
Frequence directe en Hz (puisque la fenetre
Window fait 1 seconde)
ERRARE
!!!
sur le duty cycle ,
avec : duree etat Haut *100 / Periode=Duree totale
Mes tests étaient faits avec ma boite generateur à quartz ,qui
sort un signal CARRé
donc duty-cycle =50% quelque soit la frequence
J'ai refait des test le lendemain avec un autre generateur ,
bricolé vite fait , pour verifier la precision
vers de plus hautes frequences ( up to 12,5MHz)
celui ci delivre un signal avec un Duty cycle variable (suivant
la frequence mesurée).
mis en evidence avec mon analyseur SQA
Generateur pour Test SMT1
![]() |
![]() |
![]() |
Generateur Simple 25MHz -> 12.5,6.25,3.125 Mhz |
brouillon |
montage proto :generateur + Quartz pour SCOS |
En fait, dans le mode Windowed Counter, lLe Duty Cycle
mesuré est celui du signal Window ! et non pas du
signal
dont on mesure la frequence ! Freq= nb de pulse dans une fenetre
de 1 seconde.
le signal widows etant la sortie 1Hz de la RTC, celui ci est
CARRé => donc duty cycle =50% tout le temps !
conclusion :
pas de mesure Duty Cycle signal avec ce mode ...
pour avoir le vrai Duty cycle du signal ,il faut utiliser le mode
2 ou 3
FIGURE 25-9: HIGH AND LOW MEASURE MODE SINGLE ACQUISITION TIMING
DIAGRAM
on a alors le nb de pulses à l'etat Haut et le Nb de pulses à l'etat
bas pour en deduire le Duty Cycle .
MAIS il faut que le PIC soit utilisé avec un FOSC avec
QUARTZ !
Les pointeurs (bytes) ST1 et ST2 pointent sur les resultats 24
bits ( logés dans un unsigned entier long)
*on pourrait aussi utiliser des pointeurs avec adresse absolue ..
La précision est celle du 1Hz de la RTC DS3231...
Rappel :
attention au Bug MikroC si usage EEPROM PIC
'avantage d'un PIC avec PPS !
Modif Pin entree signal SMT1, RB1 ou RC1 par defaut
compilation conditionelle via :
//#define SMT1_Input_RB1
config Hardware :
PORTC=0;
TRISC = 0b10110011;
ANSELC=0 ;
Unlock_IOLOCK();
RC6PPS = 0x13; //RC6->UART1:TX1;
U1RXPPS = 0x17; //RC7->UART1:RX1;
U1CTSPPS=0x15; // RC5
//TABLE 17-1: PPS INPUT REGISTER DETAILS
SMT1WINPPS=0x10; // RC0 PORTC =0x010 Pin 0= 0x000
// SMT1SIGPPS=0x11; //RC1 PORTC =0x010 Pin 1= 0x001
#ifdef SMT1_Input_RB1
// modif input signal (qui est RC1 par default)
RC1PPS=0;
SMT1SIGPPS= 0x09; // RB1 17.8 PPS Input Selection PortB= 001 Pin
1= 001
#else
SMT1SIGPPS=0x11; //RC1 PORTC =0x010 Pin 1= 0x001
#endif
Lock_IOLOCK();
SOFTWARE MikroC 7.60 :
revision 10/11/2021 du soft pour
enlever la mesure Duty Cycle n'ayant aucun rapport avec le signal
à mesurer
Base_18F27K42_Test_SMT1_Windowed_single_as_Freqmeter_2021_11.mcppi
Base_18F27K42_Test_SMT1_Windowed_single_as_Freqmeter_2021_1110.hex
Base_18F27K42_Fosc_interne_64Mhz_UART1_SMT_Freqmeter_Test_2021_1110.c
Base_18F27K42_Test_SMT1_Windowed_single_as_Freqmeter_2021_11.cfg
Version avec Timer0
16bits comme base de temps
1Hz
En fait , le Timer0 16 bits est calé sur 500mS et le debordement
timer ressort en interne MCU,,via une bascule JK, sur une Pin PPS
Necesite la mobilisation de 2 Pins MCU et une liaison externe
entre ces 2pins
Sortie TmR0 --> RC5 x-------------------x RC0 SMT1 Windows
input.
Abandonné avec usage d'un
Quartz 10MHz
car IL FAUT UN QUARTZ ayant une valeur modulo 2 (BINAIRE)
3,2768MHz ou 8,192MHz ou 16,384 MHz, pour pouvoir obtenir un
timming tres precis de 1000 000µS sur la sortie
TMR0 ..
le PIC ne peut plus suivre au delà de 20MHz ... en OScillateur
Interne
...par contre , pourrait recevoir un Oscillateur externe 32,768MHz
sur l' Entree Oscillateur Externe du PIC
.. mais non testé à ce jour..
Sinon le principe est bon ..
Base_18F27K42_Fosc_Q10MHzx4_UART1_SMT1_Mode10_Freqmeter_Timer0_RC5_2021_1116.c
Version avec Timer4
8bits comme base de temps 1Hz
Pourquoi avec un timer 8 bits et non 16 bits ?
.Les Timers 2/4/6 ont la possibilité de SORTIR
l'info débordement ! en interne
MCU ,
ce qui n'est PAS le cas avec Timers 16 bits !
Cette info, TMRx postscaled Output, est aiguillée DIRECTEMENT sur l'entrée SMT1 Window
,
économisant l'usage de 2 pins : RC5 reliée à
RC0 ,avec la version Timer0 !
rappel : Sortie Timer0 1Hz sur Pin RC5 ----> vers pin RC0
Windows SMT1
Problematique :
un timer 8 bits , avec FOSC/4=10MHz , ne peut delivrer qu'une
periode maxi de :
Avec Q=10MHz * PLL => cycle=0.1µS
... PR4 maxi=255 ....Prescaler : 128 .....Postscaler 16 => 0.1*255*128*16
=> 52 224 µS = 52.22mS
on peut choisir une autre source pour T4CLK
mais malheureusement pas MFINTOSC ( 500KHz
), car il est issu de l'oscillateur LOCAL , et donc pas
assez precis !
meme si ajustable à +-3 % avec OSCTUNE
par contre ,on peut utiliser le module CLOCK REFERENCE
CPrint(" CLKR init \r\n ");
// REGISTER 8-2: CLKRCLK: CLOCK REFERENCE CLOCK SELECTION MUX
CLKRCLK=0; // FOSC Q=10MHzxPLL= 40Mhz
// REGISTER 8-1: CLKRCON: REFERENCE CLOCK CONTROL REGISTER
CLKRCON=0b10010111; // div by 128
40MHz : 128 => Periode =1/F => cycle = 128/40= 3,2µS
(au lieu de 0,1µS)
On arrive à PRESQUE
1 seconde !!!! avec PR4=152
3.2 * 128*16*152=996147.2µS ==> erreur -0,38%
Ce n'est pas raisonable ...
* Contre mesure 1 :
Utiliser un quart de 3,2768MHz pour cadencer le
MCU
avec parametrage TMR4 :
FOSC 3.2768MHz
choix du diviseur CLKRCON.CLKRDIV=3 // selection FOSC/8
T4CLKCON = 0x08; // choix sur CLKREF_Out
Periode signal entree TMR4 :
Tick= 1000 000 / ( 3.2768 *8) => 2441406.25 µS
T4PR =160
Prescaler =7 soit 1/128
Postscaler= 15 soit 1/16
qui donnera :
2441406.25 µS * 160 * 128 *16 => 1000 000µS
pile poil
------------------------------------------------------------
je n'ai qu'un Quartz de 32,768MHz dans mes tiroirs !
avec CLKR diviseur =64
T4PR=250, Prescaler=128 , Postscaler=16 => 1000 000 µS !
Tentative vouée à l'Echec ..
ce qui est curieux, c'est que le PIC fonctionne quand meme ..
(Frequence mesurée sur pin RC6 (quartz) à ~22MHz
et que l'UART prevu à 19200 bds ... affichage OK sur un terminal
à 38400 bauds .
pas coherent du tout avec le 32,768 MHz renseigné dans le Projet
MicroC
voir réponse sur forum
microchip :
specification parameter OS9 (page 750 in datasheet rev G)
L'oscillateur EXTERNE du PIC , ne
peut pas suivre.
alors que le PIC peut bien utiliser un
FOSC INTERNE de 64MHz .. ramené ensuite à 16MHZ
!
pour le cycle MCU à FOSC/4.. le 64MHz ne peut profiter qu'aux
péripheriques ..
-----------------------------------------------------------
* Contre mesure 2 :
usage de ce quartz (32,768MHz) , avec un module oscillateur
EXTERNE au PIC , car
avec ECH Clock
OS5 FECH Clock Frequency
64 MHz
OS6 TECH_DC Clock Duty Cycle 40 60 %
parametrage TMR4 :
FOSC=32,768MHz
CLKR divider =7 => 1/128
choic clock Timer4 : T4CLK=8
init Prescaled counter Timer4 : T4PR = 250 = 0xFA
Diviseur Prescaler 6 => 1/64
disviseur Postscaler 15 => 1/16
diviseur global 1024
Periode Time 1 000 000 µS
Cette solution n'est pas
avantageuse , si il faut un bloc oscillateur externe,
autant prendre la Solution avec RTC DS3231 , 1Hz direct sur
entree SMT1 WIN
---------------------------------------------------------------------
* Choix Final :
Utiliser l'Oscillateur Secondaire SOSC
avec un quartz Horloger 3,2768 KHz
Inconvenients :
* mobilisera les pins RC0 et RC1
* et l'entree PPS SMT1 Signal devra etre redirigée sur une autre
PIN MCU , ici RC2
* Montage PIC avec 2 quartz ! ou 1 seul si on laisse FOSC interne
MCU
Schéma :
Configuration TMR4 et SMT1
Au final, montage d'un quartz 32768 Hz sur les pins SOSC RCO et
RC1 du PIC, quartz encadré de 2x 22pF.
Choix SOSC comme source de signal d'entrée pour le Timer4, pour
construire le signal 1Hz ( 1000 000µS)
à l'entrée du TMR4 on a : 1/F= 1/32768 => Tick d'entrée= 30,51µS
soit la chaine de comptage :
Ticks * PR * Prescaler * Postscaler = 30.51*128
* 16 * 16 => 1000 000 µS en sortie de
Postcaler
Rappel : ATTENTION , c'est PR+1 qui
est pris en compte dans la chaine de comptage !
Le signal TMR4_Poscaled output est redirigé sur l'entree SMT1
Windows via le selecteur SMT1 WSEL .
L'entree SMT1 SIG est redirigée sur la Pin RC2 ( au lieu de RC1)
via l'usage des fonctions PPS.
( car l'entree RC1 est maintenant utilisée par l'oscillateur
SOSC)
Le compteur 24 bits SMT1 est utilisé en Mode 10 : Windowed
counter single acquisition
voir timing in
fig 25-22 of datasheet
Le comptage est actif, entre le 1er front montant et le 2em front
montant du signal d'entree Window
donc sur une duree de 1 seconde.
Ce 2em front montant déclenche une interruption via le flag SMT1PRAIF
mis à 1
dans le traitement de l'interruption, il suffit de recupere le
contenu du registre 24 bits SMT1CPR
Nota: on utilise un "unsigned long 32 bits" (poids fort
toujours à 0) pour contenir les 3 bytes L,H,U constituant ce
registre
On obtient ainsi directement la mesure de Frequence en HZ
Verification :
3.125 MHz
(2:52.450) Waiting Measure : * Freq= 3125077
(2:54.456) Waiting Measure : * Freq= 3125077
(2:56.458) Waiting Measure : * Freq= 3125077
(2:58.463) Waiting Measure : * Freq= 3125077
delta= 77/3125000 soit + 0.0024%
12.5MHz
(0:13.703) Waiting Measure : * Freq= 12500299
(0:15.702) Waiting Measure : * Freq= 12500300
(0:17.705) Waiting Measure : * Freq= 12500300
(0:19.712) Waiting Measure : * Freq= 12500300
delta= 300/12500000 +0.0024%
boite à quartz 25KHz
(0:19.850) Waiting Measure : * Freq= 25003
(0:21.851) Waiting Measure : * Freq= 25004
(0:23.855) Waiting Measure : * Freq= 25005
(0:25.858) Waiting Measure : * Freq= 25005
delta max= 5/25000 +0.02%
Boite à quartz 2500Hz
(0:41.889) Waiting Measure : * Freq= 2500
(0:43.898) Waiting Measure : * Freq= 2500
(0:45.903) Waiting Measure : * Freq= 2500
delta 0%
Boite à quartz 48.82Hz
(2:22.087) Waiting Measure : * Freq= 49
(2:24.091) Waiting Measure : * Freq= 49
(2:26.092) Waiting Measure : * Freq= 48
(2:28.094) Waiting Measure : * Freq= 49
rounded value
Il y a une erreur de mesure , mais impossible de savoir si l'erreur
est due à :
* Quartz Horloger 32.768KHz for SOSC
* Quarz EPSON 25MHz (sur Generateur + 74LS93 binary divider)
* QUART 400KHz de ma boite à quartz
* erreur de programmation ?
Nota : la version avec 1 Hz RTC donne une erreur quasi nulle !
j'en conclue que ce serai plutot mon quartz horloger qui est en
cause ..ou le programme
Le maxi frequence mesurable est limité à 16
000 001 Hz .. avec une fenetre de 1sec
via le registre SMT1PR initialisé justement avec la valeur
16000001 .
Une interrupton SMTR1 est générée en cas de debordement
compteur , affichage du message "Overlimit
"
tant qu'on est en debordement , donc avec Freq input > 16MHz
Il est possible d'étendre la gamme de mesure à 32MHz,
simplement en modifiant le Prescaler ou Postscaler
et en Multipliant par 2 , la mesure issue du registre SMT1PCR
Amélioration possibles :
* Rajout LCD , ou BlueTooth pour lecture sur Appli Smartphone
* changement de gamme automatique entre au dessus de 16MHz
* changement de mode SMT1 via une entree PIC : Mode
Frequencemetre ou Periodemetre
* rajout diviseur circuit MB256 pour les frequences TRES HAUTES
.. up to 16x256=4096 MHz ( 4GHz theorique)
*Rajout d'un ampli large bande pour mesure signaux sinus , faible
amplitude
.. ex ampli large bande 20MHz 20 db pour input 0,1Veff (voir
frequencemetre 16F84!!)
SOFTWARE
L'init du Timer4 8 bits
void
TMR4_Init(void) //
{
T4CLKCON =7 ; // 0111 SOSC
Secondary Oscillator Q=32,768 KHz soit Tick =30.517578125
//TxHLT: TIMERx HARDWARE LIMIT CONTROL REGISTER
// PSYNC CKPOL CKSYNC MODE[4:0]
T4HLT = 0x00; // Mode 0= free running
T4CKPS1_bit=1; // 1 = ON register bit is synchronized to FOSC/4
T4RST = 0x00; //
T4PR = 127; // value PR+1 =128
T4TMR = 0x00; // TMRx= 0;
T4CON = 0x4F ; // Prescaler =1/16
Poscaler=1/16
TMR4IF_bit = 0; // Clearing IF flag.
TMR4IP_bit=1;
TMR4ON_bit=0 ;
TMR4IE_bit=0 ;
Count4=0; // non utilise ici
}
Nota : L'interrupt TMR4 n'est pas utilisée
L'interrupt de capture de la mesure
encadrée par signal Window de 1 sec
signalée par la montée du Flag SMT1 PRAIF ( apres le 2em fornt
montant du signal SMT1 Window
void
Interrupt_STM1_PRA() iv IVT_SMT1PRA ics ICS_AUTO
{
OSCEN.B3=0; // arret de l'Oscillator OSC
PIR1.SMT1PRAIF=0; // RAZ flag
//Lecture
des 3 registres 8 bits composant un registre de 24 bits (stocké
dans un long 32 bits)
*(ST1)= SMT1CPRL;
*(ST1+1)= SMT1CPRH;
*(ST1+2)= SMT1CPRU;
*(ST1+3)=0 ;
U1TXB='*' ;// Traçage sur terminal YAT
Drapeaux.SMT1_Dispo=1; // Flag
signalant la mise à disposition de la mesure
SMT1CON1.SMT1GO=0; // ARRET du compteur
SMT1EN_bit=0;// invalidation compteur
SMT1PRAIE_bit=0; // Stop other interrupt
}
Gestion du Debordement via Interrupt SMT1
void
Interrupt_SMT1PR() iv IVT_SMT1 ics ICS_AUTO
{
U1TXB='&' ; // Traçage sur terminal YAT
Drapeaux.SMT1_Over=1; //Flag pour signaler le debordement
SMT1IF_bit=0;
SMT1IE_bit=0; // pas d'autre interrupt autorisées
}
Remarque : si on est en débordement SMT1 , on a plus l'interrupt
fin de fenetre Windows
j'ai donc inhibé l'interrupt apres son apparition et mis une
tempo de 1 sec dans le main , pour
éviter une repetition infinie de l'interrupt ...
seule une mesure inferieure au seuil Maxi 16 000 001 Hz peut
remettre tout en ordre.
init du seuil maxi : SMT1PR
CPrint("
Init SMT1PR Registre pour maxi 16MHz : ");
// 16 000 001 => F42400
SMT1PRL=0x01;
SMT1PRH=0x24;
SMT1PRU=0xF4;
La boucle principale pour afficher la mesure sur terminal
YAT
..etc ..
do
{
TMR4ON_bit=0;
TMR4IF_bit=0;
TMR4IE_bit=0; // pas d'interrupt Timer4 !!
Drapeaux.SMT1_Dispo=0;
Drapeaux.SMT1_Over=0;
Drapeaux.Tmr4_Elapsed=0;
OSCEN.B3=1;
Raz_Buffer1();
CPrint(" Waiting measure.. "); // waiting Next rising
edge of Windows Signal
SMT1_Measure=0;
T4PR= 127;
T4TMR = 0x00;
SMT1IE_bit=1;
SMT1EN_bit=1;
SMT1CON1.SMT1GO=1; // MARCHE
SMT1PRAIE_bit=1;
LED_Rouge=ON;
TMR4ON_bit=1; // start for 1sec
TMR4 SANS INTERRUPT
SQA=1;
//
Attente Interrupt .. necessite 1 sec !
while (Drapeaux.SMT1_Dispo==0) ;
if(Drapeaux.SMT1_Dispo==1)
{
if( Drapeaux.SMT1_Over==1)
{
CPrint(" Overfow SMT1 ");
Delay_ms(1000);
}
else
{
LongWordToStr(SMT1_Measure,CRam1);
CPrint(" Freq= ");Print(CRam1);
}
}
LED_Rouge=OFF;
SQA=0;
.. etc ..
} while(1);
Projet MikroC 7.60
rev 21/11/2021
Base_18F27K42_Freqmeter_SMT1_Mode10_TMR4_as_SMT1Window_SOSC_32-768Khz_FOSC64MHz_2021_11.mcppi
Base_18F27K42_Freqmeter_FOSC64MHz_SOSC_32_768Khz_UART1_Timer4_as_SMT1Window_2021_1120.c
Base_18F27K42_Freqmeter_SMT1_Mode10_TMR4_as_SMT1Window_SOSC_32-768Khz_FOSC64MHz_2021_1121.hex
Base_18F27K42_Test_SMT1_Mode_2_PeriodMeter_Duty_Freq_plus_NCO1_2021_11.cfg
Ressources MCU utilisées:
1144 Used RAM (bytes): 329 (4%) Free RAM (bytes):
7841 (96%)
0 1144 Used ROM (bytes): 7491 (6%) Free ROM (bytes):
123581 (94%)
SMT1 en
Periodemetre,
Mode 3 Mesure Période
Etat Haut et période Etat Bas (MikroC
...11/11/2021)
Necessite un QUARTZ pour avoir un
FOSC le plus table possible
VERSION avec mesure DUTY cycle avec PIC18F27K42 FOSC = Q10MHz x
PLL => 40MHZ
Le Mode 2 est similaire , mais effectue la mesure Etat Haut ,
puis Période complete
D'où un Duty Cycle = Haut / Periode
alors qu'en Mode 3 :
Duty Cycle = Haut / ( Haut + Bas)
L'avantage du mode 3 , est d'avoir une dynamique de comptage de 2
fois 24 bits
Ici FOSC entre directement dans le compteur TMR SMT1
d'où un ticks de 25nS ( 1/40MHz )
L'interrupt SMT1CPR est suffisante pour
récupérer les 2 valeurs Haut et Bas du signal mesué.
La periode est alors T= (Haut + Bas)
en ticks
On en déduit la Frequence = 1 /(T * Ticks)
et le taux Duty cycle = Haut *100 / T
Mode 3 = Hig and Low Measurement TMR reset à chaque front
montant
donc Periode maxima =2x24 bits
voir note DS90003129A TB3129 Signal Measurement Timer on PIC MCUs
-page 3 et 4 ,
11 modes d'utilisation pour ce compteur SMT1
l'interrupt pour capter les 2
registres 32 bits durée Haut et durée Bas
void Interrupt_STM1_PRA() iv IVT_SMT1PRA ics ICS_AUTO
{
U1TXB='*' ; // traçeur d'interrupt
PIR1.SMT1PRAIF=0; // PIR1.B7
*(ST1R)= SMT1CPRL;
*(ST1R+1)= SMT1CPRH;
*(ST1R+2)= SMT1CPRU;
*(ST1R+3)=0 ;
*(ST1W)= SMT1CPWL;
*(ST1W+1)= SMT1CPWH;
*(ST1W+2)= SMT1CPWU;
*(ST1W+3)=0 ;
SMT1CON1.SMT1GO=0; // ARRET
SMT1EN_bit=0; // disable
}
L'affectation des pointeurs
unsigned long SMT1_Haut ;
unsigned char *ST1W ;
// en mode 2
//unsigned long SMT1_Periode;
// en mode 3
unsigned long SMT1_Bas;
unsigned char *ST1R;
L'init du SMT1 :
//TABLE 25-3: SUMMARY OF REGISTERS ASSOCIATED WITH SMT1 page 405
SMT1CLK=1; // FOSC 40Mhz =>
25nS
// REGISTER 25-6: SMT1SIG: SMT1 SIGNAL INPUT SELECT REGISTER
SMT1SIG=0; // SMTxSIGPPS
//REGISTER 25-1: SMT1CON0: SMT CONTROL REGISTER 0 page 395
SMT1CON0=0;
// REGISTER 25-2: SMT1CON1: SMT CONTROL REGISTER 1
SMT1CON1=0;
SMT1CON1=SMT1CON1 | 3 ;// mode 3= Haut et Bas
ST1W=&SMT1_Haut; // pointeur Byte sur debut entier long 32
bits
SMT1_Haut=0;
ST1R=&SMT1_Bas;
SMT1_Bas=0;
LE CORPS (principal) DU PROGRAMME
SMT1EN_bit=1; //validation SMT1
SMT1CON1.SMT1GO=1;//
Activation mesure
LED_Rouge=OFF;
Delay_ms(1000);
if( (Flag_SMT1_OVER==0)&& (SMT1_Bas>0) ) // on a une mesure et pas de
depassement compteur
{
LongWordToStr(SMT1_Haut,CRam1);// on recupere la valeur 32 bits etat
Haut
CPrint(" Haut = ");Print(CRam1); UART1_Write(',');
LongWordToStr(SMT1_Bas,CRam1); on recupere la valeur 32 bits etat Bas
CPrint(" Bas = ");Print(CRam1); CPrint(" soit
");
TT= SMT1_Bas + SMT1_Haut; // nombre de tcick cummulés pendant les 2 etats
Periode =(float)TT*25; // 40Mhz => tick=25nS // durée de la periode en nS
LongWordToStr(Periode,CRam1);
Print(CRam1); CPrint(" nS ,");
CPrint(" Freq=" );
Frequence=1000000000 / Periode;// Frequence= 1 /T => on divise des
nS par des nS
Float2Ascii (Frequence,CRam1,1); Print(CRam1); CPrint(" Hz");
CPrint(" , Duty= ");
Duty= ((float) SMT1_Haut*100.0)/TT;
Float2Ascii (Duty,CRam1,2);
Print(CRam1); UART1_Write('%');
} else
{
CPrint(" Over or not ready.");
}
CRLF1();
Resultat sur terminal YAT
avec Géné TTL boite à Quartz .. 25000 Hz...4,883Hz en 2 games
de 10 steps
MCU : 18F27K42
Power supply: 3.6 à 5V
Directory : C:\_MikroC\_MesProjets_MikroC\_18F27K42_Test_SMT1_24bits_counter
Projet : Base_18F27K42_Test_SMT1_High_Low_Periode_Freq_Meter_2021_11.mcppi
Source : Base_18F27K42_Test_SMT1_High_Low_Periode_Freq_Meter_Q10Mhzx4__2021-1109.c
CONFIG : P18F27K42_Fosc_Q10MhzxPLL_40MHz_with_Vectored_IT.cfgsch
FOSC : Q10MHz x 4 =40Mhz
IVT Interrupt mode !
HARDWARE :
SMT1SIG= RC1= signal à mesurer
Clock initiale in Khz = 40000
Test SMT compteur 24 bits (résumé des registres en page 364)
Test SMT1 en mode 3 :
Mode 3 = Hig and Low Measurement TMR reset à chaque front
montant
Init Interrupt UART RX
* Haut = 51206, Bas = 51202 soit 2560200 nS , Freq=390.6 Hz ,
Duty= 50.00%
* Haut = 51206, Bas = 51203 soit 2560225 nS , Freq=390.6 Hz ,
Duty= 50.00%
* Haut = 51206, Bas = 51203 soit 2560225 nS , Freq=390.6 Hz ,
Duty= 50.00%
* Haut = 51206, Bas = 51203 soit 2560225 nS , Freq=390.6 Hz ,
Duty= 50.00%
* Haut = 802, Bas = 798 soit 40000 nS , Freq=25000.0 Hz , Duty=
50.13%
* Haut = 801, Bas = 799 soit 40000 nS , Freq=25000.0 Hz , Duty=
50.06%
* Haut = 802, Bas = 798 soit 40000 nS , Freq=25000.0 Hz , Duty=
50.13%
* Haut = 32004, Bas = 32001 soit 1600125 nS , Freq=625.0 Hz ,
Duty= 50.00%
* Haut = 32004, Bas = 32001 soit 1600125 nS , Freq=625.0 Hz ,
Duty= 50.00%
* Haut = 32004, Bas = 32002 soit 1600150 nS , Freq=624.9 Hz ,
Duty= 50.00%
* Haut = 32004, Bas = 32001 soit 1600125 nS , Freq=625.0 Hz ,
Duty= 50.00%
* Haut = 32004, Bas = 32001 soit 1600125 nS , Freq=625.0 Hz ,
Duty= 50.00%
* Haut = 128012, Bas = 128009 soit 6400525 nS , Freq=156.2 Hz ,
Duty= 50.00%
* Haut = 128012, Bas = 128009 soit 6400525 nS , Freq=156.2 Hz ,
Duty= 50.00%
* Haut = 128012, Bas = 128010 soit 6400550 nS , Freq=156.2 Hz ,
Duty= 50.00%
* Haut = 128012, Bas = 128009 soit 6400525 nS , Freq=156.2 Hz ,
Duty= 50.00%
* Haut = 256023, Bas = 256020 soit 12801075 nS , Freq=78.1 Hz ,
Duty= 50.00%
* Haut = 256023, Bas = 256020 soit 12801075 nS , Freq=78.1 Hz ,
Duty= 50.00%
* Haut = 256023, Bas = 256020 soit 12801075 nS , Freq=78.1 Hz ,
Duty= 50.00%
* Haut = 256023, Bas = 256020 soit 12801075 nS , Freq=78.1 Hz ,
Duty= 50.00%
* Haut = 2048173, Bas = 2048170 soit 102408568 nS , Freq=9.8 Hz ,
Duty= 50.00%
* Haut = 2048173, Bas = 2048171 soit 102408600 nS , Freq=9.8 Hz ,
Duty= 50.00%
* Haut = 2048173, Bas = 2048170 soit 102408568 nS , Freq=9.8 Hz ,
Duty= 50.00%
* Haut = 2048173, Bas = 2048170 soit 102408568 nS , Freq=9.8 Hz ,
Duty= 50.00%
* Haut = 4096345, Bas = 4096341 soit 204817136 nS , Freq=4.9 Hz ,
Duty= 50.00%
* Haut = 4096345, Bas = 4096341 soit 204817136 nS , Freq=4.9 Hz ,
Duty= 50.00%
* Haut = 4096345, Bas = 4096341 soit 204817136 nS , Freq=4.9 Hz ,
Duty= 50.00%
test avec generateur
EPSON25MHz sortie Q3 = 1,5625 MHz
* ne convient
plus au delà de quelques centaines de KHz , pas assez de
resolution !!
par contre
tres precis en basse frequence ..
* Haut = 11, Bas = 15 soit 650 nS , Freq=1538461.2 Hz , Duty= 42.31%
* Haut = 11, Bas = 15 soit 650 nS , Freq=1538461.2 Hz , Duty= 42.31%
* Haut = 12, Bas = 14 soit 650 nS , Freq=1538461.2 Hz , Duty= 46.15%
* Haut = 11, Bas = 14 soit 625 nS , Freq=1599999.9 Hz , Duty= 44.00%
* Haut = 12, Bas = 14 soit 650 nS , Freq=1538461.2 Hz , Duty= 46.15%
Software MikroC :
Mode 3:
Base_18F27K42_Test_SMT1_High_Low_Periode_Freq_Meter_2021_11.mcppi
Base_18F27K42_Test_SMT1_High_Low_Periode_Freq_Meter_2021_1111.hex
Base_18F27K42_Test_SMT1_Period_Duty_Freq_Meter_Q10Mhzx4_2021-1111.c
PERIODE METER
en Mode 2 :
Etat Haut et Periode complete
pour test divers via terminal YAT interface Operateur
Terminal_Freqmeter_et_NCO_cdes.yat
Software :
Sortie NCO1 RC2 reliée à l'entrée du
Periometre RC1 pour test avec terminal YAT (avec predefined
commands)
Base_18F27K42_Test_SMT1_Mode_2_PeriodMeter__Duty_Freq_with_NCO1_Q10Mhzx4_2021_1113.c
Base_18F27K42_Test_SMT1_Mode_2_PeriodMeter_Duty_Freq_plus_NCO1_2021_11.mcppi
Base_18F27K42_Test_SMT1_Mode_2_PeriodMeter_Duty_Freq_plus_NCO1_2021_1113.hex
P18F27K42_Fosc_Q10MhzxPLL_40MHz_with_Vectored_IT.cfgsch
retour à l'index