V.O 21/02/2019
rev 20/05/2024
Tests sur PIC 18F27K42
Présentation
du PIC 18F27K42 et Hardware utilisé
Montage de test, et schéma
Circuit
imprimé Base 18F27K42
avec MikroC
Test
simple de RTC DS3231 en I2C1 HW (MC)
Test
simple Ecriture I2C1 Hardw. sur PCF8574 (2020)
Test
LCD2119 2x16 cars en I2C natif
(2019)
Test LCD 4x20 chars (with PCF8574) I2C1 Software ( MikroC 08/2020)
Test LCD 4x20 chars (with PCF8574) + RTC DS3231
I2C1 Hardware ( MikroC 14/02/2021)
Test OLED SSD1306 128x32 I2C1
Hardware SANS
LIB MikroC +
RTC DS3231 (MikroC
06/03/2021)
Test
Ruban 1M 60 Leds RGB WS2812E (RGB)(20/09/2021)
Tests
3 types de RGB leds dont WS2812B (individuelles) et Ruban 60 leds/M
WS2815 (GRB)(20/04/2024
Test sur FOSC et
ClockOut sur RA6 (12/2020.)
Test NCO1 :
Numerically Controlled Oscillator (MC) en mode
Frequence (rev
2021)
Test NCO1 (MPlabX IDE 5.30 + XC8) en mode
Frequence
Test NCO1 en
mode Pulse (....a suivre ...)
MUSIC
avec NCO1 (MC) (06/12/2020.)
MUSIC avec NCO1 et
fichier simili RTTL (MC) (rev 21/02/2022.)
.... En mieux, sans NCO 100%ASM (07/12/2020.)
Afficheurs LCD
TEST LCD ILI9341 320x200 65k couleurs en mode
SPI (MC)
Test OLED SSD1306 avec I2C1
Hardware (
MPLABX XC8)
Les TIMERS du 18F27K42 :
Timer0 16 bits ,
SANS Postscler, 1 seconde en mode pooling (MikroC) 17/05/2021
Timer0
16 bits , avec Postscaler , 500mS en mode Interrupt (MPLABX XC8) 26/07/2023
Pulse Width Modulation
PWMx sur 10 bits
PWM avec
module PWM5 10bits 1Khz et Timer2 (MikroC 2022-08)
PMW
avec CCP1 en mode PWM1 10bits 1Khz et Timer4 (MikroC 2021 2022-08)
PWM
avec CCP1 en mode PWM1 10bits Fxxxx Hz et Timer2 (SANS LIB MikroC
!) (MikroC
2021 2022-08)
Liens sur PWM sur 8 bits
Liens sur SMT1
Compteur 24 bits
SMT1 compteur (Timer) 24 bits résolution
+-1cycle (MPLABX XC8)
SMT1 en Frequencemetre, Mode 10 : Fenetre 1sec avec Q10MHz , TMR0
RC5<->RC1 (MikroC ...10
nov 2021)
SMT1 en Frequencemetre, Mode 10 : Fenetre 1Sec avec TMR5
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)
Test
DAC 5 bits ... générateur BF DDS ( sinus 1 à 65535 Hz)
Test
PWM Timer2 + CCP1 , pour géneration signal SINUSOIDAL
Test
interruptions IOC ( sur changement d'etat entrées) 18F27K42
MPLAB XC8
Présentation
Materiel :
datasheet 18F27K42
Tests PIC 18F27K42
Ce nouveau PIC presente de grosses
différences par rapport au 18F26K22
sur la gestion I2C
Hardware, (par contre, Au niveau SOFT I2C .. c'est idem
la meme chose)
* MikroeE Harmonisant les librairies I2C Hardware avec les autres
familles de MCU ATMEL,ARM ,FT9.. ce n'est plus aussi facile !
et dans certains cas il faudra plutot utiliser I2C Software , si
des considérations de timing sont imposées entre chaque lecture
ou ecriture.
voir ceci . Avec
MPLAB XC8 c'est aussi une vrai usine à gaz!
Une RTC et un LCD
seront utilisés ...
RTC DS3231
avec une liaison UART1 :-
-> cordon Prolix PL2303 (Noir=Gnd Vert=Rx=RC7 Blanc=Tx=RC6 )
assurant la convertion TTL/USB
Montage
de test :
BASE PIC18F27K42
Utilisation de FOSC interne 64Mhz, via
config Bits
Liaison I2C1 sur RC3 et RC4, avec R pull up de 2,8K avec RTC DS3231
Liaison UART sur RC6 (Tx) et RC7(Rx) avec Teraterm PC application
via cordon TTL/USB
Liaison ICSP avec Pickit 4 et MPLAB IPE V5.00 application PC
une entree dédiée au Forcage de la date et Heure
schema:
schema avec diptrace: Base_18F27K42_rev_190226.wh5
Montage
Developpement avec MikroC 7. version 7.30 beta ...
donc avec quelques bugs
possibles
circuit réel (réalisé par JLCPCB)
V.O. Design circuit imprimé: _Base_18F26K22_rev190218_11H00.zip
Commandés le 19/02/2019 .. reçus le 25/02/2109
![]() |
![]() |
coté cuivre | coté composants |
* avec quelques
petits défauts de conception au niveau de l'alignement au pas de
1,27mm
RTC DS3231
:
La commande Ecriture
issu de la doc MikroE
:
// for PIC18F K42 and K83 family
unsigned short I2Cx_Wr(char slave_address, char
*ptrdata, unsigned short count, unsigned short END_mode);
slave_address: slave address.
ptrdata: pointer to the received data.
count: number of bytes to be received.
END_mode: mode in which the I²C module will be set after the
reading.
Available modes : Value Description
_I2C_END_MODE_RESTART I²C bus will issue a restart.
_I2C_END_MODE_STOP I²C bus will issue a stop.
La RTC (Neuve) doit etre initialisée .
Une premiere commande permet de démarrer l'horloge RTC et d'obtenir
le cligotement , à 1HZ,
sur la sortie SQWE de la RTC
soit tmp[10] une table qui sera utilisée pour les transfert
datas I2C
* dans l'élément tmp[0] , on doit mettre la 1ere adresse (registre)
pointé dans le device connecté, ici 0x0E
* dans l'élement tmp[1], la valeur de la donnéee à écrire,
ici 0x40 (ou 0B0100000)
et donc dans l'instruction on retrouve :
L'adresse du device sur 7 bits ( adresse sur 8
bits en mode SOFTWARE I2C)
#define DS3231_ADDR 0x68 // 0xD0 en I2C software !
le pointeur sur la table --> tmp
le nombre de bytes conecernés -> 2
le mode de retour (Ack ou Nack) -> mode STOP
tmp[0]=0x0E;
tmp[1]=0b01000000;
I2C1_Wr( DS3231_ADDR, tmp, 2, _I2C_END_MODE_STOP );
Pour Initialiser completement la RTC avec des
valeurs plausibles,
on va pré-remplir les registres avec une date et heure donnée.
soit la meme table tmp[10] utilisée pour les transfert datas I2C
dans l'élément tmp[0] , on doit ECRIRE, mettre la 1ere adresse
(registre) pointé dans le device connecté
ici 0x00, adresse registre secondes
puis ecrire les datas dans les elements suivants
tmp[1]=valeur Sec
tmp[2]=valeur Mn
.. etc .
I2C1_Wr( DS3231_ADDR, tmp, 7, _I2C_END_MODE_STOP
);
exemple: ex: 20 fevrier 2019 , mardi, 14:59:50
tmp[0]=0;
tmp[1]=0x50; //Reset second to 0 sec. and stop Oscillator
tmp[2]=0x59; //write min
tmp[3]=0x14; //write hour;
tmp[4]=0x02; ///write day of week
tmp[5]=0x20; // write date
tmp[6]=0x02; // write month
tmp[7]=0x19; // write year 2019
I2C1_Wr( DS3231_ADDR, tmp, 7, _I2C_END_MODE_STOP );
Une fois initialisée, la RTC est
autonome ( avec sa pile LIR2032 )
ATTENTION : utiliser une CR2032
est risqué , Ubat=3,4V au
lieu de 4,1V max pour LIR2032
Verification en affichant le
contenu de la RTC:
on va donc LIRE les
registres RTC
issu de la doc MikroE
// for PIC18F K42 and K83 family
unsigned short I2Cx_Rd(char slave_address, char
*ptrdata, unsigned short count, unsigned short END_mode);
il faut d'abord faire connaitre , à
partir de quel registre , on veut lire , donc envoyer cette
adresse registre ..donc ECRIRE
tmp[0]=0 ; // adresse 0x00 pour
les secondes
I2C1_Wr( DS3231_ADDR, tmp, 1, _I2C_END_MODE_RESTART );
puis ensuite, Lire les 7 registres ( 0 à 6 ) , en 1 seule
instruction de LECTURE
I2C1_Rd( DS3231_ADDR, tmp, 7, _I2C_END_MODE_STOP );
Particularité, les données lues, seront rangées à partir de l'indice
0 de la table
on récupere donc les secondes dans tmp[0] .. ainsi que les
autres valeurs dans la table tmp
second=tmp[0];
minute=tmp[1];
heure=tmp[2];
jS=tmp[3];
if (jS>6) jS=0;
jour=tmp[4];
mois=tmp[5];
Annee=tmp[6];
Resultat:
SOFTWARE :
Projet MikroC :
-PIC18F27K42_UART1_RTC_I2C_HW_Test_190220.zip
source commenté : PIC18F27K42_UART1_RTC_DS3231_Hardw_I2C_Test_190220.html
Test LCD 2119 2x16 car ,
en liaison I2C .
27/02/2019
REMARQUE :
Test ADC 12bits , potar de 2,2K 10 tours pour simuler le LM35DZ
Gamme de mesure 1024 mV pour 4096 points !
Petit doute sur l'init ADC par la lib ADC MikroC, suite
instabilité de mesure ADC
voir : void My_ADC_Init (),
redéfinissant Clock ADC ..
Reprise du programme de gestion LCD2119 , en I2C Hardware ,
specifique au 18F27K42
source mikroC : LCD2119_Hardw_I2C_for_K42.c
Caracteres Speciaux : redefinition de Degre et Euro.
Nota: Ce LCD n'a pas de
caractere "Blanc" par défaut pour effacer l'ecran !
Affichage alterné : Date et Heure , EA1 en points ou en °C
Led Jaune sur sortie SQWE 1HZ de la RTC
Led Rouge s'active si reception sur UART1 ( cordon Prolific USB/TTL
Teraterm COM13 19200,8,N,1)
Mise à l'heure RTC via la liaison UART1 => exemple de cde : /
U;27;02;19;12;10;03;#<CR>
pour le 27 fev 2019 12H10 Mercredi
Projet MikroC :
Software complet : _18F27K42_Tests_UART_I2C_HW_ADC_LCD_190228.zip
Videos :
Base_18F27K42_Tests_LCD2119_19022.webm
Test
LCD 4x20 chars + RTC DS3231 , en liaison I2C1 Hardware.
(MikroC 7.60)
03/08/2020
rev 14/02.2021
Prototype :
avec Carte BASE 18F27K42
Liaison UART1 -> cordon prolific vers Terminal YAT
Liaison LCD I2C1 4 fils
Potar sur entree RA1
..Rajout RTC DS3231 sur bus I2C1 (14/02/2021)
Sur terminal YAT :
Presentation :
Directory :C:_MikroC_MesProjets_MikroC\_18F27K42_UART1_ADC12b_LCD_4x20_PCF8754_1_I2C1_HW_MC_Test_2021_02
MikroC pro 7.60
Projet :PIC18F27K42_UART1_ADC12b_LCD_4x20_PCF8754_I2C1_Hardw_MC_Test_2021_0212.mcppi
Test PIC18F27K42 avec lib I2C1 HW MC
Config bit : P18F27K42_Fosc_Interne_64Mhz.cfgsch FOSC:64.0 MHz
Source : PIC18F27K42_UART1_ADC_LCD_4x20_I2C_Hardw_et_PCF8754_2_Test_2021_0212.c_2021_0212.c
18F27K42 UART1, ADC ,LCD I2C 4x20 PCF8574
ATTENTION : adresse 7 bits donc @0x27
OTHERS LCD_4x20_PFC8574_for_18FxxK42_2021_02.mcl et *.c, *.h
Init I2C1 HARDWARE
Device(s) trouvés sur le bus
Device #1 at @27 ..<.............
LCD 4x20
Device #2 at @3C .<............ OLED
Device #3 at @57 < ........... EEPROM
Device #4 at @68 ...<.......... RTC
Init LCD I2C x20 PCF8754 @0x27
Init Steps = 9 sur 9
Init LCD I2C x20 PCF8754 @0x27
Init Steps = 9 sur 9
ADC_Init_Advanced (1,024V) pour EA1=RA1=LM35DZ
Init Timer0 sur 1 sec
EA1 Brut = 4095 Pts, I2C1 errors : 3319
EA1 Brut = 4095 Pts, I2C1 errors : 3519
EA1 Brut = 4095 Pts, I2C1 errors : 3719
EA1 Brut = 4095 Pts, I2C1 errors : 3919
EA1 Brut = 4095 Pts, I2C1 errors : 4119
EA1 Brut = 4095 Pts, I2C1 errors : 4319
EA1 Brut = 4095 Pts, I2C1 errors : 4519
EA1 Brut = 4095 Pts, I2C1 errors : 4719
EA1 Moy =04095 Pts ; 102.37 °C;
EA1 Brut = 4095 Pts, I2C1 errors : 116;
SOFTWARE:
la fonction principale est l'ecriture sur le PCF8754 pour piloter
le LCD , fonction tres differente du 18F26K22 !
Ce programme ; tres simple, n'explore pas TOUTES les
possibilités et subtilités de la librairie I2Cx Hardware
unsigned char I2C_PCF8574_Write(unsigned
char Adrp,unsigned char value)
{
unsigned char S;
dummy[0]=0x00 ;
dummy[1]=value ;
S=I2C1_Wr(Adrp,dummy ,2, _I2C_END_MODE_STOP );
return S;
}
L'adresse est l'adresse du device
sur 7 bits !
contrairement aux habituelles librairies MikroC ! 8 bits =
adresse device+ bit R/W
Header : lcd_4x20_pcf8574_for_18fxxk42_2021_02.h
unsigned char I2C_PCF8574_Write(unsigned
char Adr,unsigned char value) ;
void LCD_Cmd(unsigned char d);
void LCD_One_Cmd(unsigned char d);
void LCD_putcmd(unsigned char d,unsigned char cmdtype);
void LCD_init_4x20(void) ;
void LCD_CLS(void);
void LCD_Clear(void) ;
void Erase_Line(int L) ; // new;
void LCD_At(unsigned int Ligne,unsigned int col);
void LCD_Write_Chr(char c1);
void LCD_putch(unsigned char d);
void LCD_Chr_At(int Ligne,int col,char c1);
void LCD_puts( char *s);
void LCD_Chr(unsigned char d);
void LCD_Write_CText(const char *txt1);
void LCD_Write_CText_At(unsigned int Ligne,unsigned int col,const
char * t1);
void LCD_Write_Text_At(unsigned int Ligne,unsigned int col,char *
t1);
void LCD_At(unsigned int Ligne,unsigned int col);
void Cree_Char_Speciaux(void) ;
void DegreChar(char pos_row, char pos_char) ;
void EuroChar(char pos_row, char pos_char) ;
void OhmChar(char pos_row, char pos_char) ;
Pour palier au blocage possible , si l'adresse device n'est pas
connue ( ou reconnue !)
rajout de la fonction existante dans la librairie I2C_Remappable
// set timeout period and callback
function
//I2C1_SetTimeoutCallback(unsigned long timeout, void (*i2c1_timeout)(char));
I2C1_SetTimeoutCallback(100, I2C1_TimeoutCallback);
en rajoutant un traçage via UART dans le traitement
void I2C1_TimeoutCallback(char
errorCode)
{
if (errorCode == _I2C_TIMEOUT_RD) {
// do something if timeout is caused during read
I2C1_Count_Read_Errors++;
I2C1ERR=0;
// U1TXB='?';
//CPrint ("\r\n Error on Read\r\n");
}
if (errorCode == _I2C_TIMEOUT_WR) {
// do something if timeout is caused during write
I2C1_Count_Write_Errors++;
// CPrint ("\r\n Error on Write\r\n");
I2C1ERR=0;
// U1TXB='&';
}
Aucune idée d'ou proviennent les variables I2C_Timeout_Wr et Rd
?
et QUEL est le traitement à faire ?
Toujours est-il que le TEST est maintenant NON
Bloquant !
ce qui donne le resultat:
Init I2C1 HARDWARE
Test presence device(s) sur le bus I2C1
µµµµ
Device found at 0x27 soit 39
µµµµµµµµµµµµµµµµµµµµµµµ
Device found at 0x57 soit 87
µµµµµµµµµµµµµµµµµµ
Init LCD I2C x20 PCF8754 @0x27
Init Steps = 9 sur 9
Ecriture sur 4 lignes de 20 chars
Ecriture d'un caractere à une position définie
Definition de 3 Caracteres Speciaux : degre,euro et ohm
Lecture des registres RTC DS3231
?16/08/20 16H03M28S EA1 Brut = 4095 Pts ?T.DS3231 = 28.50°C
?16/08/20
16H03M29S EA1 Brut = 4095 Pts ?T.DS3231 = 28.50°C
?16/08/20
16H03M30S EA1 Brut = 4095 Pts ?T.DS3231 = 28.50°C
version 2020 : PIC18F27K42_UART1_ADC_LCD_4x20_PCF8754_I2C_Hw_RTC3231_NCO_Test_2020_0818.zip
On voit , qu'on entre dans le traitement d'erreur ECRITURE
avec le 'µ ' ! car ne
renvoit pas ACK ..
par la suite on a plus de traitement d'erreur pour l' écriture
sur affichage LCD
Par contre , on voit qu'il y a Traitement d'erreur sur les
LECTUREs RTC , via le '?'
rev 14/02/2021
Résultat sur terminal YAT :
Projet MikroC :
Modif :
usage de input RB1==0 pour pouvoir lancer un test presence
Devices sur le BUS.
Une fois les adresses devices connuees et verifiées, on peut se
passer du test avec RB1==1; ( ou N.C)
Projet MikroC :
PIC18F27K42_UART1_ADC12b_I2C1_Hw_LCD4x20_RTC3231_2021_0214.zip
Project : PIC18F27K42_UART1_ADC12b_I2C1_Hw_OLED_SSD1306_128x32_LCD4x20_RTC3231_2021_02.mcppi
config : PIC18F27K42_UART1_ADC12b_I2C1_Hw_LCD4x20_PCF8754_RTC3231_2021_02.cfg
main source : PIC18F27K42_UART1_ADC_I2C1_HW_LCD4x20_PCF8754_RTC_DS3231_Tests_2021_0214.c
RTC source : Tiny_RTC_DS3231_HARDW_I2C1_for_K42_2021_0214.c
RTC Header : Tiny_RTC_DS3231_HARDW_I2C1_for_K42_2021_0214.h
RTC Lib : Tiny_RTC_DS3231_HARDW_I2C1_for_K42_2021_0214.mcl
LCD source : LCD_4x20_PFC8574_for_18FxxK42_2021_0214.c
LCD Header : LCD_4x20_pcf8574_for_18fxxk42_2021_0214.h
LCD Lib : LCD_4x20_PFC8574_for_18FxxK42_2021_0214.mcl
Chargeur : PIC18F27K42_UART1_ADC12b_I2C1_Hw_LCD4x20_RTC3231_2021_0214.hex
Ruban Led RGB BTF-LIGHTING WS2812B Fils en
alliage ECO RGB 5050SMD adressable individuel 1m 60Pixels PCB
noir
Fabricant : BTF-LIGHTING Teachnology Co., Limited
WS21812E LED Strip
Dimensions du produit (L x l x h) ?12 x 10 x 1.5 cm; 20 grammes
Référence : WS2812B1M60LB30
Taille : 1m 60 LEDs
Couleur : Noir Pcb Ip30
Style : Moderne
Matière : FPCB
Type d'alimentation : DC 5V Power adapter supply
Tension : 5 Volts
Watt : 18.00
nota:
je pense que le fait de livrer le ruban enroulé sur un diametre
mini de 40mm pourrait contribuer à déteriorer
celui-ci ..
on ne voit nulle part un rayon de courbure minimum.?.
Sur les 60 leds du ruban , seules 7 leds contigues sont encore OK
...
9 ont cramés, d'autres ont DIN en court-circuit avec GND, d'autres
ont la jonction DIN DOUT coupée.
C'est arrivé à d'autres ! voir les commentaires acheteurs sur
le site du fournisseur !
in fine, la version WS2812E n'est pas
recommandée .. prefererer la version WS2812B
A la loupe on voit clairement celles qui ont cramé : Gros point
noir,
celles qui ont un point de jonction interne NOIR
et sur les autres rien de visible ..
une explication sur cette problematique :
Montage de test sur Base
18F27K42
2 modes via keyboard terminal :
Mode=1 alternance de couleur sur chaque led
Mode=2: changement de couleur à chaque salve
Commande N=xx, avec xx = nombre de leds du ruban
Mesures DC :
Avec U alim ruban =3.7V (au lieu de 5V nominal )
commande Couleur 'Bleu' maxi sur les 60 leds
I amperemetre = 0.4Amps
chute de tension entre entrée ruban et sortie ruban : 108mV
SOFTWARE :
rev 20/04/2024
Projet MikroC : PIC18F27K42_Test_Ruban_60_Leds_RGB_WS2812x_WS2815_2024.mcppi
Config : PIC18F27K42_Test_Ruban_60_Leds_RGB_WS2812x_WS2815_2024.cfg
Chargeur : PIC18F27K42_Test_Ruban_60_Leds_RGB_WS2812x_WS2815_2024.hex
Source : Test_Ruban_60_WS2812x_WS2815_18F27K42_2024_0420.c
video :
Test_morceau_Ruban_WS2812E_2021-0920.webm
----------------------------------------------------------------------
Test 3 types de
Leds RGB leds
sur la meme commande sortie PIC (dout = RC5)
*meme programme 18F27K42 que ci-dessus!
![]() |
![]() |
![]() |
Montage de TEST avec Base PIC18F27K42 | ruban 1M 60 leds RGB WS2815 ...IP65 | Led RGB WS2812B **dia 9,6mm ( externe !) |
* Ruban de 60 leds /M RGB type WS2815 IP65 12V DC
nominal ..
mais "Marchouille" ..
"Tombe en Marche" aussi
avec alim 5V , ça permet au moins de tester l'intégrité du
ruban si vous n'avez pas d'alim au dessus de 5V DC.
( avec luminosité plus faible et non respect des mélanges de
couleurs !)
* 20 Diodes Leds individuelles RGB type WS2812B 5V DC
rail +5V et Gnd soudé au dos , plus strap Dout-Din pour le
chainage des diodes leds.
...........necessite ~100 soudures ! .... 20 x2
x2+19 !
* Morceau de 7 leds recupéré sur un ruban 60leds/M RGB WS2812E
.. pas assez fiable !
Les 3 ensembles de leds sont pilotés par la sortie RC5 du PIC .
par le même Sofwtare bit bang ..commun .
Nota :
** attention le diametre donné pour les leds individuelles est
le diametre externe 9,6mm , la led seule fait ~4mm de diametre
*** le Ruban 60 Leds évite énormement de soudures ! sinon pres
de 300 soudures à
faire (60x2x2+59) en leds individuelles
le ruban WS2815 n'offre pas les
memes couleurs que les 2 modeles WS2812E et 2812B
j'ai pu trouver le pourquoi
ICI :
La différence entre le WS2815 et le WS2815
ECO.
Puce LED Matériel |
Puissance lumineuse |
période de garantie |
Cde couleur LED: |
|
WS2815 |
Fils de liaison en or pur 11 pièces |
Rouge: 300-600mcd, |
36 mois |
GRB |
WS2815 ECO |
Fils de liaison en alliage de 10 pièces |
Rouge: 200-350mcd, |
18 mois |
RGB |
en regardant à la loupe, la led , j'ai bien une WS2815
"or"
![]() |
![]() |
d'apres datasheet | mesures réelles ..... ©Temps-X |
Directory :C:\_MikroC\_MesProjets_MikroC\Test_ruban_WS2812x_WS2815_18F27K42_2021
MikroC pro 7.60
Projet :PIC18F27K42_Test_Ruban_Leds_RGB_WS2812x_WS2815_2021.mcppi
Hardware : Ruban WS2812E destroyed!
New ruban 60 leds 1M WS2815
Config bit : P18F27K42_Fosc_Interne_64Mhz.cfgsch
FOSC:64.0 MHz
Source : Test_Ruban_WS2812x_WS2815_18F27K42_2021-1025.c
BASE 18F27K42 UART1
Cde Led Dout = sortie RC5 -> Leds
Attention :
Couleur Ruban WS2815 en GBR .. WS2182 en RGB
Test interrupt Timer1 20 x 100 msec soit 2sec
Test Wait_Keyb -> Timeout or char received
#
... Waiting Keyboard Touch for <100 x 25mS >
Init Interrupt UART RX
RAZ All leds
video:
Test_3_types_leds_RGB_2021-1025.webm
Test fait sur 20 +8 leds (.chainées aux 20 premieres ). on ne
parcours donc pas tout le ruban de 60 leds
Test Numerically
Controlled Oscillator (NCO1))
28/11/2020
on peut l'assimiler à un generateur D.D.S. (DIRECT DIGITAL
SYNTHESIS)
1) En mode Frequence
Hardware :
PIC sur carte BASE 18F27K42
avec FOSC interne 16MHzx4(PLL)=> 64MHz
Entree ADC12 bit sur EA1 (RA1)
Led sur RA4, tirée au +Vcc
UART1 TX sur RC6 et RX sur RC7
SOFTWARE :
choix des Pins : sortie du module NCO1 et entree UART1 RX:
Unlock_IOLOCK() ;
U1RXPPS = 0x17; //RC7->UART1:RX1;
//TABLE 17-2: PPS OUTPUT REGISTER DETAILS
// NC01 = B5..B0 => 0b100110 avec B7..B6 00 => 0010 01100 =>0x26
// sur portA ou C
RC5PPS=0x26; // NCO1OUT= 0x26
Lock_IOLOCK() ;
Le mode FREQUENCE du module NCO1 nécessite de configurer
NCO1CON.PFM=0; // Fixed duty cycle
is 50%
Dans ce mode l' Accumulateur (registre 20 bits) n'est
pas utilisé, et la sortie passe par une bascule,
( => division par 2 !) pour avoir un duty cycle de 50%
Autres parametres :
NCO1CON.NCO1POL=0; //0 = NCO1 output
signal is not inverted
NCO1CON.NCO1EN=1; // Enabled
NCO1CLK permet de choisir la Frequence de pilote du NCO1
NCO1_Clock_Choix 0 1 2 3 4 5 6 7 8 9 10 |
NCO1CLK N1CKS<2:0> FOSC HFINTOSC LFINTOSC MFINTOSC (500 kHz) MFINTOSC/4 (32 kHz) SOSC CLKREF_out CLC1_out CLC2_out CLC3_out CLC4_out |
NCO1_Clock table 64 000 000 64 000 000 31 000 500 000 31250 |
NCO1CLK= NC01_Clock_Choix
;
avec choix de 0 à 10 ( testé ici , que de 0 à 4 )
Le registre INCREMENT de 20 bits , permet de
determiner la Frequence de sortie
en liaison avec le choix opéré via NCO1CLK
Ce registre de 20 bits est consttitué de 3 registres 8 bits
NCO1INCU U comme Upper byte (bits 19..16)
NCO1INCH H comme Higher Byte (bits 15..8
NCO1INCL L comme Lower byte (bits 7..0)
un entier long (de 32 bits) contiendra la valeur INCREMENT à
envoyer au registres du NCO1
J' y accede via un pointeur sur charactere ( byte)
unsigned char *pI;
pI=&Increment
NCO1INCU= *(pI+2);
NCO1INCH= *(pI+1);
NCO1INCL= *(pI+0);
nota : on n'utilisera pas *(pI+3) !
La formule adaptée , donnant la frequence de sortie sur RC5 :
Freq_Out= ( NCO1_Clock[NCO1_Choix_Clock]
/2 ) * Increment / Diviseur
avec diviseur = Constante= 2^20 = 1 048 576 .
ou à l'inverse
Increment = ( Fx * 2^20 * 2 )/ NCO1_Clock[NCO1_Choix_Clock]
Le terminal YAT sur UART11 , sert à verifier le contexte du test
:
Visualiser la valeur NCO1CLK , INCREMENT, valeur ANAlogique
Commande clavier :
NCO1CLK=x avec x=0 à 7
sur terminal :
NCO1CLK=4
OK NCO1CLK=4
Analog= 0=> Keyboard NCO1CLK=4 Increment
= 10000
On peut agir sur INCREMENT
via une commande de selection de mode :
Mode=1 commande analogique (ADC 12 bits)
Mode=0 commande via valeur numerique
Increment, via potar sur entree Analogique EA1
Pour avoir une plus grande dynamique que les 12 bits de base de l'ADC
je prends le cumul de 16 mesures => SEA1 ( qui sert aussi au
calcul de moyenne !)
sinon,
Commandes via Clavier :
INCREM=xxxxxxx la
valeur doit etre cadrée sur 7 digits
ex: INCREM=0033825
sur terminal: Mode 0=Keyboard NCO1CLK=2 Increment =0033825
exemple pour obtenir 500Hz avec NCO1 clock=2 =>31000Hz
Rajout commande Reglage fin OSCTUNE=x
OSCTUNE+ ou OSCTUNE-
variable de -31 à +31 par pas de 1
Detail sources clocks pour NCO1 :
Nota:
avec FOSC =Quartz 10MHz xPLL => 40MHz, OSCTUNE ne peu pas agit
sur ce mode d'horloge
de plus les frequence obtenues sur la sortie NC01 peuvent etre
tres hautes
.. si on cherche dans le domaine des frequences musicales
il faut rester soit en LFINTSOC à 31KHz
et auquel cas, en agissant sur OSCTUNE on peut parfaire la
commande de consigne frequence
Ex : pour une consigne de 0033825 pour 500Hz
OSCTUNE = 0 ----> 504Hz
OSCTUNE= +30 ---->519 Hz
OSCTUNE= -30 ---->193 Hz
avec un reglage OSCTUNE =-12 => pile poil 500Hz
soit utiliser l'Oscillateur Secondaire avec un Quart de 32,768KHz
! pour eviter les ajustements.
(solution pas encore testée)
Usage de SQA Analyser pour mesurer les signaux Freq Out RC5 :
Freq_out sur pin RC5 : = Increment * (NO1Clock / 2) / (2^20)
Récapitulatif des tests :
Limitation de mon analyser (SQA 50MHz) sur les mesures frequences
hautes !
3 Gammes de sorties disponibles avec ce NCO :
avec FOSC 64 000 000
Hz ------- 30.5Hz à > 15MHz
avec MFINTOSC 500 000 Hz ------- 0.238Hz à >
238 KHz
avec LFINTOSC 32 000 hz
------- 0.015 Hz à > 3 Khz
Terminal YAT :
fichier config terminal : Terminal_NCO1_18F27K42_19200_2021-06.yat
Projet MikroC 7.60
_18F27K42_NCO1_tests_20201128.zip
revision 13/06/2021
Projet complet : _18F27K42_NCO1_tests_2021-0613.zip
Source : PIC18F27K42_UART1_ADC12b_NCO1_FREQ_Test_with_Q10MHz_2021_0613.c
Chargeur : PIC18F27K42_UART1_ADC12b_NCO1_Freq_with_Q10Mhz_2021-06.hex
Presentation :
Directory :C:\_MikroC\_MesProjets_MikroC\_18F27K42_NCO1_tests
MikroC pro 7.60
Projet :PIC18F27K42_UART1_ADC12b_NCO1_Freq_with_Q10Mhz_2021-06.mcppi
Test PIC18F27K42 I2C1 HW
Config bit : P18F27K42_Q10Mhz_PLL_to_40MHz.cfgsch FOSC: Q10MHz x
4 =40.0 MHz
Source : PIC18F27K42_UART1_ADC12b_NCO1_FREQ_Test_with_Q10MHz_2021_0613.c
18F27K42 UART1, ADC12b, NCO1
OTHERS
Start SQA Analyser for NCO1 ...
Init NCO (voir page 454 datasheet)
Polarity =0 (Not inverted)
NCO1 operates in Fixed Duty Cycle mode 50% ,
divide by 2 (PFM=0)
Increment pour 500Hz = 33825
NCO1CLK choix = 2 soit LFINTOSC (31Khz) 31000.0
Choix clock => LFINTOSC (31Khz) soit
Correctif OSCTUNE = -12
Freq Output= 499.999
ADC_Init_Advanced (+Vcc= 2048 pts) pour EA1=RA1=LM35DZ
Init Timer0 sur 1 sec
Mode 0=Keyboard NCO1CLK_Choix=2 Increment = 33825, Freq Output=
499.999
Mode 0=Keyboard NCO1CLK_Choix=2 Increment = 33825, Freq Output=
499.999
Help
Help commandes :
NCO1CLK= (0 à 7) :
INCREM=xxxxxxx 7 digits
ANALOG=x 0=Keyboard 1=Analog
OSCTUNE=+ ou -
PFMODE=x 0=rapport cyclique fixe 1=rapport reglable
Nota: rajout du mode PFM=1 ,
rapport cyclique reglable via la valeur de PWS=0 à 7 (pour 1 à
128 )
Projet
MPLABX XC8
Projet : Test_18F27K42_NCO_MplabX_2020_1213.zip
source : main_Test_NCO_18F27K42_MplabX_2020_1213.c
chargeur : Test_18F27K42_NCO.X_2020_1213.hex
// exemple d'init pour 10Khz
// NCO1CLK = 0x03;
// 500KHz/2= 250 0000
// consigne 24 bits NCO1INCR= 41943 => 00h A3h D7h pour 10KHz
Application
MUSIC
Usage du NCO1 pour générer des notes
Programme issu d'une version MPLABX ( blog de Yves
Pelletier )
adapté pour MikroC..
La sortie NCO1 est sur RC5
qualité caca-boudin si on envoi direct la sortie sur un ampli ,
mais c'est juste pour le principe d'utiliser
le NCO pour sortir une Note donnée
...Je n'ai absolument pas l'oreille musicale !
Directory :C:\_MikroC\_MesProjets_MikroC\Music_18F27K42_NCO1_tests
MikroC pro 7.60
Projet :Joue_Note_18F27K42_via_NCO.mcppi
Test PIC18F27K42 NCO1
Config bit : P18F27K42_Fosc_Interne_64Mhz.cfgsch FOSC:64.0 MHz
Source : Joue_Note_18F27K42_via_NCO_2020_1206.c
18F27K42 UART1 ADC12b NCO1
..
OTHERS ...
Init NCO1 en mode Frequence
Sortie RC5 NCO1 avec Duty Cycle=50% (PFM=0)
NCO1CLK choix = 3 soit MFINTOSC (500 kHz)
NCO1 output test de 1 à 10Khz
j= 0 Step= 4194 Increment = 4194 Freq Output= 999.927
j= 1 Step= 4194 Increment = 8388 Freq Output= 1999.855
j= 2 Step= 4194 Increment = 12582 Freq Output= 2999.782
j= 3 Step= 4194 Increment = 16776 Freq Output= 3999.710
j= 4 Step= 4194 Increment = 20970 Freq Output= 4999.637
j= 5 Step= 4194 Increment = 25164 Freq Output= 5999.565
j= 6 Step= 4194 Increment = 29358 Freq Output= 6999.492
j= 7 Step= 4194 Increment = -31984 Freq Output= 7999.419
j= 8 Step= 4194 Increment = -27790 Freq Output= 8999.347
j= 9 Step= 4194 Increment = -23596 Freq Output= 9999.274
Musique Maestro !
Software MikroC :
Global : Music_18F27K42_NCO1_tests_2020_1206.zip
Project : Joue_Note_18F27K42_via_NCO.mcppi
Source : Joue_Note_18F27K42_via_NCO
Config : P18F27K42_Fosc_Interne_64Mhz.cfgsch
Music avec
fichiers RTTL
Version avec fichier original RTTL , récupéré
avec Appli RTTL.EXE de TempsX
en version data ASM
fichier data ,Remodifié ensuite via notetab++ ,
pour version en C
Dans l'application RapidQ RTTL.exe ,
1) ouvrir un fichier musical au format Rttl, ex: Pink panther
2) Le Lire
3) L'editer ( touche Note noire)
4) L'exporter en ASM
... il est copié dans le Press-papier !
![]() |
![]() |
![]() |
Ouvrir un fichier et le lire | Editer le fichier | Exporter au format table ASM |
coller l'export dans un nouveau
fichier texte de NOTEPAD++
on obtient par exemple ceci :
;**********************************************************************
;************** titre de la mélodie, Theme, taille 240 octets,
durée 0 min 16 sec ****
;**********************************************************************
ORG H''
melodie
db 0xFE,0xFD,0xFC,0xFB,0xFA,0x54,0x68,0x65,0x6D,0x65,0xFE,0xFD,0xFC,0xFB,0xFA,0x00
db 0xD9,0x8E,0x00,0xF0,0x00,0xE6,0xAF,0x03,0xC0,0x01,0x02,0xEA,0x00,0xF0,0x01,0x12
db 0x39,0x03,0xC0,0x00,0xD9,0x8E,0x00,0xF0,0x00,0xE6,0xAF,0x00,0xF0,0x01,0x02,0xEA
db 0x00,0xF0,0x01,0x12,0x39,0x00,0xF0,0x01,0x6E,0x14,0x00,0xF0,0x01,0x59,0x9C,0x00
db 0xF0,0x00,0xE6,0xAF,0x00,0xF0,0x01,0x12,0x39,0x00,0xF0,0x01,0x59,0x9C,0x00,0xF0
db 0x01,0x45,0xD0,0x03,0xC0,0x01,0x33,0xB1,0x00,0x78,0x01,0x12,0x39,0x00,0x78,0x00
db 0xE6,0xAF,0x00,0x78,0x00,0xCD,0x6F,0x00,0xF0,0x00,0xE6,0xAF,0x07,0x80,0x00,0xD9
db 0x8E,0x00,0xF0,0x00,0xE6,0xAF,0x00,0xF0,0x01,0x02,0xEA,0x00,0xF0,0x01,0x12,0x39
db 0x00,0xF0,0x01,0x59,0x9C,0x00,0xF0,0x01,0xCD,0x5F,0x00,0xF0,0x01,0xB3,0x1D,0x00
db 0xF0,0x00,0xD9,0x8E,0x00,0xF0,0x00,0xE6,0xAF,0x03,0xC0,0x01,0x02,0xEA,0x00,0xF0
db 0x01,0x12,0x39,0x03,0xC0,0x00,0xD9,0x8E,0x00,0xF0,0x00,0xE6,0xAF,0x00,0xF0,0x01
db 0x02,0xEA,0x00,0xF0,0x01,0x12,0x39,0x00,0xF0,0x01,0x6E,0x14,0x00,0xF0,0x01,0x59
db 0x9C,0x00,0xF0,0x00,0xE6,0xAF,0x00,0xF0,0x01,0x12,0x39,0x00,0xF0,0x01,0x59,0x9C
db 0x00,0xF0,0x01,0x59,0x9C,0x00,0xF0,0x00,0xE6,0xAF,0x00,0xF0,0x01,0x12,0x39,0x00
db 0xF0,0x01,0x59,0x9C,0x00,0xF0,0x01,0x45,0xD0,0x00,0xF0,0x01,0x33,0xB1,0x00,0xF0
db 0x01,0x12,0x39,0x00,0x78,0x00,0xE6,0xAF,0x00,0x78,0xFE,0xFD,0xFC,0xFB,0xFA
avec notetab++
Recherche ... Remplacer...... Remplacer db par \r\n, ( espace dB par CR LF et virgule)
puis supprimer les adresses sur 5 bytes
Conserver
le
nom actuel (
qui pourrait etre rallongé , complété ..plus de limites..)
Rajouter un suffixe terminateur 0xFF apres le
Nom et aussi 0xFF en fin de fichier
on obtient alors la version pour langage C
rajouter l'entete de definition de la nouvelle
table
ex:
unsigned char PinkPanther[]={
// 0xFE,0xFD,0xFC,0xFB,0xFA,
0x50,0x69,0x6E,0x6B,0x50,0x61,0x6E,0x74,0x68,0x65,0x72,0xFF,
//0xFE,0xFD,0xFC,0xFB,0xFA,
0x00,0xA2,0xE8,0x00,0xBC,0x00,0xAC,0xCE,0x00,0xBC,0x00,
0x00,0x00,0x02,0xEE,0x00,0xC1,0xD1,0x00,0xBC,0x00,0xCD,0x6F,0x00,0xBC,0x00,0x00,
0x00,0x02,0xEE,0x00,0xA2,0xE8,0x00,0xBC,0x00,0xAC,0xCE,0x00,0xBC,0x00,0x00,0x00,
0x00,0x5E,0x00,0xC1,0xD1,0x00,0xBC,0x00,0xCD,0x6F,0x00,0xBC,0x00,0x00,0x00,0x00,
0x5E,0x01,0x12,0x39,0x00,0xBC,0x01,0x02,0xEA,0x00,0xBC,0x00,0x00,0x00,0x00,0x5E,
0x00,0xA2,0xE8,0x00,0xBC,0x00,0xAC,0xCE,0x00,0xBC,0x00,0x00,0x00,0x00,0x5E,0x01,
0x02,0xEA,0x00,0xBC,0x00,0xF4,0x46,0x02,0xEE,0x00,0x00,0x00,0x02,0xEE,0x00,0xE6,
0xAF,0x00,0x5E,0x00,0xCD,0x6F,0x00,0x5E,0x00,0xAC,0xCE,0x00,0x5E,0x00,0x99,0xD8,
0x00,0x5E,0x00,0xAC,0xCE,0x02,0xEE,
//0xFE,0xFD,0xFC,0xFB,0xFA
0xFF
};
autre example de fichier une fois transformé :
unsigned char Something[]={
0x53,0x6F,0x6D,0x65,0x74,0x68,0x69,0x6E,0xFF,
// le titre
0x00,0xD9,0x8E,0x01,0x2C,0x01,0x02,0xEA,0x01,0x2C,0x01,0x02,0xEA,0x01,
0x2C,0x01,0x02,0xEA,0x01,0x2C,0x01,0x02,0xEA,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,
0x01,0x22,0x69,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,
0x45,0xD0,0x01,0x2C,0x01,0x45,0xD0,0x01,0x2C,0x01,0x45,0xD0,0x01,0x2C,0x01,0x45,
0xD0,0x01,0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x45,0xD0,
0x01,0x2C,0x01,0x02,0xEA,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,0x22,0x69,0x01,
0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x45,0xD0,0x09,0x60,0x00,0x00,0x00,0x04,0xB0,
0x00,0xE6,0xAF,0x01,0x2C,0x01,0x02,0xEA,0x01,0x2C,0x01,0x02,0xEA,0x01,0x2C,0x01,
0x02,0xEA,0x01,0x2C,0x01,0x02,0xEA,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,0x22,
0x69,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,0x45,0xD0,
0x01,0x2C,0x01,0x45,0xD0,0x01,0x2C,0x01,0x45,0xD0,0x01,0x2C,0x01,0x45,0xD0,0x01,
0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x45,0xD0,0x01,0x2C,
0x01,0x02,0xEA,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,0x22,0x69,0x01,0x2C,0x01,
0x45,0xD0,0x01,0x2C,0x01,0x22,0x69,0x09,0x60,0x00,0x00,0x00,0x04,0xB0,0x01,0x02,
0xEA,0x01,0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x59,0x9C,
0x01,0x2C,0x01,0x59,0x9C,0x01,0x2C,0x01,0x83,0xA3,0x01,0x2C,0x01,0x83,0xA3,0x01,
0x2C,0x01,0x83,0xA3,0x01,0x2C,0x01,0x83,0xA3,0x01,0x2C,0x01,0xB3,0x1D,0x01,0x2C,
0x01,0xB3,0x1D,0x01,0x2C,0x01,0xB3,0x1D,0x01,0x2C,0x01,0xB3,0x1D,0x01,0x2C,0x02,
0x05,0xD4,0x01,0x2C,0x01,0xCD,0x5F,0x01,0x2C,0x01,0xB3,0x1D,0x01,0x2C,0x01,0xCD,
0x5F,0x01,0x2C,0x01,0xB3,0x1D,0x02,0x58,0x01,0x83,0xA3,0x01,0x2C,0x01,0x83,0xA3,
0x09,0x60,0x00,0x00,0x00,0x04,0xB0,0xFF
};
une table de pointeurs est utilisée pour repérer
la melodie à jouer, par son numero dans la liste
char * Liste_Melodie[]= {Mission_Impossible,BOLERO,Smoke,Something,PinkPanther,LaureletHardy,Alfred_Hitchcok};
unsigned int Index=0;
Appel de la fonction : avec comme parametre l'indice
de la table et un drapeau permettant de voir des details sur un
terminal
void Play_Melodie(char
Num, char Visu) // drapeau visu=1 ou 2 ou 3
{
unsigned int i,j,k,Index;
unsigned char *pM;
pM=Liste_Melodie[Num] ;
NCO1EN_bit=0;
NCO1CLK=4; // Clock 31250Khz ,
NCO1EN_bit=0;
Delay_ms(100);
Index=0; i=0;
do
{
cx=*(pM+i);
*(CRam1+i)=cx;
if ( cx==0xFF) break;
i++;
}
while (i<64);
*(CRam1+i)=0;
if(Visu >0)
{
CPrint(" Melodie #"); UART1_Write(Num+48);UART1_Write('
');
Print (CRam1); CRLF1();
}
p0=(unsigned char *)&L1;
L1=0;
i++;
Index=0;
do
{
if( Visu >1 )
{ WordToStr(Index,CRam1);
Print(CRam1);UART1_Write('-');
}
*(p0)=0;
cx=*(pM+i) ;
// freqence
if ( cx==0xFF) break;
NCO1INCU= cx ;
*(p0+1)=cx;
cx=*(pM+i+1) ;
if ( cx==0xFF) break;
NCO1INCH= cx ;
*(p0+2)=cx;
cx=*(pM+i+2) ;
if ( cx==0xFF) break;
NCO1INCL= cx ;
if( Visu >1)
{
*(p0+3)=cx;
LongWordToStr(L1,CRam1);
Print(CRam1); UART1_Write('-');
}
// duree
cx=*(pM+i+3) ;
if ( cx==0xFF) break;
k= cx ;
k=k<<8;
cx=*(pM+i+4) ;
if ( cx==0xFF) break;
k=k +cx;
if( Visu >1 )
{
WordToStr(k,CRam1);
Print(CRam1);CRLF1() ;
}
NCO1EN_bit=1;
for (j=0;j<k;j++) Delay_ms(1);
NCO1EN_bit=0;
i=i+5;
Index=Index+5;
}while(cx!=0xFF) ;
if(Visu >1)
{
CPrint( " -> Clock=500Khz..End\r\n");
}
NCO1EN_bit=0;
NCO1CLK= 3 ;
Delay_ms(100);
}
Nota : le choix de
test cx==0xFF pourrait etre unique ...
avec un modulo 5 rigoureux dans la table
Exemple d'usage :
CPrint (" ATTENTION : modif choix NCO1CLK =4 => 31KHz !! \r\n");
NCO1_Clock_Choix=4; // 4=31250Khz
NCO1CLK= PWS_Valeur<<5 | NCO1_Clock_Choix ;
Play_Melodie(0,0);
Delay_ms(1000);
Play_Melodie(1,1);
Delay_ms(1000);
Play_Melodie(2,0);
à l'execution, sur terminal YAT:
Presentation :
Directory :C:\_MikroC\_MesProjets_MikroC\_18F27K42_NCO1_testsDirectory
:C:\_MikroC\_MesProjets_MikroC\PLAY_RTTL_MUSIC_2022
MikroC pro 7.60
Projet :Play_Music_RTTL_18F27K42.mcppi
Config bit : P18F27K42_Fosc_Interne_64Mhz_with_IVT_2022-0210.cfgsch
Eeprom: No
Source : Play_Music_RTTL_18F27K42_2022-0221.c
Test fichiers Musicaux RTTL
issus de l'appli RTTL.exe de Temps-X)
..format adapté ensuite pour le C
18F27K42 UART1 115200
NCO output sur RC0 -> Buzzer Piezzo
Usage Interrupt Vectors
Clock 31250Khz ,Melodie #3 Somethin
0-2396585984- 300
5-3925999872- 300
10-3925999872- 300
15-3925999872- 300
20-3925999872- 300
25-1763836160- 300
30-1763836160- 300
35-1763836160- 300
40-1763836160- 300
45-3494183168- 300
50-3494183168- 300
55-3494183168- 300
60-3494183168- 300
65-2623078656- 300
70-2623078656- 300
75-3494183168- 300
80-3925999872- 300
85-1763836160- 300
90-1763836160- 300
95-2623078656- 300
100-3494183168- 2400
105- 0- 1200
110-2951086080- 300
115-3925999872- 300
120-3925999872- 300
125-3925999872- 300
130-3925999872- 300
135-1763836160- 300
140-1763836160- 300
145-1763836160- 300
150-1763836160- 300
155-3494183168- 300
160-3494183168- 300
165-3494183168- 300
170-3494183168- 300
175-2623078656- 300
180-2623078656- 300
185-3494183168- 300
190-3925999872- 300
195-1763836160- 300
200-1763836160- 300
205-3494183168- 300
210-1763836160- 2400
215- 0- 1200
220-3925999872- 300
225-2623078656- 300
230-2623078656- 300
235-2623078656- 300
240-2623078656- 300
245-2743271680- 300
250-2743271680- 300
255-2743271680- 300
260-2743271680- 300
265- 498270464- 300
270- 498270464- 300
275- 498270464- 300
280- 498270464- 300
285-3557097984- 300
290-1607270656- 300
295- 498270464- 300
300-1607270656- 300
305- 498270464- 600
310-2743271680- 300
315-2743271680- 2400
320- 0- 1200
325- -> Clock=500Khz..End
Melodie #0 Mission Imp
Melodie #1 Bolero
Melodie #2 Smoke on the water
Melodie #3 Somethin
Melodie #4 PinkPanther
Melodie #5 LaurelAn
Melodie #6 AlfredHi
Appuyer sur une touche clavier
Output MPLAB IPE V5.30:
Loading code from C:\_MikroC\_MesProjets_MikroC\PLAY_RTTL_MUSIC_2022\Play_Music_RTTL_18F27K42.hex...
2022-02-21 15:22:55 +0100 - Hex file(s) loaded successfully.
2022-02-21 15:22:57 +0100 - Programming...
*****************************************************
Calculating memory ranges for operation...
Erasing...
The following memory area(s) will be programmed:
program memory: start address = 0x0, end address = 0x3bff
configuration memory
User Id Memory
Programming/Verify complete
2022-02-21 15:23:06 +0100 - Programming complete
Programme MikroC 7.60 :
Projet :Play_Music_RTTL_18F27K42.mcppi
Zip : PLAY_RTTL_MUSIC_with_NCO_18F27K42_2022.zip
Source C : Play_Music_RTTL_18F27K42_2022_0221
Chargeur : Play_Music_RTTL_18F27K42_2022-02.hex
config : Play_Music_RTTL_18F27K42.cfg
Projet Schem : P18F27K42_Fosc_Interne_64Mhz_with_IVT_2022-0210.cfgsch
Log Terminal : YAT-Log-20220221-152302.log
Ressources utilisés :
0 1144 Used RAM (bytes): 2200 (27%) Free RAM (bytes): 5970 (73%)
0 1144 Used ROM (bytes): 15719 (12%) Free ROM (bytes): 115353 (88%)
ancienne version :
Old Source :PIC18F27K42_UART1_ADC12b_NCO1_FREQ_Test_Fosc_interne_64MHz_IVT_Mode_Play_Melodie_2021-0917.c
chargeur : PIC18F27K42_UART1_ADC12b_NCO1_Freq_IVT_Mode_Play_Melodie_2021-0917.hex
nota : possibilité d'utiliser aussi le mode Interrupt classique
dit "Legacy"
18F27K42_Interrupt_mode_legacy_2021-09.h
En
MIEUX
et sophisiqué pour les oreilles , sans NCO1
Version Software ASM :
Page web du concepteur : Bernard.chabbert.pagesperso-orange.fr
explication (pdf) : Boite
à musique
version ASM originale
18F25K42 transposée pour le PIC18F27K42
nota : utilisation de MPLABX v5.30 et MPASM
version 5.86
Boite_A_Musique_27k42_Chabb.zip
Test sur FOSC
avec sortie Clkout RA6
11/12/2020
A des fin de vérification de la valeur FOSC utilisée, j'ai
voulu verifer sur la sortie ClockOut RA6 si on avait bien FOSC/4
Tout se passe bien avec HFINTOSC , generateur FOSC interne, jusqu'à
32MHZ (et OSCFRQ=6
J'ai bien FOSC/4= 32/4=2MHz sur la
sortie RA6 , testé ave SQA 50 Analyser logique.
config typique de FOSC
OSCCON1 = 0x60; // NOSC
HFINTOSC; NDIV 1;
while(OSCCON2 != OSCCON1) //Wait for Clock Switch to occour
OSCCON3 = 0x00; // CSWHOLD may proceed; SOSCPWR Low power;
OSCEN = 0x00; // MFOEN , LFOEN , ADOEN ,SOSCEN, EXTOEN,HFOEN all
disabled;
OSCFRQ = 0x08; // HFFRQ 0x08=64MHz ; 0x07=48Mhz; 0x05=16Mhz ; 0x02=4Mhz
OSCTUNE = 0x00; // TUN 0;
while(!OSCSTATbits.HFOR);
via MPLABX :
Par contre ,avec FOSC=64MHz et donc OSCFRQ=8
Je ne detecte rien sur sur RA6 avec
mon analyser SQA50, uniquement un niveau haut
permanent.
Un coup d'oeil à l'oscillo montre quand meme un petit signal.
![]() |
![]() |
amplitude env 500mV cr cà cr. et à 16MHz ! Le pic étant alimenté en 3,6V. |
second test , avec Vcc=5V Amplitude autour de 2V cr.à Cr. , et à 16MHz. |
La sortie FOSC/4 semble insufisament bufferisée pour sortir des
niveaux CMOS ..
A noter que j'utilise une sonde 1/10 (faible capcité <5pF)
pour ne pas perturber le signal.
Si je rajout mon entree SQA analyser sur RA6, l'amplitude tombe
à 1,08V cr Cr.
WHY ?
Question posée sur le forum
Microchip ..
Re: Clockout on 18F27K42 Yesterday (permalink)
Jerry Messina
Is the slew-rate limiting getting in the way of your measurements?
SLRCONA defaults to 0xFF (slow)
RIC
+1 (1) That still sounds like slew
limiting is enabled on that pin.
En effet, modif programme : SLRCONA=0xBF ; //
was 0xFF ! résoud le probleme.
2 ) En mode PULSE
NCO1CON.PFM=1;
....à suivre
Test LCD 4x20
chars , en liaison I2C1 Software. (MikroC)
08/08/2020
Bus I2C1 sur RC3=SCL et RC4=DATA
Detection device sur bus I2C1 ..OK ( en I2C1
Software !)
Rajout caracteres speciaux : Ohm,Degré,Euro
*******************************
I2C software 18F27K42 mikroC
********************************
Presentation :
Directory :C:_MikroC_MesProjets_MikroC_BASE_18F27K42
MikroC pro 7.30 Beta <LF><CR> Projet :PIC18F27K42_UART1_ADC12b_LCD_4x20_PCF8574_I2C1_Softw_Test_2020_08.mcppi
Test PIC 18F27K42 I2C SOFTWARE
Config bit : P18F27K42_Fosc_Interne_64Mhz.cfgsch FOSC: 64Mhz MHz
Source : PIC18F27K42_UART1_ADC_LCD_4x20_Softw_I2C_Test_2020_0808.c
Init I2C1 SOFTWARE
Recherche devices sur le bus I2C1 RC3=SCL RC4=SDA (softw)
Device at adresse 20 is not found
Device at adresse 22 is not found
....
Device at adresse 4C is not found
Device at adresse 4E found OK
<------------
Device at adresse 50 is not found
Device at adresse 52 is not found
....
Device at adresse FA is not found
Device at adresse FC is not found
Creation caracteres Speciaux Ohm,Degre,Euro
ADC_Init_Advanced (1,024V) pour EA1=RA1=LM35DZ
Init Timer0 sur 1 sec
EA1 = 4095 Pts
EA1 = 4095 Pts
EA1 = 4095 Pts
EA1 = 4095 Pts
EA1 = 4095 Pts
EA1 = 4095 Pts
EA1 = 4095 Pts
EA1 = 4095 Pts
EA1=04095 Pts ; EA1 = 102.3 °C
EA1 = 4095 Pts
EA1 = 4095 Pts
Projet MikroC :
Zipé: PIC18F27K42_UART1_ADC12b_LCD_4x20_PCF8574_I2C_Softw_Test_2020_08.zip
Source C : PIC18F27K42_UART1_ADC_LCD_4x20_I2C_Hardw_et_PCF8754_2_Test_2020_0803.c
Lib LCD : LCD_4x20_PFC8574_for_18FxxK42_2020_08.mcl
Header Lib :
LCD_4x20_Soft_I2C_PCF8574_2020_08.h
Test
Ecriture PCF8574 sur 18F27K42 (2020)
Gestion I2C Hardware tres differente sur ce PIC !
l'adresse I2C utilisée dans les fonctions est l'adresse device
et non plus l'adresse 8 bits !
SAUF si on utilise le SOFT I2C !
ATTENTION , PIC avec entrees/sorties configurable
Necessite d'activer la librairie Perpheral Pin Select
pour faire le bon aiguillage entre PINs du PIC et
fonctionalité associé
On ne change pas une equipe qui gagne, je reste donc
avec :
bus I2C1 Hardware sur RC3=SCL et RC4=SDA
Unlock_IOLOCK() ;
I2C1SDAPPS = 0x14; //RC4->I2C1:SDA1;
I2C1SCLPPS = 0x13; //RC3->I2C1:SCL1;
RC3PPS = 0x21; //RC3->I2C1:SCL1;
RC4PPS = 0x22; //RC4->I2C1:SDA1;
RC6PPS = 0x13; //RC6->UART1:TX1;
U1RXPPS = 0x17; //RC7->UART1:RX1;
// U1CTSPPS = 0x15; //RC5->UART1:CTS1;
RC5PPS=NCO1OUT; // RC5 => 0x26 ?
Lock_IOLOCK() ;
Attention au type
de boitier MCU utilissé pour une meme reference de PIC
ici PIC en boitier PDIP 28 broches!
Hardware :
Cablage des 3 pins adresses PCF8574
A0=Vcc=>1 A1=Vcc =>1, A2=Gnd => 0 -----> soit 011 =>
0110 avec x=bit R/W à zero
L'adresse devient donc : Base 0x40 + 0x06 (sur 8 bits avec le bit
R/W)
sinon, adress device sur 7 bits : 0x23
MikroC propose une librairie I2C plus ou moins bien explicitée
!..
Le premier test est la recherche du device sur le BUS I2C1
Il est indispensable d'armer la fonction Timeout, sinon, le
programme se bloque, dès la premiere adresse I2C non valable. (car
ne reçoit pas de Ack !)
SQA 50 analyser sur bus I2C
SOFTWARE :
Adresse I2C complete , format 8 bits = 0x46
Adresse I2C format device 7 bits = 0x23
Init I2C1 HARDWARE
Test presence device(s) sur le bus I2C1
µµµµµµµµµµµµ
Device found at 0x 23 soit 35
µµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµµ
Bus I2C1 : PCF8754 @0x23 A0=1 A1=1 A2=0
Mesure Analogique sur 12 bits ,
avec +Vref=2.048V
Moyenne arithmetique sur 8 valeurs ..
gamme : 2048mV pour 4096 Pts
LM35DZ donne 10mV/°C => 204.8°C
cumul sur 8 mesures => moyenne = 4096*8=> 32768 points
coef pour mise à l'echelle en degré C= 0.00625
EA1 Moy =02334 Pts ;
116.72 °C;
EA1 Moy =04095 Pts ;
204.75 °C;
Projet MikroC 7.60
PIC18F27K42_UART1_ADC_PCF8754_I2C_Hw_et_NCO_Test_2020_1123.zip
Source: PIC18F27K42_UART1_ADC_PCF8754_I2C_Hw_et_NCO_Test_2020_1123.c
Chargeur : PIC18F27K42_UART1_ADC12b_PCF8754_I2C1_Hw_NCO1_2020_11.hex
Les Timers du
18F27K42
TIMER0
en mode pooling (avec MikroC)
voir DS40001919F-page 301....
Timer0 sur 1 seconde avec FOSC=64MHz , utilisé en mode Polling,
pour caler la duree d'excution d'une boucle principale
de programme .. Le mode pooling est privilégié dans ce cas,pour
ne pas perturber le programme principal, pouvant
par ailleur ,utiliser des interruptions.
Evite une situation bloquante telle qu'un Delay_ms(1000);
utilisant toutes les ressources MCU ( sauf si IT utilisées)
FOSC=64MHz, usage de FOSC/4 comme Clock Timer1
Cycle = 4/64= 0.0625µS
Prediviseur= 1/256 ,
Postdiviseur non utilisé
: 1/1
TMR0 16 bits initialisé à : 3036
d'où la durée :
(65536-3036) * 256 *1 * 0.0625 = 1 000 000 µS
Software (MikroC):
void Init_Timer0_1sec()
{
// REGISTER 22-1: T0CON0: TIMER0 CONTROL REGISTER 0
T0CON0=0;
T0CON0.B7=0; // Disable module and operating
T0CON0.B4=1; //MD16=1;
// OUTPS<3:0>: TMR0 Output Postscaler (Divider)
Select bits 0000= 1/1
T0CON0.B3=0;
T0CON0.B2=0;
T0CON0.B1=0;
T0CON0.B0=0;
// REGISTER 22-2: T0CON1: TIMER0 CONTROL REGISTER 1
// bit 7-5 CS<2:0>:Timer0 Clock Source Select bits = 011
HFINTOSC 010=FOSC/4
T0CON1.B7=0; //T0CON1.CS2
T0CON1.B6=1; //T0CON1.CS1
T0CON1.B5=0; //T0CON1.CS0
// bit 4 ASYNC: TMR0 Input Asynchronization Enable bit
// T0CON1.ASYNC=0;//The input to the TMR0 counter is not
synchronized to FOSC/4
T0CON1.ASYNC=1;//The input to the TMR0 counter is synchronized to
FOSC/4
// bit 3-0 CKPS<3:0>: Prescaler Rate Select bit
T0CON1.B3=1 ; // CKPS3:0 1000=> 1/256
T0CON1.B2=0 ;
T0CON1.B1=0 ;
T0CON1.B0=0 ;
Drapeaux.Tmr0_Elapsed=0 ;
Count0=0;
PIR3.TMR0IF = 0; // Flag Timer0
PIE3.TMR0IE = 0 ; // TMR0 disable Interrupt.
T0CON0.B7=1; // Enable module and operating
TMR0H = 0x0B; //3036 => 62500 cycles;
TMR0L = 0xDC;
}
Usage :
CRLF1();
Print(" Test Timer0 en mode pooling sur 1 sec \r\n");
Init_Timer0_1sec(); // init and start tmr0
// do something here .. in less than 1seconde elpsed time
Delay_ms(800); // simulate some job to do
while(PIR3.TMR0IF == 0); // wait until loop duration is 1 sec
Print(" Fin de test Timer0\r\n");
Resultat :
(11:31:57.227) Test Timer0 en mode pooling
sur 1 sec
(11:31:58.232) Fin de test Timer0
TIMER0
en mode Interrupt , avec value f (Postscaler > 1 )
(avec MPLABX XC8)
Le Timer0 mode 16 bits est utilisé ici via une Interupt
Vectorisée , avec FOSC=64MHz
Le Postscaler est utilisé (car > 0)
L'usage du Poscaler est PIEGEUX
! car il ne multiplie pas le comptage initial déterminé
par la valeur de TMR0,
comme avec le PRESCALER.
voir le post sur le
forum Microchip et discution sur le forum
Fantaspic.
init variables : volatile uint16_t Cpt0; volatile struct Anybits { // 8 flags unsigned Tmr0_Elapsed:1; // for timer0 16bits unsigned Tmr1_Elapsed:1; // for timer1 16bits unsigned Tmr2_Elapsed:1; // for timer2 8bits unsigned Tmr3_Elapsed:1; // for timer3 16bits unsigned Tmr4_Elapsed:1; // for timer4 8bits unsigned Tmr6_Elapsed:1; // for timer6 8bits unsigned NCO_initialise:1; // for NCO unsigned Key_ON :1; // detection appui BP }Drapeaux ; Init Vecteurs d' Interruptions void Interrupt_Init(void) { INTCON0bits.IPEN = 1; bool state = (unsigned char) INTCON0bits.GIE; INTCON0bits.GIEH = 0; // dishigh priority interrupts INTCON0bits.GIEL = 0; // dis low priority interrupts INTCON0bits.IPEN = 1; // Enable interrupt priority IVTLOCK = 0x55; IVTLOCK = 0xAA; IVTLOCKbits.IVTLOCKED = 0x00; // unlock IVT IVTBASEU = 0; IVTBASEH = 0; IVTBASEL = 8; IVTLOCK = 0x55; IVTLOCK = 0xAA; IVTLOCKbits.IVTLOCKED = 0x01; // lock IVT // Assign peripheral interrupt priority vectors IPR3bits.U1RXIP = 1; IPR3bits.TMR0IP = 0; INTCON0bits.GIE= state; } Interrupt de traitement TMR0: void __interrupt(irq(IRQ_TMR0),high_priority)TMR0_ISR(void) { Cpt0++ ; // x 100ms avec MFINTFosc=500Khz LED_verte=0; // allume led (car tir\0xE9e au +Vcc) Drapeaux.Tmr0_Elapsed=1; TMR0H = 0x5E; // 24288 TMR0L = 0xE0; PIR3bits.TMR0IF = 0; // T0CON0bits.EN=0; // stope timer0 } L'init du timer0 void Init_Timer0_16b_500mS() { T0CON0=0; T0CON0bits.EN=0; T0CON0bits.MD16=1; //CS[2:0]:Timer0 Clock Source Select bits //// 010 = FOSC/4 T0CON1bits.CS2=0; T0CON1bits.CS1=1; T0CON1bits.CS0=0; //0= The input to the TMR0 counter is synchronized to FOSC/4 T0CON1bits.ASYNC=0; // Postscaler=7 => 1/8 T0CON0bits.OUTPS3=0; T0CON0bits.OUTPS2=1; T0CON0bits.OUTPS1=1; T0CON0bits.OUTPS0=1; // CKPS[3:0]: Prescaler =4 => Rate Select bit => div 1/16 T0CON1bits.CKPS3=0; T0CON1bits.CKPS2=1; T0CON1bits.CKPS1=0; T0CON1bits.CKPS0=0; TMR0H = 0x5E; // 24288 TMR0L = 0xE0; // complement=65536-24288=41248 => 0x5EE0 // =MCU_Cycle*Pre_div*( (Post_div-1) *65536 + 65536-Valeur_TMR0 )=> 500 000µS Cpt0=0; Drapeaux.Tmr0_Elapsed=0; PIR3bits.TMR0IF = 0; PIE3bits.TMR0IE=1; // en mode interrupt par defaut T0CON0bits.EN=1; } dans le main Init_Timer0_16b_500mS(); GIE=1; Start_Chronometre(); while(Drapeaux.Tmr0_Elapsed==0) { } ; TMR0IE=0; TMR0IF=0; Stop_Chronometre(); sprintf(txt,"%c%c Test TMR0 mode 16b 500mS , Nb Tics %lu L2=%lu uS%c%c",13,10,L1,L2,13,10); Print(txt);// affiche valeur brute et valeur en µS CRLF1(); CRLF1(); CPrint("\r\n.. fin de test ..\r\n"); while(1); |
![]() |
init variables :
volatile uint16_t Cpt0;
volatile struct Anybits { // 8 flags
unsigned Tmr0_Elapsed:1; // for timer0 16bits
unsigned Tmr1_Elapsed:1; // for timer1 16bits
unsigned Tmr2_Elapsed:1; // for timer2 8bits
unsigned Tmr3_Elapsed:1; // for timer3 16bits
unsigned Tmr4_Elapsed:1; // for timer4 8bits
unsigned Tmr6_Elapsed:1; // for timer6 8bits
unsigned NCO_initialise:1; // for NCO
unsigned Key_ON :1; // detection appui BP
}Drapeaux ;
Init Vecteurs d' Interruptions
void Interrupt_Init(void)
{
INTCON0bits.IPEN = 1;
bool state = (unsigned char) INTCON0bits.GIE;
INTCON0bits.GIEH = 0; // dishigh priority interrupts
INTCON0bits.GIEL = 0; // dis low priority interrupts
INTCON0bits.IPEN = 1; // Enable interrupt priority
IVTLOCK = 0x55;
IVTLOCK = 0xAA;
IVTLOCKbits.IVTLOCKED = 0x00; // unlock IVT
IVTBASEU = 0;
IVTBASEH = 0;
IVTBASEL = 8;
IVTLOCK = 0x55;
IVTLOCK = 0xAA;
IVTLOCKbits.IVTLOCKED = 0x01; // lock IVT
// Assign peripheral interrupt priority vectors
IPR3bits.U1RXIP = 1;
IPR3bits.TMR0IP = 0;
INTCON0bits.GIE= state;
}
Interrupt de traitement TMR0:
void
__interrupt(irq(IRQ_TMR0),high_priority)TMR0_ISR(void)
{
Cpt0++ ; // x 100ms avec MFINTFosc=500Khz
LED_verte=0; // allume led (car tir\0xE9e au +Vcc)
Drapeaux.Tmr0_Elapsed=1;
TMR0H = 0x5E; // 24288
TMR0L = 0xE0;
PIR3bits.TMR0IF = 0;
// T0CON0bits.EN=0; // stope timer0
}
L'init du timer0
void Init_Timer0_16b_500mS()
{
T0CON0=0;
T0CON0bits.EN=0;
T0CON0bits.MD16=1;
//CS[2:0]:Timer0 Clock Source Select bits
//// 010 = FOSC/4
T0CON1bits.CS2=0;
T0CON1bits.CS1=1;
T0CON1bits.CS0=0;
//0= The input to the TMR0 counter is synchronized to FOSC/4
T0CON1bits.ASYNC=0;
// Postscaler=7 =>
1/8
T0CON0bits.OUTPS3=0;
T0CON0bits.OUTPS2=1;
T0CON0bits.OUTPS1=1;
T0CON0bits.OUTPS0=1;
// CKPS[3:0]: Prescaler =4 => Rate Select bit =>
div 1/16
T0CON1bits.CKPS3=0;
T0CON1bits.CKPS2=1;
T0CON1bits.CKPS1=0;
T0CON1bits.CKPS0=0;
TMR0H = 0x5E; // 24288
TMR0L = 0xE0;
// complement=65536-24288=41248 => 0x5EE0
// =MCU_Cycle*Pre_div*( (Post_div-1) *65536 + 65536-Valeur_TMR0
)=> 500 000µS
Cpt0=0;
Drapeaux.Tmr0_Elapsed=0;
PIR3bits.TMR0IF = 0;
PIE3bits.TMR0IE=1; // en mode interrupt par defaut
T0CON0bits.EN=1;
}
dans le main
Init_Timer0_16b_500mS();
GIE=1;
Start_Chronometre();
while(Drapeaux.Tmr0_Elapsed==0)
{
} ;
TMR0IE=0;
TMR0IF=0;
Stop_Chronometre();
sprintf(txt,"%c%c Test TMR0 mode 16b 500mS , Nb Tics %lu L2=%lu
uS%c%c",13,10,L1,L2,13,10);
Print(txt);// affiche valeur brute et valeur en µS
CRLF1();
CRLF1();
CPrint("\r\n.. fin de test ..\r\n");
while(1);
le probleme de base:
Rappel : Postacaler=0 => div 1/1 = usage classique
Attention à
distnguer la valeur du registre POSTSCALER et facteur de Division
de celui ci
MAIS , si le postscaler à la valeur >0, soit
X , après le premier débordement le timer repart à 0 au lieu
de la valeur d'init TMR0,
puisque l'interruption (montée du flag TMR0IF) se produit que
tous les X débordements !
il faut donc revoir le calcul :
global timeout value = 65536 * [ (value f (Postscaler) + (65536 -
TMR0 initial value)] * value f (Prescaler) * MCU Cycle
dans le cas du test ci dessus
Timer Cycle= 0.0625µS .......( because choix clock= FOSC/4=>MCU
Cycle)
Prescaler = 4 =>divide by 16
Postscaler =7 => divide
by 8
TMR0 init= 24288 => décompte de 65536-24288 = 41248
donc
global timeout value= ( (65536-TMR0) + (65536 * (8-1) ) * 16 * 0.0625
Timeout =MCU_Cycle * Pre_div
* [ (Post_div-1) *65536 + 65536-Valeur_TMR0 ] =>
500 000µS
Presentation :
PIC18F27K42 version de test Timer0
Directory :C:\MPLABX_Projects\_18F27K42_Test_Timer0_2023.X
Project : _18F27K42_Test_Timer0_2023
Source : main.c config.c SMT1_Chrono.c,UART1_Function.c_2023-0726
Config Internal Fosc 64MHz
Autres : config.h, Presentation.h, SMT1_chrono.h ,UART1_Functions.h
Eeprom : no Eeprom
RC7=RX UART RC6=TX UART1 RA4=Led rouge
RBxx not used
Compile le Jul 26 2023 \0xE0 13:24:55 UTC
avec version XC8 : 2360
2 leds eteintes (led tirees au +Vcc !)
Init Compteur 24 bits SMT1, avec choix clock 4=> 500KHz tick=2uS
Test Timer0 en mode 16b 500mS (with FOSC/4=16MHz Prescale= 4
Postscaler=7
Led verte activee via interrupt en fin de delay TMR0 !
Resultat TMR0 500mS , Nb Tics 249998 L2=499996 uS
Resultat TMR0 500mS , Nb Tics 5000007 L2=10000014 uS
Apres Cpt0= 20 interrupts TMR0
.. fin de test ..
SOFTWARE:
_18F27K42_Test_Timer0_2023-0726.X.hex
_18F27K42_Test_Timer0_2023-0726.zip
Test Module PWM 10bits à Freq=1KHz (MikroC)
****************************************************************
ATTENTION : ne pas confondre les CCP 1,2,3,4 -> utilisés en
PWM 1,2,3,4
avec les Modules PWM utilisés directement comme PWM 5,6,7,8
********************************************************************************
Duty cyle cde 0 à 1023
usage de TMR2 et PWM5
sortie PWM sur RC2
option: OLED LCD SSD1306 afficheur sur bus I2C1
commande niveau PWM via Potar (ADC EA0)
Pin RC2 PWM output -> MOSFET IRLZ14 ->
Ampoule 12V 5W -- alim externe 12V
pins RC6 (TX) et RC7 (RX) -> cordon Prolific TTL/USB <->
Terminal YAT
voir 18F27K42_All_Datas_Help.xls
...onglet PWM
Hardware :
Timer2 , partie integrante
associée ici , au PWM5 :
void PWM5_Load_Duty_Value(unsigned int
Duty_Value) { PWM5DCH = (Duty_Value & 0x03FF)>>2; // Writing to 8 MSBs of PWM duty cycle in PWMDCH register PWM5DCL = (Duty_Value & 0x0003)<<6; // Writing to 2 LSBs of PWM duty cycle in PWMDCL register } |
d'apres datasheet page 349 :
FOSC=64MHz TOsc = 1/FOSC = 0.015625 µS
Prescaler Timer2 = 6 => diviseur =1/64
T2PR=255
PWM Periode = ( T2PR + 1) *4 * Tosc * TMR2 Prescaler
PWM Periode = (255+1) * 4 * 0,015625 * 64 = 1024 µS
Freq= 1/ T => 1 000 000 / 1024 = 976.5Hz
EQUATION 23-2: PULSE WIDTH
Pulse Width = (CCPRxH:CCPRxL register pair) * Tosc * (TMR2
Prescaler Value)
avec consigne =512
Pulse With (50%) = 512 x 0.015625 * 64 = 512 µS
EQUATION 23-3: DUTY CYCLE RATIO
Duty Cycle Ratio = (CCPRxH:CCPRxL register pair) / 4*( T2PR +1 )
ex ! Duty consigne = 512
Duty = 512 / (4 * 256)= 512/1024= 50 pourcent
signal :
signal PWM5 mesuré : Freq=977 Hz
et NCO1 Freq=10KHz
réactualisé 04/08/2022
Projet
Directory : C:\_MikroC\_MesProjets_MikroC\_18F27K42_TMR2_PWM5_10bits_2022_08
projet : 18F27K42_Base_UART1_RX_IT_ADC0_TMR2_PWM5_10bits_2022_08.mcppi
zippé : _18F27K42_TMR2_PWM5_10bits_2022_0806.zip
Source : \_18F27K42_64Mhz_Uart1_ADC_TMR2_PWM5_10b_2022_0804.c
Chargeur : 18F27K42_Base_UART1_RX_IT_ADC0_TMR2_PWM5_10bits_2022_08.hex
config : P18F47K42_Internal_Fosc_16x4_64MHz.cfgsch
Commandes possibles via le clavier ( liaison terminal YAT 19200bds)
Help menu
Cxxxx -> consigne via
valeur saisie au clavier, avec xxxx variable de de 1 à 1020
'RAMPE' evolution de 0 à 1020
par pas de 16 every 50mS , puis dans le sens contraire
Source Timer via 'Sx' avec x=1
->16Mhz x=2 ->500Khz x=2 ->32Khz
....Freq. correspondantes 977 Hz ..30.86 Hz ...et 1.946 Hz .
'A' -> consigne PWM via
potar sur RA0
cde 'Px' avec x de 1 à 7 pour
Prescaler Timer2 (prescaler initial=6 soit 1/64)
donc avec progression possible du diviseur Prescaler de 1,2,4,8,16,32,64,128
Le choix de Source Frequence pourTimer2 via Sx
+ le choix de Prescaler via Px
permet moult combinaisons de reglage PWM output ...
Rappel : Postscaler NON utilisé pour PWM , mais sortie
postscalée dispo !
mais certaines configurations (avec
Sx et Px ) ne supportent plus la résolution sur 10 bits réels
voir datasheet
Test orientation sortie PWM sur autre Pin via PPS
// test
affectation à RC1 ..OK
// CPrint(" Affectation (PPS) PIN RC1 à Sortie PWM5 \r\n");
// TRISC.B1=0;
// Unlock_IOLOCK() ;
// RC1PPS=0x0D;
// Lock_IOLOCK() ;
// test affectation à RA3 ..OK
// CPrint(" Affectation (PPS) PIN RA3 à Sortie PWM5 \r\n");
// TRISA.B3=0;
// Unlock_IOLOCK() ;
// RA3PPS=0x0D;
// Lock_IOLOCK() ;
VERSION avec module CCP1 utilisé en PWM avec TMR4
rev 06/08/2022
sortie PWM sur RC1 (choix via PPS)
18F27K42_CCP1_2_3_4_en _mode_PWM_Diagram.jpg
FOSC = 64 MHz
FOSC/4 = 16 MHz
TOSC for TMR = 0.0625 µS
T4PR = 255
TMR4 CKPS Prescaler= 64 => codage= 0x60
PW period calcul = Tosc*(T4PR+1)*(TMRx Prescaler value)
PWM period = 1024 µS
soit Freq PWM = 977 Hz
Duty cycle : 0 à 1023 ...
SOFTWARE
Projet : 18F27K42_TMR4_CCP1_PWM_10bits_RC1_2022_0806.zip
Source : _18F27K42_64Mhz_Uart1_ADC_TMR4_CCP1_PWM_2022_0806.c
Chargeur : 18F27K42_Base_64Mhz_UART1_RX_IT_ADC0_Timer4_CCP1_PWM_10b_2022.hex
config : P18F27K42_Fosc_Interne_IVT_interrupts_16x4_PLL_64MHz.cfgsch
rappel : il faut reconfigurer
IVT mode manuellement ! dans le setup project.
VERSION CCP1 utilisé en PWM avec TMR2 (sans
librairie MC)
rev 11/08/2022
sortie PWM sur RC1 (choix via PPS)
Sans l'usage de LA LIBRAIRIE
MIKROC PWM REMAPPABLE
Rajout possibilité de définir la frequence via liaison (UART1)
terminal
cde : Fxxxx calcul des parametres via la fonction :
void Calcul_and_Set_param_Timer2(
unsigned int value) // en Hz
la fonction determine :
la valeur du choix de FOSC 500KHz ou 64MHz
la valeur du prescaler
la valeur de PR2
On peut ainsi avoir un PWM à 50 Hz .. ex: pour servomoteur ..
------------------------------------------------------------------------------------
avec usage de la lib MikroC ....avec
fosc=64MHz:
Impossible pour F< 200Hz
exemple :
une init à 100Hz ne passe pas à la compilation :
PWM1_Remappable_Init(100); // Message 323
Argument is out of range
La lib Mikroc n'accepte que 8 bits
pour l'argument Duty!
--------------------------------------------------------------------------------------
Nota :
à F=1000Hz la commande Duty value C=xxxx plafonne à 1020 pour
100% au lieu de 1023
à F=11025 Hz la commande plafonne à 700 pour 100% au lieu de
1023
Test avec Format Timer2 pour la commande duty :
FMT=1 (aligné à gauche) et FMT=0 (aligné à droite)
en fait c'est bien plus simple et intuitif en mode FMT=0
le resultat obtenu étant le meme avec FMT=1....
rev 11/08/2022
Projet : 18F27K42_TMR2_CCP1_PWM_10bits_RC1_2022_0810.zip
Source : _18F27K42_test_UART_IVT_CTS_CCP1_PWM_Timer2_2022_0810.c
Chargeur : 18F27K42_Base_64Mhz_UART1_RX_IT_ADC0_Timer2_CCP1_PWM_10b_2022-0810.hex
config : P18F27K42_Fosc_Interne_IVT_interrupts_16x4_PLL_64MHz.cfgsch
rappel : il faut reconfigurer
IVT mode manuellement ! dans le setup project.
Test
PWM Timer2 + CCP1 , pour géneration signal SINUSOIDAL
d'apres la base départ :
9th Jun 2011 - Open Source - www.RomanBlack.com
Test du PWM Timer2 , en usage classique ... PWM F=1000Hz
Puis usage du Timer2 en mode libre , calé à 20µS
Nota : alim MCU 3,3V seulement ...
CPrint(" Test new init Timer2 \r\n");
TMR2IF_bit = 0; // Clear Interrupt flag
T2CLKCON = 0x01; // FOSC/4; soit 64/4=16MHz.
// T2CLKCON = 0x05; // (500 kHz internal oscillator)
cycle= 0.0625; // =1/16Mhz
T2HLT = 0x80; // synchro sur Fosc/4 et Free mode =0000
T2RST = 0x04; //T2RSEL=0x04 => reset by CCP1OUT;
T2TMR = 0x00; // TMR2= 0;
// pour 20µS
T2CON = (0x02<<4) | 0x00 ; // Prescaler=2=>
1/4 Postscaler=0=> 1/1
// pour 60µS
// T2CON = (0x02<<4) | 0x02 ; // Prescaler=2=> 1/4
Postscaler=2=> 1/3
// Pour 200µS
// T2CON = (0x02<<4) | 0x09 ; // Prescaler=2=> 1/4
Postscaler=9=> 1/10
T2PR = (80-1); // PR2 set to total PWM period of 80 ticks
TMR2ON_bit=1;
Au rithme du tour de cycle Timer2, la table de 50 valeur de sinus
( * amplitude =120)
correspondant à une sinusoide entiere , est explorée , et
ressort la valeur lue servant à la commande Duty du PWM
On a donc une frequence de T= 20µS*50=1000µS => soit 1Khz..
inutilisable telle quelle !
Un filtre passe bas est indispensable :
haute impedance d'entrée et faible impedance de sortie , permet
de recupérér ce signal sinusoidal.
amplitude de 800mV cr cr . avec Vdd=3,3V
Nota : avec le POSTscaler on peut modifier la frequence dans un
rapport de 1 à 16 !
Le POSTscaler ne modifie pas la frequence du PWM :
50Khz
Un filtre actif serait plus efficace qu'un filtre RC molasson ,
et permettrait un niveau de récuperer un niveau de tension sinus
plus élévé.
On enleve quand meme tous les niveaux d'harmoniques impaires au
signal présent à l'entrée ..
je n'ai pas essayé avec une frequ .PWM plus faible .. avec des
echelons plus larges dans la sinusoide..
exemple:
T2CON = (0x02<<4) | 0x02 ; // Pescaler=2=> 1/4 Postscaler=2=>
1/3 TMR2IF every 60µS Freq PWM=50Khz sinus=334
Hz
Software:
_18F27K42_PWM_Sinus_1KHz_2022-0823.zip
_18F27K42_FOSC_64Mhz_PWM_to_Sine1kHz_2022_0823.c
18F27K42_FOSC_interne_64MHz_PWM_to_Sine1kHz_2022_0823.hex
voir aussi :
Variante avec CCP1 Timer2
en mode 8 bits ( Librairie MC ) ou avec fonction speciale pour
PWM 10 bits
MCU : 18F27K42
Power supply: 5V
Directory : C:\_MikroC\_MesProjets_MikroC\_18F27K42_PWM
Projet : 18F27K42_UART1_RX_IT_ADC0_PWM1_8b_10b_Base_2022_08.mcppi
Source : _18F27K42_32Mhz_Uart1_ADC_PWM_8b_ou_10b__2022_0812.c
CONFIG : P18F27K42_FOSC_Q8MHzx4_32MHz.cfgsch
FOSC : 32MHz
Clock initiale in Khz = 32000
Commandes via Keyboard Terminal :
Cxxx pour saisie Valeur xxxx Duty PWM via le Clavier
A pour Valeur Duty PWM issue du Potar /RA1 Analogique
P1 pour mode PWM 10bits , P0 pour mode PWM 8 bits
RAMPE pour rampe Up , puis Rampe Down
Help : cette aide
Usage de la Librairie MikroC
Affectation (PPS) PIN RC2 à Sortie PWM1
Init PWM1 8bits at 1000Hz on RC2
Mesure # 9 Reglage Duty via ADC/ RA1 =>
1028 Mode PWM 8 bits IRatio =0064
P1
Mesure # 10 Reglage Duty via ADC/ RA1 => 1028 Mode PWM 8 bits
IRatio =0064
Recept UART1= P1
Mesure # 11 Reglage Duty via ADC/ RA1 => 1027 Mode PWM 10 bits
IRatio =0256
Mesure # 12 Reglage Duty via ADC/ RA1 => 1029 Mode PWM 10 bits
IRatio =0257
C512
Mesure # 15 Reglage Duty via ADC/ RA1 => 1028 Mode PWM 10 bits
IRatio =0257
Recept UART1= C512
PWM mode= 10 bits New IRatio = 512
Mesure # 16 Reglage via cde Clavier Cxxxx Mode PWM 10 bits IRatio=
512
Mesure # 44 Reglage Duty via ADC/ RA1 => 3986 Mode PWM 10 bits
IRatio =0996
P0
Mesure # 45 Reglage Duty via ADC/ RA1 => 3989 Mode PWM 10 bits
IRatio =0997
Recept UART1= P0
Mesure # 46 Reglage Duty via ADC/ RA1 => 3984 Mode PWM 8 bits
IRatio =0249
la fonction commande PWM 10bits :
void PWM1_Set_10b_Duty(unsigned
int R)
{
CCP1CON.B4=0; // FMT=0 cadrage à droite
CCPR1H =R>>8;
CCPR1L= R & 0x00FF;
}
Questionnement
sur le fait que j'atteins 100% PWM ( observé à l'oscilloscope)
pour une consigne 10 bits PWM = 999 et non pas 1023 ?
Nota : en mode 8 bits j'ai quasiment 99% à consigne 8 bits =255
Software :
Projet zippé: _18F27K42_32Mhz_Uart1_ADC_PWM_8b_ou_10b_2022_0812.zip
Source : _18F27K42_32Mhz_Uart1_ADC_PWM_8b_ou_10b_2022_0812.c
Chargeur :
18F27K42_UART1_RX_IT_ADC0_PWM1_8b_10b_Base_2022_08.hex
*PWM
8 bits à 5KHz avec 18F47K42
(Dip40)
*PWM 8 bits 1Khz (Fosc =Q10Mhz x
4)
*PWM 8 bits 11025 Hz (Fosc interne =16
x 4=64Mhz)
Test interruptions IOC ( sur changement d'etat
entrées) 18F27K42 MPLAB XC8
voir application Chaudiere : usage de 8 switches , dont 6
regroupés sur RB0 ... gestion interrupt INT0
18F27K42_test_INT0_IOCBF_6BP_Uart1_AVEC_IVT_2023-08.zip
// avec IVT interrupt
exemple usage
PIC18F27K42 + Test interrupt INT0 sur 6 BP portB Directory :C:\MPLABX_Projects\18F27K42_test_INT0_IOCBF_6BP_Uart1_2023-08 Compile le Aug 21 2023 a 09:49:44 UTC avec version XC8 : 2360 Test SMT1 avec delay 100mS , Nb Tics 49997 L2=99994 uS ... avec IVT interrupt Etats_BP : SW0 =0X01 duree k= 3529 via SMT1 L2=357 mS Etats_BP : SW1 =0X02 duree k= 886 via SMT1 L2=89 mS Etats_BP : SW2 =0X04 duree k= 2822 via SMT1 L2=285 mS Etats_BP : SW3 =0X08 duree k= 3098 via SMT1 L2=313 mS Etats_BP : SW4 =0X10 duree k= 0 via SMT1 L2=284 mS Etats_BP : SW5 =0X20 duree k= 2398 via SMT1 L2=242 mS Etats_BP : SW1 SW2 =0X06 duree k= 6560 via SMT1 L2=663 mS Etats_BP : SW1 SW3 =0X0A duree k= 4274 via SMT1 L2=432 mS Etats_BP : SW2 SW3 =0X0C duree k= 5074 via SMT1 L2=513 mS
Characteres speciaux LCD const unsigned char LCD_Custom_Chars[] = { //---------- set #1 ------------------ 0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00, //char #1 Degrée 0x06,0x09,0x08,0x1E,0x1E,0x08,0x09,0x06, //char #2 euro 0x04,0x0A,0x11,0x11,0x0A,0x0A,0x11,0x00, // char #3 Ohm 4,14,14,14,31,0,4,0, // char #4 bell //0x10,0x18,0x1C,0x1E,0x1C,0x18,0x10,0x00, //char #5 A droite 28,20,27,18,19,18,18,0 , //char #5 initiales PF 0x01,0x03,0x07,0x0F,0x07,0x03,0x01,0x00, //char #6 A gauche 0x00,0x11,0x0A,0x04,0x06,0x11,0x00,0x00, //char #7 cancel 0x00,0x01,0x03,0x16,0x1C,0x10,0x00,0x00, //char #8 Checked //----- set #2 0 à 6 colonnes Barre horizontale ------- 0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000, 0b01000000,0b01000000,0b01000000,0b01000000,0b01000000,0b01000000,0b01000000,0b01000000, 0b01100000,0b01100000,0b01100000,0b01100000,0b01100000,0b01100000,0b01100000,0b01100000, 0b01110000,0b01110000,0b01110000,0b01110000,0b01110000,0b01110000,0b01110000,0b01110000, 0b01111000,0b01111000,0b01111000,0b01111000,0b01111000,0b01111000,0b01111000,0b01111000, 0b01111100,0b01111100,0b01111100,0b01111100,0b01111100,0b01111100,0b01111100,0b01111100, 0b01111110,0b01111110,0b01111110,0b01111110,0b01111110,0b01111110,0b01111110,0b01111110, 0b01111111,0b01111111,0b01111111,0b01111111,0b01111111,0b01111111,0b01111111,0b01111111, //---- #set #3 Barre verticales ------------------ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,31, 0,0,0,0,0,31,31, 0,0,0,0,0,31,31,31, 0,0,0,0,31,31,31,31, 0,0,0,31,31,31,31,31, 0,0,31,31,31,31,31,31, 0,31,31,31,31,31,31,31 };
Character Generator RAM (CGRAM)
In the character generator RAM, the user can rewrite character
patterns by program.
For 5 x 8 dots, eight\par character patterns can be written,
and for 5 x10 dots, four character patterns can be written.
Rappel :
RS=0 => Cde
RS=1 => Data