version   15/05/2025
rev 25/05/2025


Test MCP23017 avec PIC 18F27K42

ce test est en rapport avec le sujet : commande de Portail , sur Fantaspic

Hardware :
MCP23017 configuration
Prototype complet
Test INTB MCP23017
Chronometrage de chaque changement d'etat port MB
Test ecriture sur port MA MCP23017 + clignotement





Hardware :

Alimentation VCC= 5V
Carte Base 18F27K42
Led sur RA4 ..PIC18F
Fosc interne 64Mhz
MCP23017 sur breadboard
2 BP N.O. sur entree MB1 pin2 et MB34 pin 4
UART1 115200bds TX sur RC6, RX sur RC7
1 led sur MA4 pin 25
YAT terminal sur PC
Prolific TTL/USB cable
Pickit4 programmer

MCP23017 expander 16 I/O sur bus I2C




Prototype de test sur breadboard
Schema partie MCP


Adresse I2C1 7 bits : 0x22


Prototype complet :

images3/t_Prototype_PORTAIL_photo_2025-0524.gif




PIC Config via MCC :





MCP23017 Configuration
attention:
notation PortB pour le port B du PIC18F , mais MB pour le portB du MCP23017
Le MCP23017 est piloté en I2C à l'adresse (7bits) 0x22 ( pins adresses : A0=0,A1=1,A2=0)
Le port MB est configuré en (8) entrées
Le port MA en (8)sorties
Un changement d'etat sur le PORT MB genere une interruption via lla sortie INT B du MCP.


Registres du MCP23017 :
/TABLE 1-6: CONTROL REGISTER SUMMARY (IOCON.BANK = 0)
// page 11
#define MCP23017_ADDR 0x22 // adresse 7 bits ! (A0=0 A1=1 A2=0 )
#define MCP_IODIRA 0x00
#define MCP_IODIRB 0x01
#define MCP_IPOLA 0x02
#define MCP_IPOLB 0x03
#define MCP_GPINTENA 0x04
#define MCP_GPINTENB 0x05
#define MCP_DEFVALA 0x06
#define MCP_DEFVALB 0x07
#define MCP_INTCONA 0x08
#define MCP_INTCONB 0x09
#define MCP_IOCONA 0x0A
#define MCP_IOCONB 0x0B
#define MCP_GPPUA 0x0C
#define MCP_GPPUB 0x0D
#define MCP_INTFA 0x0E
#define MCP_INTFB 0x0F
#define MCP_INTCAPA 0X10
#define MCP_INTCAPB 0x11
#define MCP_GPIOA 0x12
#define MCP_GPIOB 0x13
#define MCP_OLATA 0x14
#define MCP_OLATB 0x15

Datasheet MCP23017_features_01043a.pdf


// --- Init MCP23017 pour interruptions sur PORT MB
void MCP23017_Init(void) {
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_IODIRB, 0xFF); // IODIRB = 0xFF (entrée)
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_GPINTENB, 0xFF); // Interrupt-on-change
I2C1_Write1ByteRegister(MCP23017_ADDR,MCP_DEFVALB,0xFF);
I2C1_Write1ByteRegister(MCP23017_ADDR,MCP_GPPUB,0xFF);
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_INTCONB, 0x00); // Comparaison avec l'état précédent
//I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_INTCONB, 0xFF); // Comparaison avec l'étatDEFVALB
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_IOCONB,0x44); // Bank=0 INTB active low, open-drain
}

INTB MCP23017 relié à pin B1 du Port B PIC18F27K42
armement interruptions coté PIC
void __interrupt(irq(IRQ_IOC),high_priority) IOC_ISR(void)
{
unsigned char i;
const char *p2="ALERT\r\n";
if ( (IOCCF & 0x01)==1) // RC0
{
Led_Rouge=0; // allume led
k1_PWM=0;
k2_PWM=0;
PWM1_LoadDutyValue(k1_PWM); // plus de cde PWM sur le PONT H
PWM2_LoadDutyValue(k2_PWM);
IOCCF = 0x00;
}

if ((IOCBF & 0x02)==2) // RB1 <-INTB du MCP23017
{
mcp_timestamp = SMT1_GetTimeUs(); // Lecture "temps réel" dans l'ISR
mcp_flag = true;
IOCBF = 0x00;
}
}

