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)




Présentation


BASE 18F27K42 :

images/t_Base_Test_18F27K42_schema_wh5_190226.gif images/t_Base_18F26K22_vue_photo_190220.gif
schema version 18F26K22 ISIS photo circuit (sprint layout 6) version originale

 


 


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

images/t_SMT1_WINDOWED_COUNTER_MODE_SINGLE_ACQUISITION TIMING.gif

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

images/t_Anomalie_Duty_cycle_mesure_6-25MHz.gif

Generateur pour Test SMT1

images/t_Generateur_simple_25MHz_4_gammes_schema_2021-11.gif images/t_Gene_EPSON_Q_25MHz-74HCTLS93_12-5MHz_6-25_3-125Mhz.giff images/t_Generateur_simple_25MHz_4_gammes_Hardware_2021-11.gif

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 :


images/t_Base_18F27K42_Schema_2021.gif

Configuration TMR4 et SMT1

images/t_Timer8bits_Clock_REF_SMT1_18F27K42.gif
config TMR4 pour 1 sec Diagramme Interconnection internes MCU



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


images/t_SMT1_High_and_Low_Measure_Mode_Single_Acq_Timing.gif
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
images/t_YAT_Terminal_setting_20211113.gif

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





../common/GIF/LTC1286p.jpg

retour à l'index