V.O 21/02/2019
rev 20/04/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:

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

schema avec diptrace: Base_18F27K42_rev_190226.wh5


Montage

images/t_Base_Test_18F27K42_190225.gif

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

images/t_Base_18F27K42_Tests_190227b.gif

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)


images/t_Proto_18F27K42_LCD_4x20_I2C1_Hardw_UART1_ADC1_2020_0803.gif




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






TEST Ruban 60Leds RGB WS2812E

reference fournisseur ruban

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 ..

images/t_WS2812E_Problemo_2021-0920.gif
Leds RGB H.S. ! docu fournisseur .. ce n'est pas le modele E


une explication sur cette problematique :



Montage de test sur Base 18F27K42

images/t_Test_morceau_ruban_led_WS2812E_2021-0920.gif

 

Help
Mode=1 couleur à chaque Minute
Mode=2 couleur alterné chaque seconde
N=xx 8, 10 ou 60 leds max

Directory :C:\_MikroC\_MesProjets_MikroC\Test_ruban_WS2812x_WS2815_18F27K42_2024
MikroC pro 7.60
Projet :PIC18F27K42_Test_Ruban_60_Leds_RGB_WS2812x_WS2815_2024.mcppi
Hardware : Ruban WS2812E destroyed!
New ruban 60 leds 1M WS2816
Config bit : P18F27K42_Fosc_Interne_64Mhz.cfgsch
FOSC:64.0 MHz
Source : Test_Ruban_60_WS2812x_WS2815_18F27K42_2024-0420.c
BASE 18F27K42 UART1
Cde Led Dout = sortie RC5 -> Leds
Attention :
Couleur Ruban WS2815 en GBR .. WS2182 en GRB

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
1 RAZ All leds
2 RAZ All leds
3 RAZ All leds
4 RAZ All leds
5 RAZ All leds
6 RAZ All leds
7 RAZ All leds
8 RAZ All leds
9 RAZ All leds
0 RAZ All leds

Proto et affichage Help

introduction


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 (dout = RC5)
*meme programme 18F27K42 que ci-dessus!

images/t_TEST_3_types_deRGB_leds_2021-1025.gif images/t_Bande_lumineuse_RGB_LED_IP65_1M_60leds_WS2815.gif images/t_LED-RGB_WS2812B_5050_DC5V.gif
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,
vert: 1500-2500mcd,
bleu: 150-400mcd .

36 mois

GRB

WS2815 ECO

Fils de liaison en alliage de 10 pièces

Rouge: 200-350mcd,
vert: 1100-1400mcd,
bleu: 150-300mcd

18 mois

RGB


en regardant à la loupe, la led , j'ai bien une WS2815 "or"

images/WS2812B_mesures.jpg
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

images/t_NCO1_Freq_Diagram.gif

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 :

images/t_Clock_Reference_for_NCO1.gif bit 3-0 CKS[3:0]: NCO1 Clock Source Select bits
1111 = Reserved

1011 = Reserved
1010 = CLC4_out
1001 = CLC3_out
1000 = CLC2_out
0111 = CLC1_out
0110 = CLKREF_out
0101 = SOSC
0100 = MFINTOSC/4 (31.25 kHz)
0011 = MFINTOSC (500 kHz)
0010 = LFINTOSC (31 khz)
0001 = HFINTOSC
0000 = FOSC
 
detail sources Clock pour NCO1 registre choix de clock  

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 :

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

images/t_YAT_terminal_config_touches_2021-0613.gif
  detail config touches commandes terminal 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,0x
FE,0xFD,0xFC,0xFB,0xFA

avec notetab++
Recherche ... Remplacer...... Remplacer
db par \r\n, ( espace dB par CR LF et virgule)

images/t_RTTL_ASM_C.gif

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 :
images/t_Config_64MHz_ClckoutEnabled.gif

images/t_FOSC_Diagram_18F27K42.gif
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
images/PPS_lib.jpg

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

images/t_Device_PCF8574_found.gif images/PCF8574_Adresse_Hardware.jpg

Analyse bus I2C: presence Ack = presence device

modif adresse de base PCF8574


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);
images/t_18F27K42_TMR0_diagram.gif


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 :

images/t_Test_PWM5_18F27K42.gif

Timer2 , partie integrante associée ici , au PWM5 :

images/t_TMR2_18F27K42_interrupt.gif images/t_Simplified_PWM_Block_5_6_7_8_Diagram_18F27K42.gif


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 :
images/t_SQA_Anlayser_PWM5_NCO1_18F27K42.gif
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

images/t_18F27K42_CCP1_2_3_4_en _mode_PWM_Diagram.gif

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..

images/t_Filtre_pass_bas_1000Hz_PWM_50pct.gif images/t_PWM_Timer2_CCP1_to_Sinus_1Khz_2022-0823.gif
filtre passe bas et signal PWM avec duty fixe=50% signal en sortie de filtre et charge de 2,2K

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








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




















../common/GIF/LTC1286p.jpg

retour à l'index