* le traitement RC0 a un lien avec le traitement Surcharge Amperes du capteur INA229
On memorise le chrono (SMT1) en cours à l' instant de l'interrupt INTB



Test du flag Interruption MCP23017 INTB
par interruption IOCB pin B1 du PIC18F

if (mcp_flag)
{
IT_Flag=I2C1_Read1ByteRegister(MCP23017_ADDR,MCP_INTFB);
CAPB=I2C1_Read1ByteRegister(MCP23017_ADDR,MCP_INTCAPB);
MCP_B = MCP23017_ReadGPIOB();
sprintf(CRam1," %lu.%lu mS IT_Flag = 0x%02X CAPB= 0x%02X",mcp_timestamp/1000,mcp_timestamp%1000, IT_Flag ,CAPB); // ok
Print(CRam1);
CRLF1();
mcp_flag = false;
}
le test INTB est OK !
le compteur SMT1 24 bits sert à chronometrer, certains évenements ou parties de codes.

exemple capture d'appui sur les Switches BP 2 et 4:
(0.640) N= 19 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600
(0.590) 6453.495 mS
IT_Flag = 0x00 CAPB= 0x02
(0.065) N= 20 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600
(0.136) 6535.074 mS
IT_Flag = 0x00 CAPB= 0x02
(0.521) N= 21 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600
(0.649) N= 22 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600
(0.144) 7133.053 mS
IT_Flag = 0x00 CAPB= 0x08
(0.000) 7212.565 mS IT_Flag = 0x00 CAPB= 0x08
(0.522) N= 23 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600

nota : on recupere quelle est la PIN MCP qui a générer l'interrupt et quel éait l'etat du port MB à cet instant

Problemes rencontrés :

Probleme sur Affichage des valeurs IT_Flag et CAPB issues de la capture du flag INTB MC23017
OK avec
sprintf(CRam1," %lu.%03d mS IT_Flag = 0x%02X CAPB= 0x%02X",mcp_timestamp/1000,mcp_timestamp%1000,IT_Flag,CAPB);
CAPB est bien vu à 0x02

(13:42:08.922) N= 21 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600 MCP_B = 0xFF
(13:42:09.561) N= 22 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600 MCP_B = 0xFF
(13:42:10.213) N= 23 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600 7231.436 mS IT_Flag = 0x00 CAPB= 0x02
(13:42:10.860) N= 24 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600 MCP_B = 0xFF

MAIS bad avec
sprintf(CRam1," %lu.%03d mS CAPB= 0x%02X",mcp_timestamp/1000,mcp_timestamp%1000,CAPB); // bad
CAPB est vu à 0x00 au lieu de 0x02

(13:45:07.669) N= 41 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600 MCP_B = 0xFD
(13:45:08.320) N= 42 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600 13507.815 mS CAPB= 0x00
(13:45:08.964) N= 43 PWM1= 0 PWM2= 0 4.99 V 0.001 A . Seuil=0.600 MCP_B = 0xFF

En fait le vrai probleme est en amont, sur l'affichage de mcp_timestamp, valeur unsigned long 32 bits..
et le resultat de mcp_timestamp%1000 que j'avais considré comme un int , puisque toujours inferieur à 1000 !
mais comme mcp_timestamp est un uL , le formattage devait etre perturbé, par 1 seule valeur 8 bits suivante..
alord que dans le test plus haut , j'ajoutait 2 valeurs 8 bits =16 bits ..bref , la cause exacte est enfouie dans le compilo !
Remede :
Caster le resulat de Mcp_timestamp%1000 en un unsigned Long
sprintf(CRam1," %lu.%lu mS CAPB= 0x%02X",mcp_timestamp/1000,mcp_timestamp%1000,CAPB);
OK !

Probleme majeur :
impossibilite de lire la valeur du port MB via l'interruption IOCB1
car l'I2C1 n'est pas ré-entrant. On ne peut lire le port MCP23017 QUE dans le MAIN ...
il s'ensuit un décalage temporel lié à la durée de la boucle principale , seule la datation de l'évenement
est temps réel ..mais pas le traitement ,qui sera Asynchrone, en retard , par rapport à l'évenement.
un peu de lectrure sur 5.1.2.1 Reentrancy - onlinedocs.microchip.com
Contre mesure :
multiplier l'occurence du test du flag dans le main program ...mais il faudrait AUSSI multiplier l'action lié
à l'evenement => donc INTB inutile, uniquement lire le MCP en pooling dans la boucle main..
sauf à l'utiliser directement pour une réaction au niveau Hardware ...
ou pour verifier un sequencement temporel ...
Diminuer tous les temps morts de la boucle principale ..

Les Evenements critiques ne doivent donc pas etre concernés par un resultat
de fonction NON réentrante ou récurssive.
Nota :
L'interrupt RC0 est OK, car c'est la sortie hardware du INA226 qui l'envoie et que le traitement n' a pas de lien avec
la lecture I2C de l'INA226 ....


Le code lié à ce test comporte aussi :
*la gestion d'un LCD 4x20 cars sur I2C1 ,
* module ITB2 driver de puissace pour moteur DC ( ici en 12V) ,piloté par 2 sortie PWM1 et PWM2 du PIC
* module de mesure Courant (et tension) moteur INA226 piloté via I2C1, avec sortie ALERT sur RC0 du PIC18F
(utilise un shunt 15Amp 150mv soit 0,01 ohm)
ALERT message à 0,6Amps (testé en frainant le rotor) => actions : arret par Enable=0 et Cdes PWM à zero.
* Liaison UART permettant de regler plusieurs valeurs de PWM1=xxxx et PWM2, et faire la commande M/A moteur: MA=1 ou MA=0
Affiche aussi Umoteur,I moteur ,PWM1,PWM2 ,et l'etat MCP23017
*gestion du chronometre utilisant le compteur SMT1 24 bits à +-1µS.

Init_I2C() 100Khz;
Test presence devices sur Bus I2C1
@ decimal # 68 soit @Device 7bits =
0X22 MCP23017 2 ports 8bits
@ decimal # 78 soit @Device 7bits = 0X27 PCF8754 for LCD 2x16cars
@ decimal # 128 soit @Device 7bits = 0X40 INA226 Current sensor


exemple d'affichage sur YAT terminal

(0.580) N= 40 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
(0.581) N= 41 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
(0.579) N= 42 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
(0.580) N= 43 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
(0.152)
12605.143 mS CAPB= 0xFD IT_Flag = 0x02
(0.063) N= 44 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
(0.161)
12718.454 mS CAPB= 0xFF IT_Flag = 0x02
(0.052) N= 45 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
(0.554) N= 46 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
(0.581) N= 47 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
..............
(0.135) MA=1
(0.423)
Recu :MA=1
(0.060) ITB2 Enabled
(0.000) N= 94 PWM1= 500 PWM2= 0 0.00 V -0.001 A . Seuil=0.600

(0.582) N= 122 PWM1= 500
PWM2= 0 5.34 V 0.034 A . Seuil=0.600
(0.581) N= 123 PWM1= 500 PWM2= 0 5.34 V 0.032 A . Seuil=0.600
(0.582) N= 124 PWM1= 500 PWM2= 0 5.34 V 0.033 A . Seuil=0.600
(0.581) N= 125 PWM1= 500 PWM2= 0 5.34 V 0.033 A . Seuil=0.600
(0.232) PWM1=1000
(0.326)
Recu :PWM1=1000
(0.009) Saisie OK PWM1-RC2 1000 98.0%
(0.051) N= 126 PWM1= 1000 PWM2= 0 5.34 V 0.034 A . Seuil=0.600
(0.585) N= 127 PWM1= 1000 PWM2= 0 5.30 V 0.070 A . Seuil=0.600
(0.579) N= 128 PWM1= 1000 PWM2= 0 5.29 V 0.082 A . Seuil=0.600
(0.581) N= 129 PWM1= 1000 PWM2= 0
5.24 V 0.139 A . Seuil=0.600
.......
(0.583) N= 149 PWM1= 1000 PWM2= 0 12.17 V 0.085 A . Seuil=0.600
(0.583) N= 150 PWM1= 1000 PWM2= 0 12.08 V 0.160 A . Seuil=0.600
(0.583) N= 151 PWM1= 1000 PWM2= 0
12.00 V 0.531 A . Seuil=0.600
...freinage moteur
(0.258)
ALERT
(0.324) N= 152 PWM1= 0PWM2= 0 0.00 V -0.001 A . Seuil=0.600


1ere valeur entre parenthese = durée boucle principale ~ 580mS

Lancement du programme :

Presentation :
BASE 18F27K42 + LCD4X20+ PWM1,2,3,4 Analog RA0,1,2,3
Directory :C:\MPLABX_Projects\18F27K42_PMW_CCP1234_2025
Project : 18F27K42_PMW_CCP1234_2025
Source : main.c , rev :_250512
Config Internal Fosc 64MHz
Autres :
LCD_4bits_I2C_2025-05, UART1_Functions.h , mcc.h,
A inclure:
Dialogue_Operateur_PC_via_UART_2023-0905

LCD_chars_Speciaux_2024.h, Eeprom : Eeprom...........
Hardware : BASE 18F27K42, I2C1: LCD4x20,INA226,IBT 2 Mosfet,MCP23017 + UART1
Schema: Carte_Portail_2_Vantaux_24v_H-en-MOSFET_INA226-HIP4082_FQP30N06L_V5.0.3.pdf by H.T.


Compiled May 12 2025 at 11:58:09 UTC version XC8 :2360

Init_I2C() 100Khz;
Test presence devices sur Bus I2C1
@ decimal # 68 soit @Device 7bits =
0X22 MCP23017 2 ports 8bits
@ decimal # 78 soit @Device 7bits = 0X27 PCF8754 for LCD 2x16cars
@ decimal # 128 soit @Device 7bits = 0X40 INA226 Current sensor



version Prototype : LCD Bleu a l'adresse 0x27 !
adresse LCD= 39 soit 0X27

Sequence d'Init LCD 4x20 via I2C1 PCF8574
.123456789A
Initialisation PWM1,2 avec FReq 3,9KHz (Timer2)

* PWM1 sur RC2 (TMR2)=0%
* PWM2 sur RC1 (TMR2)=0%

Init INA226 mesure de courant via I2C, shunt de 150mV pou 15Amps
Config INA226_CONF_REG,0x43FF (was 0x4127 )
Calibration register 05h (pour shunt 0,01 ohm et 8 Amps)
Mask/Alert MASK_EN_REG register 06h <- 0x8001
Alert MASK_EN_REG register 07h <- 2400 pour 0.6 A
Mesure de courant 0 mA
Seuil d'alerte 0.600 Amperes
INA Manufactuer 0x5449
INA Identifiant 0x2260
Fin de parametrage INA226... OK

Init MCP23017
Test differentes valeurs de Duty-cycle via le clavier terminal YAT
Activer la sortie PWMy avec MA=1 (arret via MA=0)
Entrer une valeur PWMy=xxxx puis <enter> avec y=1 ou 2 au clavier
Init SMT1 compteur 24b

Test chrono avec TMR6 x 10 boucles
Init TRM6 100mS
.......... SMT1 Nb Tics 1000102

Fin tempo de 1 sec via TMR6

N= 0 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600
N= 1 PWM1= 0 PWM2= 0 0.00 V -0.001 A . Seuil=0.600




Chronometrage avec SMT1 compteur 24 bits

Chronometrage_via_SMT1.inc

Exemple
txt=&TEXTE[0];
CPrint("\r\n Test chrono avec TMR6 x 10 boucles\r\n");
CPrint(" Init TRM6 100mS\r\n");
TMR6_Init_100ms();
Start_Chrono();
do
{
PrintChar('.');
__delay_ms(25);
}
while(Cpt6<10);
Stop_Chrono(1);


Resultat :
Test chrono avec TMR6 x 10 boucles
Init TRM6 100mS
..................................... SMT1 Nb Tics 1025230 uS
Fin tempo de 1 sec via TMR6


nota : +2,5mS ! mesuré sur tempo 1sec
mais avec modif OSCTUNE=0x10
nouvelle essai donne
Test chrono avec TMR6 x 10 boucles
Init TRM6 100mS
........................................ SMT1 Nb Tics 1000336 uS
Fin tempo de 1 sec via TMR6


Les valeurs réelles obtenues pour les tempo , dependent de FOSC interne 64MHz qui peut etre ajustée de +- 3%
surement meilleur avec un oscillateur à QUARTZ !

rev : 15/05/2025
MPLAB IDE 6.0 et XC8
Directory: C:\MPLABX_Projects\18F27K42_PMW_CCP1234_2025
Project : 18F27K42_PMW_CCP1234_2025-0512.X.zip
main : main_18F27K42_MCP23017_0512.X.c
Chargeur :
18F27K42_PMW_CCP1234_2025-0512.X.hex




Test Ecriture sur port MA MCP23017

Hardware Init
3 leds tirées au Gnd sur PORTA Pin 21,22,23

//Mask pour MCP_OLATA
#define Flash 1
#define Sirene 2
#define Buzzer 4
volatile int Clignote=0;
// pour test des sorties MCP_A avec terminal
volatile uint8_t Flash_Out=0;
volatile uint8_t Sirene_Out=0;
volatile uint8_t Buzzer_Out=0;
// variable de travail, pour stockage valeurs registres MCP
volatile uint8_t MCP_A=0;
volatile uint8_t MCP_B=0;
volatile uint8_t IT_Flag;
volatile uint8_t CAPB;
volatile bool mcp_flag = false;

Fonctions MCP23017 :
uint8_t MCP23017_ReadGPIOB(void);
void new_MCP23017_Init(void);
void MCP23017_Write_Register(uint8_t registre, uint8_t donnee);
void MCP23017_SetBits_PORTA(uint8_t mask, uint8_t state);

Initialisation du MCP23017_Init(void)
void MCP23017_Init (void) {
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_IODIRA, 0x00); // IODIRA = 0x00 (Sorties)
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_OLATA, 0x07); //leds tirées au + sur 0,1,2 outputs
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_IODIRB, 0xFF); // IODIRB = 0xFF (entrée)
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_GPINTENB, 0xFF); // Interrupt-on-change
I2C1_Write1ByteRegister(MCP23017_ADDR,MCP_DEFVALB,0xFF);
I2C1_Write1ByteRegister(MCP23017_ADDR,MCP_GPPUB,0xFF);
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_INTCONB, 0x00); // Comparaison avec l'état précédent
//I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_INTCONB, 0xFF); // Comparaison avec l'étatDEFVALB
I2C1_Write1ByteRegister(MCP23017_ADDR, MCP_IOCONB,0x44); // Bank=0 INTB active low, open-drain
}


Lecture du PORTB du MCP23017
uint8_t MCP23017_ReadGPIOB(void) {
uint8_t value;
value = I2C1_Read1ByteRegister(MCP23017_ADDR, MCP_GPIOB);
return value;
}


Ecriture sur MCP23017
void MCP23017_Write_Register(uint8_t registre, uint8_t donnee)
{
I2C1_Write1ByteRegister(MCP23017_ADDR, registre,donnee);
}


Ecriture sur 1 ou plusieurs bits du port MA MCP23017
void MCP23017_SetBits_PORTA(uint8_t mask, uint8_t state)
{
uint8_t Etat_EnCours = I2C1_Read1ByteRegister(MCP23017_ADDR, MCP_GPIOA);
uint8_t Nouvel_Etat=0;
if (state) {
Nouvel_Etat= Etat_EnCours | mask; // Mise à 1 des bits spécifiés par le masque
} else {
Nouvel_Etat= Etat_EnCours & ~mask; // Mise à 0 des bits spécifiés par le masque
}
MCP23017_Write_Register(MCP_OLATA, Nouvel_Etat);
}


exemple de Commande d'une sortie MCP MA
// test sortie "Flash" sur Port MA MCP23017



la variable Clignote regroupe les flags de clignotement correspondants au bits à 1 du port de sortie.
si la sortie est à 1 , et que le Flag est est à 1 => celle ci clignote
au rythme de la duree de boucle principale ..avec test Nb_Boucles pair
( on pourrait aussi utiliser TMR6 et Bit500mS)
On peut ainsi faire clignoter une ou plusieurs sorties..

A chaque tour de boucle, s'affiche sur le terminal ,
exmple:
N= 123 PWM1= 750 PWM2= 0 14.19 V 0.057 A . Seuil=0.600 Flash Buz* MA=0x05 MB=0xFF

le N° de boucle, la consigne PWM1 et PWM2, la tension Moteur, le courant moteur, le seuil d'alerte,
sortie Fla ,Sir,Buz sir à l'etat ON , plus le caractere * si elle clignote , la valeur du port de sortie MA, et du port d'entree MB
La frequence du clignotement est issue de la duree de la boucle principale, ici <600mS
La mesure INA , le rafraichissement des cdes PWM se fait aussi à chaque tour de boucle..

Affichage terminal YAT



Fichier de configuration Terminal :
Terminal_MCP23017_test_2025-0520.yacp

Modif dialogue Operateur
Dialogue_UART_MCP23017_2025-0520.inc
rajout possibilité de modifier le seuil ALERT INA226


if ( (*(p0)=='S') && (*(p0+1)=='L') && ( *(p0+2)=='=') & ( *(p0+3)=='0') & ( *(p0+4)=='.') )
{
cx=*(p0+5);
if ( (cx>'0') & (cx<'9'))
{
CPrint(" Nouveau Seuil=0.");
PrintChar(cx);
cx=cx-48;

// Alert MASK_EN_REG register 07h <- 2400 pour 0.6 A
// 2400 pour 0.6Amps
k=(uint8_t)cx*400;
tmp[0]=INA226_ALERT_LIMIT_REG;
tmp[1]=(k >> 8);
tmp[2]=(uint8_t)(k & 0x00FF);
Addr=INA226_ADDR;
p1=&tmp[0];
cx=3;
I2C1_WriteNBytes(Addr, p1, cx);

Addr= INA226_ADDR;
tmp[0]=0;
tmp[1]=0;
p1=&tmp[0];
I2C1_ReadDataBlock(Addr, INA226_ALERT_LIMIT_REG, p1,3);
k=(tmp[0]<<8) + tmp[1];
//Seuil_Alerte= 8.192 * (double)k / 32768.0;
Seuil_Alerte= (double)k / 4.0;
sprintf(CRam1," Seuil d'alerte %3.3f Amperes\r\n",Seuil_Alerte);
Print(CRam1);
}
else
{
CPrint(" Erreur parametre\r\n" );
}
if(cx=='0') Clignote=0;
CRLF1();
p0=0;
}
Flag_Buffer1=0;
}


images3/t_Test_cligot_sorties_MCP.gif


rev :21/05/2025
MPLAB IDE 6.0 et XC8
Directory: C:\MPLABX_Projects\18F27K42_PMW_CCP1234_2025
Project : 18F27K42_PMW_CCP1234_2025-0521.X.zip
main : main_18F27K42_MCP23017_0521.X.c

à suivre aussi
ICI



paulfjujo@free.fr


../common/mylogo_CI.jpg



Retour à l'index general