Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

Test mini OLED SSD1306 20x10mm 128x32 18F27K42
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#61 Message par paulfjujo » lun. 1 mars 2021 13:48

Bonjour à tous,

Merci ! à Satinas pour son support efficace

OUF !!!
Pas trop compliqué finalement, avec l'usage des interrupts !
pour l'ecriture et la lecture I2C

Test OK pour Init RTC .


Code : Tout sélectionner



 Init_Timer1
();
  GIE_bit=1;

    CPrint(" #1 Active sortie SQW=1Hz: \r\n");
    Wait_TimeOut_Only(30,0);
    CPrint(" GO\r\n");
  // avec interrupt
     tmp[0]=0x0E; tmp[1]=0x40; // set SQW output  Start oscillateur
    p1=&tmp[0];
    SQA=1;
    while (!I2C1STAT0_BFRE) ;
    I2C1ERR=0;
    I2C1STAT1_CLRBF = 1;
    I2C1ADB1 =  DS3231_ADDR;      // Load address  0xD0 with write = 0
    I2C1CNT = 2;                  // Load with size of array to write PLUS 1 for reg
    I2C1PIR_PCIF = 0;             // Clear Stop condition IF
    I2C1CON0_S = 1;
    I2C1IE_bit=1;
    I2C1TXIE_bit =1;
    // l'interrupt se charge de remplir la table
     while (!I2C1PIR_PCIF) ;       // PCIF is set after the STOP
     SQA=0;
    I2C1IE_bit=0;
    I2C1TXIE_bit =0;
    CPrint(" ok\r\n");


et OK, pour la lecture des 7 registre RTC



Code : Tout sélectionner


 
 
//--- Boucle principale  -----------
  do
   
{
     CPrint(" re-Lecture des 7 registre RTC DS3231 : ");
    // RAZ table d'echange
    for (i=0;i<10;i++) tmp[i]=;
    p1=&tmp[0]; // pointeur sur debut de table
    SQA=1;
    // choix debut RTC registre=0
    while (!I2C1STAT0_BFRE) ;
    I2C1STAT1_CLRBF = 1;
    I2C1ADB1 =  DS3231_ADDR;      // Adresse Devide avec R/W=0  ( 0xD0)
    I2C1CNT = 1;                  // Charge Nb de bytes à ecrire
    I2C1TXB = *(p1++);            // Charge l'adresse du registre concerné
    I2C1PIR_PCIF = 0;             // Raz flag STOP
    I2C1CON0_S = 1;               // Start transmission
    while (!I2C1PIR_PCIF) ;       // attente du STOP
    // lecture des 7 regitres
    while (!I2C1STAT0_BFRE) ;     // attente bus libre
    p1=&tmp[0]  ;
    I2C1PIR_PCIF=0;
    I2C1ERR=0;
    I2C1RXIE_bit=1;             // arme interrupt I2C reception
    I2C1ADB1 = (DS3231_ADDR+1); // adresse devic e+ R/W=1 )lecture en 0xD1
    I2C1CNT =7;                 // nombre de regitre à lire
    I2C1IE_bit=;              // autorise IT I2C
    I2C1CON0_S = 1;             // Start
    Delay_us(10);
    while (!I2C1PIR_PCIF) ;
    I2C1STAT1_CLRBF =0; // clear I2C1RXIF bi
    I2C1IE_bit=0;
    I2C1PIR_PCIF=0;
    SQA=0;
     second=tmp[0];
     minute=tmp[1];
     heure=tmp[2];
     jS=tmp[3];
     if (jS>7) jS=0;
     jour=tmp[4];
     mois=tmp[5]& 0x1F;
     Annee=tmp[6];
     tmp[7]=0;
     tmp[8]=0;
     // affichage data RTC
     for (i=6;i>0;i--)
     {
        BCD_To_Ascii(tmp[i],CRam1);
        Print(CRam1);Envoi_Char(TAB);
     }
     BCD_To_Ascii(tmp[0],CRam1);
     Print(CRam1);
     CRLF1();
     Delay_ms(1000);
   }
   while (1);



la partie interrupt .. trop simple
IT UART pour pouvoir faire la Mise A Jour RTC
IT Timer pour l'attente ( Wait_TimeOut_Only(30,0);)


Code : Tout sélectionner



void Interrupts
() iv 0x0008 ics ICS_AUTO
{    
     
// pour debugger
     // U1TXB=Count0+48;
    if (( TMR0IE_bit==1) && (TMR0IF_bit==1))
    {
        // pour 100mS
         TMR0H         = 0x3C; //15536;
         TMR0L         = 0xB0;
        Count0++;
        if (Count0 >9)
        {
          //  LED_VERTE = ~LED_VERTE;
            Drapeaux.Tmr0_Elapsed=1;
            TMR0IE_bit=0;
            PIE3.TMR0IE = 1 ;
        }
        PIR3.TMR0IF= 0;
    }
     //RX UART IT
     if (( U1RXIF_bit==1) && ( U1RXIE_bit==1))
     {
      // U1TXB=='?'; // pour debugger
      c1=U1RXB;
      if (U1ABDOVF_bit==1)    // voir parag  31.2.2.4   page 479
      {
       U1ABDOVF_bit = 0 ;
       CptErr++;
       c1=U1RXB ;
       }
       if(U1FERIF_bit==)
       {
        CptErr++;
        //c1 = UART1_Read();
        c1=U1RXB;
       }
       // modif pour test envoi par BluetoothElectronic.apk (pas de CR)
       if ((c1==CR) || (c1==LF) || (Index1>MAX_LEN1-1))
       //  if ((c1==CR) || (Index1>MAX_LEN1-1))
       {
        Flag_Buffer1=1;
        Buffer1[i1]=0;
        U1RXIE_bit=0;
        Index1=i1;
        i1=0;
        if( Index1>MAX_LEN1-1) Flag_Buffer1=2;
        TMR2IE_bit=0;
       }
       else
       
{
       Flag_Buffer1=0;
       Buffer1[i1]=c1;
       Index1=i1;
       i1++;
       }
     }
   if (( TMR1IE_bit) && (TMR1IF_bit))
    {
     // U1TXB='.';
      Cpt1--;
      if (Cpt1 <1)   // x25ms at 64MHz
      {
       TMR1ON_bit=0;
       TMR1IE_bit=0; // stop comptage  timer1
       Drapeaux.Tmr1_Elapsed=1;
      }
      else
      
{
        TMR1H         = 0x3C;
        TMR1L         = 0xB0;
      }
       TMR1IF_bit  = 0;
    }
  if ((I2C1RXIF_bit==1) && (I2C1IE_bit==1)&& (PIE2_I2C1RXIE ==1) )
  {
   // U1TXB='*';
   *(p1++)=I2C1RXB;
   }
    if ((I2C1TXIF_bit==1) && (I2C1IE_bit==1)&& (I2C1TXIE_bit ==1) )
  {
   // U1TXB='*'; // pour debug
    I2C1TXB=*(p1++);
   }
   }



l'acces individuel des registres RTC est aussi OK ( ex: test sur Minute only)

Init speciale I2C1 Hardware (sans MC)
Etat pin < Test Presence Device> =1
donc ,Pas de test presence Device
#1 Active sortie SQW=1Hz:
Waiting Timeout for < 3,0 Sec >
GO
ok
Etat pin <RTC_Forcee> = 1
Lecture registre Minute RTC DS3231 pendant > 2mn : 36
Lecture registre Minute RTC DS3231 pendant > 2mn : 37
Lecture registre Minute RTC DS3231 pendant > 2mn : 37
Lecture registre Minute RTC DS3231 pendant > 2mn : 37
Lecture registre Minute RTC DS3231 pendant > 2mn : 37
Lecture registre Minute RTC DS3231 pendant > 2mn : 37
Lecture registre Minute RTC DS3231 pendant > 2mn : 37
Lecture registre Minute RTC DS3231 pendant > 2mn : 38
Lecture registre Minute RTC DS3231 pendant > 2mn : 38
Lecture registre Minute RTC DS3231 pendant > 2mn : 38
Lecture registre Minute RTC DS3231 pendant > 2mn : 38
Lecture registre Minute RTC DS3231 pendant > 2mn : 38
Lecture registre Minute RTC DS3231 pendant > 2mn : 38
re-Lecture des 7 registre RTC DS3231 : 20 09 12 06 21 39 06
re-Lecture des 7 registre RTC DS3231 : 20 09 12 06 21 39 07
re-Lecture des 7 registre RTC DS3231 : 20 09 12 06 21 39 08
re-Lecture des 7 registre RTC DS3231 : 20 09 12 06 21 39 09






je mettrais un peu plus tard le projet complet
apres integration des fonctions ecr et lec , dans des sub routines
et le rajout de l'OLED

:-D du soleil, 20°C ... allez un peu de jardinage maintenant !
Aide toi, le ciel ou FantasPic t'aidera

Test mini OLED SSD1306 20x10mm 128x32 18F27K42
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#62 Message par satinas » lun. 1 mars 2021 14:46

Bonjour tout le monde

Bien joué pour les interruptions :)
Ce matin j'ai ressorti une ancienne carte DS3231 et fait un essai de lecture/écriture à l'adresse 0, pour afficher minutes et secondes.
Normalement il faut faire un Restart entre le W et le R, le Stop/Start c'est ok aussi.
La lecture se passe bien, j'affiche les secondes qui défilent, par contre l'écriture des secondes ne marche pas, la RTC n'est pas mise à jour. J'ai pas lu en détail la doc de la RTC, Tu as une idée ?

Code : Tout sélectionner

// I2C 18F27K42
//------------------------------------------------------------------------------
void I2cWrite(unsigned char addr7, unsigned char addr_data, unsigned char* b, unsigned char n)
//------------------------------------------------------------------------------
{
  while (!I2C1STAT0bits.BFRE) { }       // attente bus libre
  I2C1ADB1 = (unsigned char)(addr7<<1); // adresse chip + W
  I2C1CNT = 1+n;                        // on envoie adresse data et n data
  I2C1TXB = addr_data;
  I2C1CON0bits.S = 1;                   // envoi Start, adresse chip+W, adresse data
  while (n--) {
    while (!I2C1STAT1bits.TXBE) { }
    I2C1TXB = *b++;                     // envoi n data, Stop
  }
}

//------------------------------------------------------------------------------
void I2cRead(unsigned char addr7, unsigned char addr_data, unsigned char* b, unsigned char n)
//------------------------------------------------------------------------------
{
  while (!I2C1STAT0bits.BFRE) { }       // attente bus libre
  I2C1ADB1 = (unsigned char)(addr7<<1); // adresse chip + W
  I2C1CNT = 1;                          // on envoie adresse data
  I2C1TXB = addr_data;
  I2C1PIRbits.PCIF = 0;
  I2C1CON0bits.S = 1;                   // envoi Start, adresse chip+W, adresse data, Stop
  while (!I2C1PIRbits.PCIF) { }

  I2C1ADB1 += 1;                        // adresse chip + R
  I2C1CNT = n;                          // on reçoit n data
  I2C1CON0bits.S = 1;                   // envoi Start, adresse chip+R
  while (n--) {
    while (!I2C1STAT1bits.RXBF) { }
    *b++ = I2C1RXB;                     // réception n data, Stop
  }
}


OK l'écriture marche, j'envoyais en décimal, pas en BCD :)

Test mini OLED SSD1306 20x10mm 128x32 18F27K42
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#63 Message par paulfjujo » mer. 3 mars 2021 19:47

bonjour à tous ,


:mur: :mur: Encore une journée de perdue .. à chercher un probleme inexistant ..!

Plantage lors du lancement de ma routine MAJ RTC ...via ma commande UART terminal
Alors que cette fonction avait été maintes fois éprouvée, validée ..

probleme résolu apres désinstallation complete de MikroC et ré-installation ( version 7.60)
car je remarquai que mon fichier source modifié n'etait pas toujours pris en compte , réactualisé au vu du comportement apres compilation.

Le simple fait de ré-installer mikroC => programme OK

03/03/21 16H23M14S 18.00°C ; EA1(12b)= 208
03/03/21 16H23M15S 18.00°C ; EA1(12b)= 208
03/03/21 16H47M01S 18.00°C ; EA1(12b)= 208
03/03/21 16H47M02S 18.00°C ; EA1(12b)= 210
U;03;03;21;19;51;03;#

MAJ RTC
U;03;03;21;19;51;03;
Index1 = 21
03
03
21
19
51
03

Jour Semaine jS = 3 Mercredi mois =Mars

param Ok
Ecriture en bloc dans DS3231... OK


03/03/21 16H47M04S 18.00°C ; EA1(12b)= 208
03/03/21 16H47M05S 18.00°C ; EA1(12b)= 208



:furieux: et ce n'est pas la premiere fois que je le constate ..
il me semble que la gestion des fichiers dans l'environnement MikroC n'est pas fiable ..
ni la definition des paths .... surtout si on modifie le nom du source d'un projet .

nota : MikroC n'aime pas non plus les underscores _ dans les noms de projet, directory ou fichiers
alors que Win10 les toleres tres bien.

:!!: MikroC users !
ATTENTION,
ACHTUNG , PASST AUF !
Take Care if you get strange behaviors in your application ..

et de plus, je pense aussi que Necto Studio est TROP orienté , Hardware MikroE only ..
avec couches d'abstration HAL ... SDK et compagnies ..
Les PIC ne sont donc pas aussi Fantastiques ..coté MikroE

retour vers MPLABX ? en XC8 ? en ASM , le nouveau ?
sinon ARMons nous ?
Aide toi, le ciel ou FantasPic t'aidera

Test mini OLED SSD1306 20x10mm 128x32 18F27K42
venom
Avatar de l’utilisateur
Confirmé
Confirmé
Messages : 953
Âge : 38
Enregistré en : avril 2016
Localisation : Klyntar
Contact :

#64 Message par venom » jeu. 4 mars 2021 07:54

Bonjour paulfjujo,

C'est quand même fou, tout les problèmes que tu rencontres/trouves :shock: il y a de quoi se décourager.

Bravo pour la ténacité en tout cas. Et merci de tes retours.
Car même si je ne répond pas souvent, je lie toujours tes post enrichissant Merci !





@++
Mon site web
Mon discord : venom#4888

Test mini OLED SSD1306 20x10mm 128x32 18F27K42
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#65 Message par paulfjujo » jeu. 4 mars 2021 11:10

bonjour,

Coté RTC , c'est réglé
et le but est atteint :
les lib MikroC UART Hw ,I2C1 Hw et PPS ne sont pas utilisées
verifiable via la fenetre "messages" montrant le deroulement de la compilation ..

à noter :
* que mikroC n'a pas défini tous les registres de ce MCU ..ce qui explique la Re-definition de registres via sbit ...
principalement en ce qui concerne l' I2C1 hardware .
* cette application ne requiere que 6% de RAM (max=8170 bytes) et 6% de ROM (max 131071 bytes), de ce PIC Costaud.
* le simple fait d'utiliser la Lib MikroC UART , entrainerait l'usage de la lib PPS qui fait 1582 bytes en plus !
alors qu'on peut s'en passer , la preuve..
*L'OLED sera integré d'ici la fin de semaine..

Librairies MikroC utilisées:
_Lib_Math.mcl" "
_Lib_MathDouble.mcl" "
_Lib_System.mcl" "
_Lib_Delays.mcl" "
_Lib_CType.mcl" "
_Lib_CString.mcl" "
_Lib_CStdlib.mcl" "
_Lib_Conversions.mcl" "
_Lib_ADC_K40.mcl"

pas d'UART, ni de I2C , ni PPS (tres gourmande en taille!)


le code source complet :

Code : Tout sélectionner



#define Version "2021_0304"
 // OK apres rechargement complet de MikroC 7.60
 // #define Version "2021_0303"
 // PB avec MAJ RTC ..plantage
 // reception I2C RTC via interruption   .. OK
#define With_RTC_DS3231
//#define With_OLED_SSD1306

#define Directory "C:\\_MikroC\\_MesProjets_MikroC\\"\
  "_18F27K42_UART1_ADC1_Mini_Oled_20x10mm_RTC_I2C_Hw_SANS_MC_lib_2021"
#define Project " P18F27K42_I2C1_HW_RTC_sans_MC_Lib_2021.mcppi"
#define Source  " P18F27K42_I2C1_HW_RTC_OLED_sans_MC_Lib"
#define Eeprom " not used ...."
#define Others " No MikroC Lib for UART,I2C,PPS  ! "
#define Config " P18F27K42_Fosc_Interne_64Mhz_with_RA6_Clockout.cfgsch"
#define PROCESSOR " 18F27K42 PDIP28 "
#define POWER_SUPPLY  " 3.6V"

#define OSCILLATEUR_INTERNE
#define FOSC "64.0"  // MHz
#define BAUD "19200"  // UART1

#ifdef With_OLED_SSD1306
#define  SSD1306_LCDWIDTH     128
#define  SSD1306_LCDHEIGHT    32
#define OLED_ADDR   0x78                // oled i2c 0x3C<<1
#define OLED_PAGE    4                   // oled 32*128
#define OLED_COL    128
#define CMD_STREAM                  0x00
#define DATA_STREAM                 0x40
#define CMD_SINGLE                  0x80
#define SET_COL   0x21
#define SET_PAGE   0x22
#define OLED_Set(c,d)  OLED_Cde(c),OLED_Cde(d)
#define OLED_Set_Page(first,last) OLED_Cde(SET_PAGE),OLED_Cde(first),OLED_Cde(last)
#define OLED_Set_Col(first,last) OLED_Cde(SET_COL),OLED_Cde(first),OLED_Cde(last)
 #endif

#define CLS 12
#define CR 13         //0x0D
#define LF 10
#define TAB 9
#define BACK 8
#define Beep 7
#define Separator 0x20      // space
#define ON 0              // because led tirée au +VCC
#define OFF 1
#define SPECIAL 1
#define NORMAL 0
#define Plein 1
#define Vide 0


#ifdef With_OLED_SSD1306
 #include "../common/BMP_images_128x32_2021-0207.inc"
 #include "OLED_128x32_Tables_2021_02.h"
 #include "BigFont.inc"
 #include "OLED_Lib_I2C1_HW_SANS_Lib_MikroC_20210209.h"
#endif

#define DS3231_ADDR 0xD0  //0x68 I2C Hardware : sur 7 bits sinon  0xD0 sur 8 bits
//#include "Tiny_RTC_DS3231_HARDW_I2C1_for_K42_SANS_MC_Lib_2021_0302.h"


const char MOIS0[] ="erreur ";
const char MOIS1[] ="Janvier ";
const char MOIS2[] ="Fevrier ";
const char MOIS3[] ="Mars ";
const char MOIS4[] ="Avril ";
const char MOIS5[] ="Mai ";
const char MOIS6[] ="Juin ";
const char MOIS7[] ="Juillet ";
const char MOIS8[] ="Aout ";
const char MOIS9[] ="Septembre ";
const char MOIS10[]="Octobre ";
const char MOIS11[]="Novembre ";
const char MOIS12[]="Decembre ";
const char * Douze_Mois[]={MOIS0,MOIS1,MOIS2,MOIS3,MOIS4,MOIS5,MOIS6,MOIS7,MOIS8,MOIS9,MOIS10,MOIS11,MOIS12 };



const code char Jour0[]="Error ";
const code char Jour1[]="Lundi ";
const code char Jour2[]="Mardi ";
const code char Jour3[]="Mercredi ";
const code char Jour4[]="Jeudi ";
const code char Jour5[]="Vendredi ";
const code char Jour6[]="Samedi ";
const code char Jour7[]="Dimanche ";
const code char * JourSemaine[]={Jour0,Jour1,Jour2,Jour3,Jour4,Jour5,Jour6,Jour7};

const code char All_Jour_Semaine[]="ErLuMaMeJeVeSaDi";

const code char mesg0[]=" Directory :"Directory"\r\n";
const code char mesg1[]=" MikroC pro 7.60 \r\n";
const code char mesg2[] =" Projet :"Project"\r\n";
const code char mesg3[]=" Test PIC18F27K42 en I2C1 Hardware SANS I2C LIB MIKROC , SANS PPS LIB! \r\n";
const char char mesg4[]=" Config bit : "Config"\r\n FOSC:"FOSC" MHz\r\n";
const char char mesg5[]=" Eeprom: "Eeprom"\r\n";
const char char mesg6[]=" Source : "Source"_"Version".c\r\n";
const char char mesg7[]=" Autres : "Others"\r\n";
const char char mesg8[]=" 18F27K42 UART1 19200,8,N,1\r\n";
const char char mesg9[]=" I2C1 Hw  Test RTC !\r\n";
const char char mesg10[] ="  ";

const code char * Messages[]={mesg0,mesg1,mesg2,mesg3,mesg4,mesg5,mesg6,mesg7,mesg8,mesg9,mesg10};
const char Blancs[]="  ";


sbit I2C1STAT0_BFRE    at I2C1STAT0.B7;
sbit I2C1STAT1_TXBE    at I2C1STAT1.B5;
//sbit I2C1STAT1_CLRBF   at I2C1STAT1.B5;
sbit I2C1CON1_ACK      at I2C1CON1.B4;
sbit I2C1CON1_ACKSTAT  at I2C1CON1.B5;   //0 = Ack was received  1 = No Ack was not received
sbit I2C1CON2_ABD      at I2C1CON2.B4;
sbit I2C1CON0_EN       at I2C1CON0.B7;
sbit I2C1CON0_RSEN     at I2C1CON0.B6;
sbit I2C1CON0_S        at I2C1CON0.B5;
sbit I2C1CON0_MDR      at  I2C1CON0.B3;
sbit I2C1PIR_PCIF      at I2C1PIR.B2 ;
sbit I2C1PIR_SCIF      at I2C1PIR.B0 ;
sbit I2C1STAT1_RXBF    at I2C1STAT1.B0;
sbit I2C1STAT0_MMA     at I2C1STAT0.B5;
sbit I2C1PIR_CNTIF     at I2C1PIR.B7;
sbit PIR2_I2C1RXIF     at PIR2.B7;
sbit PIE2_I2C1RXIE     at PIE2.B7;
sbit I2C1STAT1_CLRBF  at I2C1STAT1.B2;

sbit CLKOUT at LATA.B6;
sbit CLKOUT_Dir at TRISA.B6;
sbit Led at LATA.B4;
sbit Led_Dir at TRISA.B4;
sbit SQA at LATA.B3;
sbit SQA_Dir at TRISA.B3;
sbit RTC_Forcee at PORTC.B0;
sbit RTC_Forcee_Dir at TRISC.B0 ;
sbit Test_Presence_Device at PORTC.B1;
sbit Test_Presence_Device_Dir at TRISC.B1 ;
// -----------------------------------


#define MAX_LEN1 80
#define MAX_LEN2 64
#define MAX_LEN3 80

unsigned int i,j,k,l,m,n;
volatile unsigned char Buffer1[MAX_LEN1];
unsigned  char tmp[40];
volatile unsigned char *p1;
volatile unsigned char *p2;

unsigned char CRam1[MAX_LEN2];
unsigned char TEXTE [MAX_LEN3];
unsigned char *txt;
static unsigned char *px;
volatile unsigned  char NumReg=0;
volatile struct chbits {   // 8 flags
       unsigned FrameErr:1;
       unsigned RAZ:1;
       unsigned Tmr0_Elapsed:1;
       unsigned Tmr1_Elapsed:1;
       unsigned Tmr2_Elapsed:2;
       unsigned
       unsigned Full
:1;
      unsigned Gie:1;
 }Drapeaux ;

#ifdef With_OLED_SSD1306
unsigned char RamBuffer[512];
unsigned char buff[128];  //OLED_COL*OLED_PAGE];
#endif

unsigned char I2C_Adresses_Devices[8];

volatile int Flag_Buffer1=0;
volatile unsigned char c1,cx;
volatile unsigned int i1;
volatile unsigned int Index1;
volatile unsigned int CptErr;
volatile unsigned int Cpt1;

volatile unsigned int Count0,Count1,Count2,CountS;

unsigned int SEA1,EA1,Nb;
float F0,F1;
unsigned long L1;



 int Etat;
 unsigned char Adr;
 char time[]="00H00M00S";
 char date[]="00/00/00";
 unsigned char second,minute,heure,jS,jour,mois,Annee;
 unsigned char Month;
 unsigned char Sec;
 unsigned char DateTime[10];
 char Visu;
 unsigned char DS_Temp[10];
 volatile unsigned char Temp=0;

//===========================================
void strConstRamCpy(unsigned char *dest, const code char *source);
void Envoi_Char(char c);    // SANS UART Lib !!!
void CPrint (const char *t);
void Print ( char *t);
void CRLF1(void);
void Raz_Buffer1(void);
void I2C1_Hw_Init(void);
unsigned char I2cScan(void);
void Decompile_Byte(unsigned char un);
void Arme_Timer1(signed int  Max_Timer1)  ;
void Init_Timer1(void);
void Wait_Keyb_Only(unsigned int T) ;
void Init_Timer2(void);   // 200µS at 64MHz

//================
void Display_Date_Time(char Visu);  // 12-06-2018
void Ds3231_Temp_CP(char mode) ;
void DS3231_Read_All_Registers(void);
unsigned char Lecture_Affichage_Registre_DS3231(char n, char imprime);
void I2C1_Write(unsigned char addr8, unsigned char addr_data, unsigned char* b, signed char n);

void BCD_To_Ascii(unsigned char cc,unsigned char *pp);
unsigned char Dec2Bcd(unsigned char decnum);
void MAJ_RTC(void);


#ifdef With_OLED_SSD1306
void My_OLED_Init(void);
void Another_OLED_Init(void);
void OLED_WriteDat(unsigned char I2C_Dat);
void OLED_Data(unsigned char *p1, unsigned  char nb);
void OLED_Cde(unsigned char c);
void Big_affichage( unsigned char posX, unsigned char N );
void ShowBigNumber(unsigned char x,unsigned char  y, unsigned char N);  //16x16
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char *ch, unsigned char TextSize);
void OLED_DrawBMP_128x32(const unsigned char *BM) ;
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,const unsigned char *BM);
void Resize(void);
void OLED_Fill(unsigned char x);
void OLED_CLS (void);
void OLED_SetPos(unsigned char x1, unsigned char y1);
void Affiche_Car_8x8 ( unsigned char posX, unsigned char PosY,unsigned char *Name );
void Affiche_Car_Speciaux_8x8 ( unsigned char posX, unsigned char PosY,char N );
void Write_Char_At(unsigned char X,unsigned char Y, unsigned char C);
void OLED_pixel(short x, short y, char color);
void Refresh_OLED(void);
void Raz_RamBuffer(void);
#endif



void Interrupts() iv 0x0008 ics ICS_AUTO
{    
     
// pour debugger
     // U1TXB=Count0+48;
   /*
    if (( TMR0IE_bit==1) && (TMR0IF_bit==1))
    {
       // pour 100mS
         TMR0H         = 0x3C; //15536;
         TMR0L         = 0xB0;
        Count0++;
        if (Count0 >9)
        {
          //  LED_VERTE = ~LED_VERTE;
            Drapeaux.Tmr0_Elapsed=1;
            TMR0IE_bit=0;
            PIE3.TMR0IE = 1 ;
        }
        PIR3.TMR0IF= 0;
    }
    */
    
     
//RX UART IT
     if (( U1RXIF_bit==1) && ( U1RXIE_bit==1))
     {
      // U1TXB=='?';
      c1=U1RXB;
      if (U1ABDOVF_bit==1)    // voir parag  31.2.2.4   page 479
      {
       U1ABDOVF_bit = 0 ;
       CptErr++;
       c1=U1RXB ;
        U1TXB=='W';
       }
       if(U1FERIF_bit==)
       {
        CptErr++;
        //c1 = UART1_Read();
        c1=U1RXB;
          U1TXB=='Y';
       }
       // modif pour test envoi par BluetoothElectronic.apk (pas de CR)
       if ((c1==CR) || (c1==LF) || (Index1>MAX_LEN1-1))
       //  if ((c1==CR) || (Index1>MAX_LEN1-1))
       {
        Flag_Buffer1=1;
        Buffer1[ Index1]=0;
        Index1=i1;
        U1RXIE_bit=0;
        i1=0;
        c1=U1RXB ; // vide UART buffer when receiving CR LF
        if( Index1>MAX_LEN1-1) Flag_Buffer1=2;
       // TMR2IE_bit=0;
       }
       else
       
{
       Flag_Buffer1=0;
       Buffer1[i1]=c1;
       Index1=i1;
       i1++;
       }
     }
   if (( TMR1IE_bit) && (TMR1IF_bit))
    {
     // U1TXB='.';
      Cpt1--;
      if (Cpt1 <1)   // x25ms at 64MHz
      {
       TMR1ON_bit=0;
       TMR1IE_bit=0; // stop comptage  timer1
       Drapeaux.Tmr1_Elapsed=1;
      }
      else
      
{
        TMR1H         = 0x3C;
        TMR1L         = 0xB0;
      }
       TMR1IF_bit  = 0;
    }
  if ((I2C1RXIF_bit==1) && (I2C1IE_bit==1)&& (PIE2_I2C1RXIE ==1) )
  {
   // U1TXB='*';
   *(p1++)=I2C1RXB;
     I2C1RXIF_bit=0;
   }
   if ((I2C1TXIF_bit==1) && (I2C1IE_bit==1)&& (I2C1TXIE_bit ==1) )
  {
   // U1TXB='*';
    I2C1TXB=*(p1++);
    I2C1TXIF_bit=0;
   }
}


void strConstRamCpy(unsigned char *dest, const code char *source)
 {
  while (*source)*dest++ = *source++ ;
  *dest = 0 ;    // terminateur
}

void Envoi_Char(char c)
{
 while(U1TXIF_bit==0);
  U1TXB=c;
  Delay_us(50);
  }
  
void Print 
(char *t)
{
int i=0;
 while(*(t)>0)
 {
   Envoi_Char(*(t++));
   i++;
   if (i>250) break;
 }
}

void CPrint (const char *t)
{
int i=0;
 while(*(t)>0)
 {
   Envoi_Char(*(t++));
   i++;
   if (i>250) break;
 }
}


void CRLF1()
{
Envoi_Char(CR);
Envoi_Char(LF);
}

void Raz_Buffer1()
{
        // nettoye le debut de buffer ,car utilisé pour init BT
        for(i1=0;i1<MAX_LEN1-1;i1++) Buffer1[i1]=0;
        Flag_Buffer1 =;
        U1RXEN_bit=1;
        U1ERRIR = 0x00;
        U1ERRIE = 0x00;
        if (U1RXIF==1)   c1=U1RXB ;
        c1=0;
        Buffer1[0]=0;
        i1=0;
        p2=Buffer1;
        Index1=0;
        U1RXIE_bit=1;        //RC1IE_bit = 1;  sur  18F26K22
}


//------------------------------------------------------


void Arme_Timer1(signed int  Max_Timer1)
{
   // 100mS * Max_Timer1  (at 64Mhz/4 =16Mhz)
  T1CON         = 0x31;
  TMR1H         = 0x3C;
  TMR1L         = 0xB0;
  if (Max_Timer1>0) Cpt1=  Max_Timer1 ; else Cpt1=30; // 3sec par defaut
  Drapeaux.Tmr0_Elapsed=0;
  TMR1IF_bit  = 0;
  TMR1IE_bit= 1;
  TMR1ON_bit=1;     // Timer0 ON
  GIE_bit=1;
  }

void Init_Timer1(void)
 {
// FOSC=64MHz   .. mais !!!
//Timer1
//Prescaler 1:8; TMR1 Preload = 15536; Actual Interrupt Time : 25 ms
  T1CKPS1_bit=1;
  T1CKPS0_bit=1;
  T1CON.B0=1;
  T1RD16_bit=1;
  T1CON         = 0x32;
  T1GCON=0;  //GE disabled
  T1CLK=1; //  FOSC/4   => 16MHz !    ==> 100mS
  TMR1H         = 0x3C;
  TMR1L         = 0xB0;
   TMR1IF_bit  = 0;
  TMR1IP_bit=1;   // high level interrupt
  Cpt1=4;
  Drapeaux.Tmr0_Elapsed=0;
  TMR1ON_bit=0;
  TMR1IE_bit =0;
}

 void Wait_TimeOut_Only(unsigned int T, char mode)       // sans RX UART Interrupt
 // void Wait_Keyb_Or_Timeout(unsigned int T)       // sans RX UART Interrupt
  { char Tx[8];
    int T1;
    Led=~Led;
    if (T>999) T=999;
    T1=T;
   // Raz_Buffer1() ;
    Arme_Timer1(T<<2);    // T * 4 * 25mS =100 ms
    if (mode==0) CPrint(" Waiting Timeout for <");
    else  CPrint(" ... Waiting Keyboard Touch until Timeout for <");
    if (T1/100>0) *(Tx)=T1/100+48;  else *(Tx)=' ';
       T1=T1%100;
     if (T1/10>0) *(Tx+1)=T1/10+48;
       else *(Tx+1) ='0';
     Tx[2]=0x2C;
     Tx[3]= T1%10+48;
     Tx[4]=0;
     Print(Tx);
      CPrint(" Sec >\r\n");
      if (mode==1)
      {
        while ( (Flag_Buffer1==0) && (Drapeaux.Tmr1_Elapsed==0));
       }
       else
         while 
( Drapeaux.Tmr1_Elapsed==0);
    Drapeaux.Tmr1_Elapsed=0;
  // CRLF1();
 }


void Init_Timer2()
{
  //T2CON         = 0x64;  //Prescaler 1:1; Postscaler 1:13; TMR2  245; 200µS at 64MHz
  //PR2           = 245;
  T2CON         = 0x3E; // 2ms at 64MHz
  // T2CON         = 0x7D;     // 1ms at 64MHz  prescaler=1/4  postscaler=1/16
  //T2CON         = 0x34; // 100µS at 64 Mhz  Prescaler=1/1  postscaler =1/7
  // PR2                 = 250;
  TMR2IE_bit         = 0;
  INTCON         = 0x00;
}


void Decompile_Byte(unsigned char un)
{
 unsigned char masque;
 masque = 0x80;
 while (masque > 0 )
 {
   if ((un & masque)==masque)
   Envoi_Char('1');  //  '*'
   else
   Envoi_Char
('0');  //  ' '
   masque =masque >>1;
   Delay_us(20);
  }
}

//------------------------------------------------------
void  I2C1_Hw_Init(void)
//------------------------------------------------------
{
  TRISC.B3   = 0;         // C3 output
  TRISC.B4   = 0;         // C4 output
  WPUC       = 0x18;      // C3 et C4 pull-up
  ODCONC     = 0x18;      // C3 et C4 open drain
  RC3PPS     = 0x21;      // i2c1, scl -> C3
  I2C1SCLPPS = 0x13;      // i2c1, scl <- C3
  RC4PPS     = 0x22;      // i2c1, sda -> C4
  I2C1SDAPPS = 0x14;      // i2c1, sda <- C4
  //CLKRCON=0b10010110;  // EN=1 Duty=50%  Div=64
  //CLKRCLK=0x01; //0001 = HFINTOSC
  I2C1CLK    = 0x03;      // i2c1, 0011 MFINTOSC  500Khz  ..OK
  I2C1CON0   = 0x04;      // i2c1, master 7 bits
  I2C1CON1   = 0x80;      // i2c1, envoi NAK sur dernier octet attendu
  //I2C1CON2   = 0x01;      // i2c1, envoi Start non auto, SDAHT 300ns hold time, BFRET 16 i2c clock pulses
  I2C1CON2 = 0x00;      // ABD enabled; SDAHT 300 ns; BFRET 8 I2C Clocks; FME disabled;
  I2C1ADB1   = 0x00   ; //OLED_ADDR; // i2c1, 2 * adresse esclave
  I2C1CON0_EN = 1;        // i2c1 on
  I2C1ERR = 0;
  I2C1PIR = 0;
}


char I2C1_DevicePresent(unsigned char adr)     // voir Device_detect_18F27K42_20210225.jpg
 {  
   static char Status
;
    //   SQA = 1 ;                // debug bit high
       I2C1PIR_PCIF = 0;    // clear STOP bit flag
       I2C1ADB1 = adr ; // Load slave address 8 bits
       I2C1CNT = 0;
       I2C1CON0_S = 1;     // send START + addr
    //   SQA = 0 ;
       while (I2C1PIR_PCIF == 0);    // wait for STOP
    //   SQA = 1;                 // debug bit low
       Status=!I2C1CON1_ACKSTAT;
    //    SQA = 0 ;
       return Status ;
}



 //--------------------------------------------------------------------------------------------
unsigned char I2cScan(void)
//--------------------------------------------------------------------------------------------
// Scan bus I2C, envoi Start + adresse + Stop
{
  unsigned char adr;
  static unsigned char n ;
  n=0;
  for (adr=2; adr<254; adr=adr+2)
  {    if ( I2C1_DevicePresent(adr))
    {
        I2C_Adresses_Devices[n]=adr;
        n++;
    }
    if(n>7) break;
  }
  return n;
}

void I2C1_ReadDataBlock(unsigned char adre, unsigned char registre, unsigned char *dat, unsigned char Nb)
 {   while (!I2C1STAT0_BFRE) ;     // attente bus libre
    I2C1PIR_PCIF = 0;              // Clear Stop condition IF
    I2C1PIR_SCIF = 0;              // Clear Start condition IF
    I2C1STAT1_CLRBF = 1;
    I2C1ADB1 =adre;                // Load slave address and shift
    I2C1TXB = registre;                  // Load slave starting register address
    I2C1CNT = 1;                    // Load count
    I2C1CON0_RSEN = 0;              // Set RSEN for master read
    I2C1CON0_S = 1;                 // Set Start to get things going
    while(I2C1CON0_MDR);           // Wait until master is ready to receive data
    I2C1ADB1 = (adre| 0x01);          // Load address with Read enabled
    I2C1CNT = Nb;                   // Load length of expected packet in bytes
    I2C1CON0_S = 1;                 // Set Start to begin Restart condition
    I2C1CON0_RSEN = 1;              // Clear RSEN
    while(I2C1CNT>0)                  // While there is a count
    {   while(!I2C1STAT1_RXBF);     // Wait until buffer receives data
        *(dat++) = I2C1RXB;           // Transfer data into array, hardware decrements count
    }
    while (I2C1PIR_PCIF==0);    // PCIF is set after the STOP
      I2C1PIR_PCIF = 0;       // Clear Stop condition IF
    I2C1PIR_SCIF = 0;           // Clear Start condition IF
    I2C1STAT1_CLRBF = 1;
}


#ifdef With_OLED_SSD1306
// **********************    OLED  ***************************

void My_OLED_Init(void)
{
//SSD1306.pdf
//Software Configuration
       OLED_Cde(0xAE); //display off
       Delay_ms(100);
       OLED_Cde(0xAF); //display on
       Delay_ms(10);
       OLED_Cde(0xB0);// Set GDDRAM Page start adresse [2:0]  0 à 7
       OLED_Cde(0x00);   // mini 0
       OLED_Cde(OLED_PAGE-1);   // maxi
      // OLED_Cde(0x07);   // maxi  pour 128x64
       OLED_Cde(0x20); //Set Horizontal Memory Addressing Mode
                       //A[1:0] = 00b, Horizontal Addressing Mode
                       //A[1:0] = 01b, Vertical Addressing Mode
                       //A[1:0] = 10b, Page Addressing Mode (RESET)
                       //A[1:0] = 11b, Invalid
        OLED_Cde(0x00); //   Horizontal Addressing Mode (  0x02 =page adressing mode or RESET)
        OLED_Cde(SET_COL); // Setup column start and end address
        OLED_Cde(0);   //A[6:0] : Column start address, range : 0-127d,(RESET=0d)
        OLED_Cde(OLED_COL-1);  // B[6:0]: Column end address, range : 0-127d,(RESET =127d= 0x7F)
        OLED_Cde(SET_PAGE);//  Setup page start and end address
                         //  A[2:0] : Page start Address, range : 0-7d,
                         // (RESET = 0d)
                         //  B[2:0] : Page end Address, range : 0-7d,
                         // (RESET = 7d)
        OLED_Cde(0x00);
        OLED_Cde(0x03);     //was 0x07
       // OLED_Cde(0xA0); //--set segment re-map colum 0 to SEG 0     de droite -> gauche
       OLED_Cde(0xA1); //--set segment re-map to 127     de gauche -> droite
       OLED_Cde(0xA4);//command enable display outputs according to the GDDRAM contents.
       //  OLED_Cde(0xA5);//command forces the entire display to be “ON”, regardless of the contents of the display data RAM.
       OLED_Cde(0xA6);//normal display
       //  OLED_Cde(0xA7);//reverse display
       OLED_Cde(0xC8); //Set COM Output Scan Direction
       //C0h, X[3]=0b: normal mode (RESET) Scan from COM0 to COM[N –1]
       //C8h, X[3]=1b: remapped mode. Scan from COM[N-1] to COM0
       OLED_Cde(0xD3); //--set start line address 40h =  set   to 0
       OLED_Cde(0x40);  //0x40  ou 0x3F
       // was     OLED_Cde(0x00);
       //0xD3,0x3F, // DISPLAY offset ROW0 - L0xD3,0x00,leaves one row of pixels at top. 0xD3,0x3F is better
       OLED_Cde(0xD5); //--set display clock divide ratio/oscillator frequency
       OLED_Cde(0x80); //--set divide ratio   80h
       OLED_Cde(0xA8); //--set multiplex ratio to 63
       OLED_Cde(0x3F); //  was 3F
       OLED_Cde(0xD6); //-- This command is to set the vcommon signals padconfiguration.
       OLED_Cde(0x80); // --set divide ratio   80h
       OLED_Cde(0xD9); //--set display clock divide ratio/oscillator frequency
        // A[3:0] : Phase 1 period of up to 15 DCLK clocks 0 is invalid entry(RESET=2h)
        // A[7:4] : Phase 2 period of up to 15 DCLKclocks 0 is invalid entry(RESET=2h )
       OLED_Cde(0x22); //  22h --reset values   22h
       //0xDA, (C.OLED_HEIGHT==64)?0x12:0x02,
       OLED_Cde(0xDA); //--set com pins hardware configuration
       OLED_Cde(0x20);  // was 0x20      32
       //        OLED_Cde(0x12);  // 0x12h   64
       //        A[4]=0b, Sequential COM pin configuration
       //        A[4]=1b(RESET), Alternative COM pin configuration
       //        A[5]=0b(RESET), Disable COM Left/Right remap
       //        A[5]=1b, Enable COM Left/Right remap
       OLED_Cde(0xEE);      // Read-Modify-Write end.
       OLED_Cde(0x81); //--set contrast control register
       OLED_Cde(0x7F); // 0x00~0xff
       OLED_Cde(0x2E); // no scrolling
       OLED_Cde(0xDB); //--set VComH deselect level
       OLED_Cde(0x20); // 20H => 0.77x Vcc (Reset value)
       OLED_Cde(0x8D); //--set DC-DC enable  Charge Pump Setting
       OLED_Cde(0x14); // 0x14 Enable Charge Pump
       OLED_Cde(0xAF); //--turn on OLED panel
}




//------------------------------------------------------
void OLED_Cde(unsigned char c)
//------------------------------------------------------
{
  I2C1ADB1   = OLED_ADDR;
  while (!I2C1STAT0_BFRE) ;    // attente bus libre
  I2C1CNT = 2;                    // on envoie 2 octets
  I2C1TXB = CMD_SINGLE;
  I2C1CON0_S = 1;                 // envoi Start
  while (!I2C1STAT1_TXBE)  };
  I2C1TXB = c;                    // envoi commande puis Stop
 while (!I2C1PIR_PCIF);    // PCIF is set after the STOP
      // Delay_us(10);
}




//------------------------------------------------------
void OLED_Data(unsigned char *p1, unsigned  char nb)
{
  I2C1ADB1   = OLED_ADDR;
  while (!I2C1STAT0_BFRE) { };     // attente bus libre
  I2C1CNT = nb+1;                  // on envoie 1+n octets
  I2C1TXB = DATA_STREAM;          // envoi adresse puis DATA_STREAM
  I2C1CON0_S = 1;
  while (nb--)
  {                   // envoi n data puis Stop
    while (!I2C1STAT1_TXBE) {  };
    I2C1TXB =*(p1++);
    }
  while (!I2C1PIR_PCIF);    // PCIF is set after the STOP
}

void Big_affichage( unsigned char posX, unsigned char N )
{
     int k;
     unsigned  char cc;
     CRLF1();
    OLED_Cde(0x20);   OLED_Cde(0x00); // horizontal mode
    OLED_Cde(0x21); // On configre la largeur de l'ecran
    // pour forcer, limiter le retournement horizontal   voir DS figure 10.5
    OLED_Cde(0+posX);        // Colonne minimum
    OLED_Cde(15+posX);        // Colonne MAximum;
    OLED_Cde(0x22);
    // positionement vertical entre page 1 et 3    H=16 pixels
    OLED_Cde(1);
    OLED_Cde(3);
    for(k=0;k<48;k++)
    {
    cc= *(Big_Numbers[N]+k);
    OLED_Data(&cc,1);
   //  Decompile_Byte(cc);
   //  CRLF1();
     }
   // CRLF1();
    //OLED_Data(*(Big_Numbers[N]),48);
    //  Resize();
 }

//--------------------------------------------------------------
// Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Parameters     : x,y --(x:0~127, y:0~7); ch[] ; TextSize (1:6*8 ; 2:8*16)
//--------------------------------------------------------------
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char *ch, unsigned char TextSize)
{
        unsigned char c = 0, cx=0;
        unsigned char i = 0,= 0;
        unsigned char xd=0,yd=0;
        int kx,lx;
        xd=x;
        yd=y;
        OLED_SetPos(xd,yd);
        switch(TextSize)
        {
                case 1:
                    while((*(ch+j) !=0) && ( yd<5))
                    {
                     c = *(ch+j);
                     if(c==176) c=124-32; else c=c-32; // pour °C
                     if(xd > 120)
                     {
                      xd = x;
                      yd++;
                       OLED_SetPos(xd,yd);
                     }
                     kx=(int)yd*128;
                     kx=kx+xd;
                     for (i=0;i<6;i++)
                     {
                       tmp[i]= font_regular_6x8[c][i];
                       RamBuffer[kx+i]= tmp[i];
                     }
                      OLED_Data(tmp, 6);
                     /*
                     tmp[0]= font_regular_6x8[c][0];
                     tmp[1]= font_regular_6x8[c][1];
                     tmp[2]= font_regular_6x8[c][2];
                     tmp[3]= font_regular_6x8[c][3];
                     tmp[4]= font_regular_6x8[c][4];
                     tmp[5]= font_regular_6x8[c][5];
                     OLED_Data(tmp, 6);
                     kx=(int)yd*128;
                     kx=kx+xd;
                     strncpy(RamBuffer+kx,tmp,6);
                     */
                     xd=xd+6;
                     j++;
                    }
                    break;
                 case 2:
                     kx=strlen(ch);
                     j=0;
                    while((*(ch+j) !=0) && (j<16) )
                    {
                      c = *(ch+j) ;
                      if(c==176) c=124-32; else c=c-32; // pour °C
                      if(xd > 112)        // width > 14 chars x8
                      {
                        xd = x;      // si deborde la ligne
                        yd=yd+1;     // change de ligne
                        }
                     OLED_SetPos(xd,yd);
                     for(i=0;i<16;i++)
                     {
                        tmp[i]=*(F8X16+(c*16+i)) ;
                      }
                      OLED_Data(tmp,8);
                      OLED_SetPos(xd,yd+1);   // page  (ligne) en dessous
                      OLED_Data(tmp+8,8);
                      xd=xd+8;
                      j++;
                    }
                    break;
                 case 3:
                        lx=strlen(ch);
                  if (lx>0)
                   {
                     for (i=0;i<lx;i++)
                     {
                     //cadrage à droite
                      kx=(i+7-lx) *16;
                      c=*(ch+i);
                      // numeriques seulement 0 à 9
                      if ((c>47) && (c<58))
                       Big_affichage(kx,c-48);
                       else
                       
// caracteres speciaux
                        {
                         switch (c)
                         {
                          case 46 :
                            Big_affichage(kx,10) ;     //point
                            break;
                          case 32:
                             Big_affichage(kx,11) ;   // space=Blanc
                             break;
                          case '-':
                             Big_affichage(kx,12) ;  // ° ( degré)
                             break;
                         case 176:
                             Big_affichage(kx,13) ;   // moins
                             break;
                          default:
                             Big_affichage(kx,11) ;   //space
                            break;
                         }
                       }
                     }
                   }
                    break;

                default:
                    break  ;
        }
}

//--------------------------------------------------------------
// Prototype      : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Parameters     : x0,y0 --(x0:0~127, y0:0~3); x1,y1 -(x1:1~128,y1:1~4)
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char page0,unsigned char x1,unsigned char page1,const unsigned char *BM)
{
        unsigned int j=0;
        unsigned int k=0;
        unsigned char x,y;
        unsigned char C1;
     j=0;
      k=x1-x0;
     for(y=page0;y<page1;y++)
    {
      OLED_SetPos(x0,y);
      j=x0+(y*128);     // car BMP 128x32
      for(x=x0;x<x1;x++)
      {    OLED_SetPos(x,y);
      C1=BM[j];
      OLED_Data(&C1,1);
      j++;
    //   Decompile_byte(C1);
     }
   //  CRLF1();
     }
   //   OLED_ON();
}

void OLED_DrawBMP_128x32(const unsigned char *BM)
{
   unsigned int j=0;
    unsigned char x,y;
    unsigned char c1;
    j=0;
    for(y=0;y<OLED_PAGE;y++)
    {
      OLED_SetPos(0,y);
      for(x=0;x<128;x++)
      {
      c1=BM[j];
      OLED_Data(&c1,1);
      buff[j]=c1;
      j++;
      }
   }
}


void Resize()
{
    OLED_Cde(0x20);
    OLED_Cde(0x00); // horizontal mode
 //   OLED_Cde(0x02); // page mode
    OLED_Cde(0x21); // On configre la largeur de l'ecran
    OLED_Cde(0);        // Colonne minimum
    OLED_Cde(127);        // Colonne MAximum;
    OLED_Cde(0x22);
    OLED_Cde(0);        // page minimum
    OLED_Cde(3);          // page maxi
    }

void OLED_Fill(unsigned char ca)
//------------------------------------------------------
{
  unsigned char p, c;
  for (p=0; p<OLED_PAGE; p++)
  {
    OLED_Set_Page(p, p);                  // page 0 à 7
    OLED_Set_Col(0, OLED_COL-1);         // colonnes 0 à 127
    for (c=0; c<OLED_COL; c++)
    {
       buff[c] = ca;
    }
    OLED_Data(buff, OLED_COL);
  }
}


void OLED_CLS(void)
{
        OLED_Fill(0);
        OLED_SetPos(0,0);
        Delay_ms(10);
}

void OLED_SetPos(unsigned char x1, unsigned char y1)
{
       OLED_Cde(0xB0+y1);
       OLED_Cde(x1 & 0x0F) ;
       OLED_Cde(((x1 & 0xF0)>>4)|0x10);

}


// rev 19-01-2020
void Write_Char_At(unsigned char X,unsigned char Y, unsigned char C)
{
unsigned char ca;
      OLED_SetPos(X,Y);
      if (C>=32)  /// caractere imprimable
        {
          // traitement special pour ° (de °C)
         if (C==176)  ca=124-32; else ca=C-32;
         //OLED_Cde(0x40);
         tmp[0]= font_regular_6x8[ca][0];
         tmp[1]= font_regular_6x8[ca][1];
         tmp[2]= font_regular_6x8[ca][2];
         tmp[3]= font_regular_6x8[ca][3];
         tmp[4]= font_regular_6x8[ca][4];
         tmp[5]= font_regular_6x8[ca][5];
         OLED_Data(tmp, 6);
       }
}


void OLED_Pixel(unsigned char x, unsigned char y,unsigned char Color)
{
  int  m;
   unsigned char  nt,page,bx;
    page=y/8;
    bx=y%8;
    m=(int)page*128;
    m=m+x;
    nt= RamBuffer[m];
    if (Color==1)
    nt=nt | (1<<bx);
    else
     nt
=nt & (~(1<<bx));
     RamBuffer[m]=nt ;
   //  OLED_Data(RamBuffer+m,1) ;
}



void Draw_Line(unsigned char x1, unsigned char y1, unsigned char x2, signed char y2, unsigned char color)
{
    signed int x, y, addx, addy, dx, dy;
      signed int px;
      int i;
      dx = abs ( (signed int) (x2 - x1));
      dy = abs ( (signed int) (y2 - y1));
      x = x1;
      y = y1;

      if (x1 > x2)
        addx = -1;
      else
      addx 
= 1;

      if (y1 > y2)
         addy = -1;
      else
      addy 
= 1;

      if (dx >= dy)
      {
         px = (dy<<1) - dx;
         for (i=0;i<=dx;i++)
         {
            OLED_Pixel(x, y,color);
            if (px < 0)
            {
               px =px + (dy<<1);
               x= x+ addx;
            }
            else
            
{
              px = px + (dy<<1) - (dx<<1);
               x =+ addx;
               y = y + addy;
            }
         }
      }
      else
      
{
         px = (dx<<1) - dy;
         for (i=0;i<= dy;i++)
         {
            OLED_Pixel(x, y,color);
            if (px < 0)
            {
               px = px + (dx<<1);
               y = y + addy;
            }

            else
            
{
               px = px + (dx<<1) - (dy<<1);
               x = x + addx;
               y = y +  addy;
            }
         }
      }
}


// Draw a triangle
void Draw_Triangle(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, char color)
 {
  Draw_Line(x0, y0, x1, y1,color);
  Draw_Line(x1, y1, x2, y2,color);
  Draw_Line(x2, y2, x0, y0,color);
}


void Draw_Rectangle(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char fill, unsigned char colour)
{
     unsigned char i ,j= 0x00;
     unsigned char xmin = 0x00;
     unsigned char xmax = 0x00;
     unsigned char ymin = 0x00;
     unsigned char ymax = 0x00;

     if(fill != 0)
     {
        if(x1 < x2)
        {
           xmin = x1;
           xmax = x2;
        }
        else
        
{
           xmin = x2;
           xmax = x1;
        }

        if(y1 < y2)
        {
           ymin = y1;
           ymax = y2;
        }
        else
        
{
           ymin = y2;
           ymax = y1;
        }

        for(j=xmin; j <= xmax; j++)
        {
           for(= ymin; i <= ymax; i++)
           {
               OLED_Pixel(j, i, colour);
           }
         }
     }

     else
     
{
        Draw_Line(x1, y1, x2, y1, colour);
        Draw_Line(x1, y2, x2, y2, colour);
        Draw_Line(x1, y1, x1, y2, colour);
        Draw_Line(x2, y1, x2, y2, colour);
     }

}


void Draw_Circle(unsigned char xc, unsigned char yc, unsigned char radius, unsigned char fill, unsigned char colour)
{
   signed int a = 0x0000;
   signed int b = 0x0000;
   signed int P = 0x0000;

   b = radius;
   P = (- b);

   do
   
{
        if(fill != 0)
        {
           Draw_Line((xc - a), (yc + b), (xc + a), (yc + b), colour);
           Draw_Line((xc - a), (yc - b), (xc + a), (yc - b), colour);
           Draw_Line((xc - b), (yc + a), (xc + b), (yc + a), colour);
           Draw_Line((xc - b), (yc - a), (xc + b), (yc - a), colour);
        }
        else
        
{
           OLED_Pixel((xc + a), (yc + b), colour);
           OLED_Pixel((xc + b), (yc + a), colour);
           OLED_Pixel((xc - a), (yc + b), colour);
           OLED_Pixel((xc - b), (yc + a), colour);
           OLED_Pixel((xc + b), (yc - a), colour);
           OLED_Pixel((xc + a), (yc - b), colour);
           OLED_Pixel((xc - a), (yc - b), colour);
           OLED_Pixel((xc - b), (yc - a), colour);
        }

        if(< 0)
        {
           P += (+ (* a++));
        }
        else
        
{
           P += (+ (* ((a++) - (b--))));
        }
    }while(<= b);
}

 void Refresh_OLED(void)
 {
  int m,k;
   for(m=0;m<OLED_PAGE;m++)  // was <8  for 128x64
   {
     OLED_SetPos(0,m);
     Delay_us(2);
     k=m*128;
     OLED_Data(RamBuffer+k,128);
   }
 }

void Raz_RamBuffer(void)
{
    int k;
    for(k=0;k< 512;k++)RamBuffer[k]=0;
     OLED_SetPos(, 0);
}

// Prints a display big number (16x16 bytes) in coordinates X Y,
// being multiples of 16. This means we have 16 COLS (0-15)
  void ShowBigNumber(unsigned char x,unsigned char  y, unsigned char N)  //16x16
  {
    unsigned char x1,v=0;
    unsigned int  adder;
    unsigned char Cc;
    OLED_Cde(0x20);
    OLED_Cde(0x00); // Horizontal
    //OLED_Cde(0x02); // Page mode
     adder=N;
      OLED_SetPos(, y);
      for(= 0;< 16;v=v+2)
        {
         Cc=Big_Numer_16x16[adder+v];
         OLED_Data(&Cc,1); //OLED_WriteDat(Cc);
          adder++;
        }
         adder=16*N;
         OLED_SetPos(, y+1);
        for(= 1;< 16;v=v+2)
        {
         Cc=Big_Numer_16x16[adder+v];
         OLED_Data(&Cc,1); //OLED_WriteDat(Cc);
          adder++;
        }
  }


//const unsigned char  points ...fleche_bas,fleche_haut,_degre,DegreC,moins
//void Affiche_Car_8x8 ( unsigned char posX, unsigned char PosY,const char *N)
void Affiche_Car_8x8 ( unsigned char posX, unsigned char PosY, char *Name )
 {   int j;
      char cc;
   //   char *pc;
    OLED_Cde(0x20);
   // OLED_Cde(0x00); // 0=horizontal mode
    OLED_Cde(0x02); // 2= page mode
    OLED_Cde(0x21); // On configre la largeur de l'ecran
    // pour forcer, limiter le retournement horizontal   voir DS figure 10.5
    OLED_Cde(0+posX);        // Colonne minimum
    OLED_Cde(7+posX);        // Colonne MAximum;
    // On configre la Hauteur d'ecran
    OLED_Cde(0x22);
    // positionement vertical entre page Y et Y+1   H=8 pixels
    OLED_Cde(PosY);
    OLED_Cde(PosY+1);
    for(j=0;j<8;j++)
     {
        tmp[j]= *(Name+j);
      }
     OLED_Data(tmp,8);
  // Resize();
  }
  

 void OLED_WriteDat
(unsigned char I2C_Dat)
{
    I2C1ADB1   = OLED_ADDR; // i2c1, 2 * adresse esclave
    while (!I2C1STAT0_BFRE) ;     // attente bus libre
    I2C1CNT = 1;
    I2C1TXB = DATA_STREAM;
    I2C1CON0_S = 1;
    while (!I2C1STAT1_TXBE) ;
    I2C1TXB = I2C_Dat;
      while (!I2C1STAT1_TXBE) ;
  }



//const unsigned char  points ...fleche_bas,fleche_haut,_degre,DegreC,moins
//void Affiche_Car_8x8 ( unsigned char posX, unsigned char PosY,const char *N)
void Affiche_Car_Speciaux_8x8( unsigned char posX, unsigned char PosY, char Num )
 {   int j;
      char cc;
   //   char *pc;
    OLED_Cde(0x20);
   // OLED_Cde(0x00); // 0=horizontal mode
    OLED_Cde(0x02); // 2= page mode
    OLED_Cde(0x21); // On configre la largeur de l'ecran
    // pour forcer, limiter le retournement horizontal   voir DS figure 10.5
    OLED_Cde(0+posX);        // Colonne minimum
    OLED_Cde(7+posX);        // Colonne MAximum;
    // On configre la Hauteur d'ecran
    OLED_Cde(0x22);
    // positionement vertical entre page Y et Y+1   H=8 pixels
    OLED_Cde(PosY);
    OLED_Cde(PosY+1);
      for(j=0;j<8;j++)
     {
        tmp[j]= *(Car_Speciaux[Num]+j);
        Delay_us(50);
      }
     OLED_Data(tmp,8);
    //   OLED_Data(Car_Speciaux[Num],8);
    // Resize();
  }
  //===================================================
  #endif

void Ds3231_Temp_CP(char mode)
  {
   // " range: -99 to +127 degree
   char msb, lsb, tmp1;
    // read the two temperature registers:
    msb=Lecture_Affichage_Registre_DS3231(0x11,0);
    lsb=Lecture_Affichage_Registre_DS3231(0x12,0);

   tmp1 = ' ';
   if (msb.B7)
   { // SIGN_bit = 1: negative
      tmp1 = '-';
      // two's complement conversion:
      msb ^= 0xFF;
      if (!lsb)
         ++msb; // required if the fractional portion is zero
      else
         lsb
.B0 = 1; // negative fract. sign, normally it is 0
   }
   else
   
{
   if (msb > 99)
   {
      msb -= 100;
      tmp1 = '1';
   }
   }
   // the first char is a space, '-' or '1':
   DS_Temp[0]=tmp1;
   //Lcd_Chr_CP(tmp);
   // convert msb (binary value) to 2 ASCII digits
   for ( tmp1 = '0' ; msb > 9 ; ++tmp1, msb -= 10 );
   // display integer portion:
   DS_Temp[1]=tmp1;
   DS_Temp[2]=msb+'0';
   // decimal point:
   DS_Temp[3]= '.';
   // compute fract. part:
   msb = '0';
   tmp1 = '0';
   if (lsb)
   {
      // positive 7,6 bits: 01(25), 10(50), 11(75)
      // negative 7,6 bits: 01(75), 10(50), 11(25)
      if (!lsb.B6)
         msb = '5'; // 50
      else
      
{
         msb = '2';
         tmp1 = '5';
         if (lsb.B0) // negative fract. (see above): 25 <> 75
            lsb.B7 = !lsb.B7;
         if (lsb.B7)
            msb = '7';
      }
   } // fract. part

   DS_Temp[4]= msb;
   DS_Temp[5]= tmp1;
  if (mode==0)  DS_Temp[6]='°'; else DS_Temp[6]= ' ';  // for LCD
   DS_Temp[7]= 'C';
   DS_Temp[8]=0;
}
 // end of Ds3231_Temp_CP()

 void BCD_To_Ascii(unsigned char cc,unsigned char * px)
 {
 *(px)=(cc>>4) + 48;
 *(px+1)=(cc & 0x0F) +48;
 *(px+2)=0;
 }




void I2C1_Write(unsigned char addr8, unsigned char addr_data, unsigned char* b, signed char n)
//------------------------------------------------------------------------------
{
  while (!I2C1STAT0_BFRE);       // attente bus libre
   I2C1PIR_PCIF=0;
  I2C1ADB1 = addr8; // adresse chip + R/W=0
  I2C1CNT =1+ n;                        // on envoie adresse data et n data
  I2C1TXB = addr_data;
  I2C1CON0_S = 1;                   // envoi Start, adresse chip+W, adresse data
  while (n--)
  {
    while (!I2C1STAT1_TXBE);
    I2C1TXB = *(b++);                     // envoi n data, Stop
  }
   while (!I2C1PIR_PCIF); // PCIF is set after the STOP
   I2C1PIR_PCIF=0;
}


void Display_Date_Time(char Visu)
{
   unsigned char Adresse,Registre;
    signed char Nb;
    int i;
    Adresse=DS3231_ADDR;
    Registre=0;
    Nb=7;

    for(i=0;i<8;i++) tmp[i]=0;
    p1=&tmp[0];
    DS3231_Read_All_Registers();
    time[0]=0;
    date[0]=0;
     BCD_To_Ascii(heure,time) ;   time[2]='H';
     BCD_To_Ascii(minute,time+);  time[5]='M';
     BCD_To_Ascii(second,time+6);   time[8]='S';time[9]=0;
     BCD_To_Ascii(jour,date); date[2]='/';
     BCD_To_Ascii(mois,date+3); date[5]='/';
     BCD_To_Ascii(Annee,date+6); date[8]=0;
     Month=Bcd2Dec(mois);
     Sec= Bcd2Dec(second);
   if( Visu==1)
   {   Print(date);  CPrint(Blancs);
       Print(time); CPrint(Blancs);
    }
  }
  
  
void MAJ_RTC
(void)
{
 int m,i,j,k;
  m=2; // passe par dessus "U;"
  // U;24;08;17;17;36;02#
  j=0;
  //Status=0;
   U1RXIE_bit=0;
   Print(Buffer1);CRLF1();
  *(Buffer1+Index1)=0;
   if ((Index1<22)&&(Index1>18))
    {
        CPrint(" Index1 = ");
        WordToStr(Index1,CRam1);
        Print(CRam1);
        CRLF1();
        for (i=2;i<Index1;i++)
        {
          if(Buffer1[i]==';')
              {
                Buffer1[i]=0;
                DateTime[j]=atoi(Buffer1+m);
              Print(Buffer1+m);CRLF1();
               j++;
               m=i+1;
              }
       }// for i
        DateTime[j]=atoi(Buffer1+m);
        jour=DateTime[0];
        mois=DateTime[1] & 0x1F;
        Annee=DateTime[2];
        heure=DateTime[3];
        minute=DateTime[4];
        jS=DateTime[5] & 0x07; // jour de la semaine
        CPrint("\r\n Jour Semaine jS =");
        ByteToStr(jS,CRam1);
        Print(CRam1);
        Envoi_Char(9);
        CPrint(JourSemaine[jS]); Envoi_Char(9);
        CPrint(" mois =");
        Month=Bcd2Dec(mois);
        if (Month>12) Month=0;
        CPrint( Douze_Mois[Month]);
        CRLF1();

        if (jS>7)
        {
             jS=0;  // error si defaut !
              CPrint("\r\nErreur sur Jour Semaine jS. \r\n");
        }
        CPrint("\r\n param Ok\r\n");
        
        second
=0;
        tmp[0]=second; //Reset second to 0 sec. and stop Oscillator
        tmp[1]=Dec2Bcd(minute); //write min
        tmp[2]=Dec2Bcd(heure); //write hour
        tmp[3]=jS; //write day of week
        tmp[4]=Dec2Bcd(jour); // write date
        tmp[5]=Dec2Bcd(mois); // write month
        tmp[6]=Dec2Bcd(Annee); // write year
        tmp[8]=0x00;
        p1=&tmp[0];
        Adr= DS3231_ADDR;
       // I2C1_Write(unsigned char addr8, unsigned char addr_data, unsigned char* b, signed char n)
        I2C1_Write(Adr,0,p1,8) ;
        Delay_ms(10);
        p1=&tmp[0];
        tmp[0]=0x0E; //Reset second to 0 sec. and stop Oscillator
        tmp[1]=0x40;  // SQW=> 1Hz
       I2C1_Write(DS3231_ADDR,0,p1,2);
      CPrint("Ecriture en bloc dans DS3231... OK\r\n");
      CRLF1();
    }
    else
    
{
    CPrint("\r\n Rappel format de cde : \"U;JJ;MM;AA;HH;MM;jS;#\" \r\n");
    CPrint(" U;24;08;17;18;36;04#  pour 24 Aout 2017  18H36 04=Jeudi\r\n\r\n");
    }
 }

    
    void DS3231_Read_All_Registers
()
    {
     //Lecture des 7 registre RTC DS3231
   // RAZ table d'echange
    for (i=0;i<10;i++) tmp[i]=;
    p1=&tmp[0]; // pointeur sur debut de table
    SQA=1;
    // choix debut RTC registre=0
    while (!I2C1STAT0_BFRE) ;
    I2C1STAT1_CLRBF = 1;
    I2C1ADB1 =  DS3231_ADDR;      // Adresse Devide avec R/W=0  ( 0xD0)
    I2C1CNT = 1;                  // Charge Nb de bytes à ecrire
    I2C1TXB = *(p1++);            // Charge l'adresse du registre concerné
    I2C1PIR_PCIF = 0;             // Raz flag STOP
    I2C1CON0_S = 1;               // Start transmission
    while (!I2C1PIR_PCIF) ;       // attente du STOP
    // lecture des 7 regitres via interruption
    while (!I2C1STAT0_BFRE) ;     // attente bus libre
    p1=&tmp[0]  ;
    I2C1PIR_PCIF=0;
    I2C1ERR=0;
    I2C1RXIE_bit=1;             // arme interrupt I2C reception
    I2C1ADB1 = (DS3231_ADDR+1); // adresse devic e+ R/W=1 )lecture en 0xD1
    I2C1CNT =7;                 // nombre de regitre à lire
    I2C1IE_bit=;              // autorise IT I2C
    I2C1CON0_S = 1;             // Start
    Delay_us(10);
    while (!I2C1PIR_PCIF) ;
    I2C1STAT1_CLRBF =0; // clear I2C1RXIF bi
    I2C1IE_bit=0;
    I2C1PIR_PCIF=0;
    SQA=0;
     second=tmp[0];
     minute=tmp[1];
     heure=tmp[2]&0x3F;
     jS=tmp[3];
     if (jS>7) jS=0;
     jour=tmp[4];
     mois=tmp[5]& 0x1F;
     Annee=tmp[6];
     tmp[7]=0;
     tmp[8]=0;
    }
 
 void I2C1_Read
(unsigned char addr8, unsigned char addr_data, unsigned char* px, signed char n)
//------------------------------------------------------------------------------
{
  while (!I2C1STAT0_BFRE);      // attente bus libre
  I2C1ADB1 = addr8; // adresse chip + R/W=0
  I2C1CNT = 1;                          // on envoie adresse data
  I2C1TXB = addr_data;
  I2C1PIR_PCIF = 0;
  I2C1CON0_S = 1;                   // envoi Start, adresse chip+R, adresse data, Stop
  while (!I2C1PIR_PCIF);
   while (!I2C1STAT0_BFRE);
  I2C1ADB1 =addr8+1;             // adresse chip + R
  I2C1CNT = n;                  // on recoit n data
  I2C1CON0_S = 1 ;            // envoi Start, adresse chip+R
  while (n>0) {
    while (!I2C1STAT1_RXBF);
    *(px++) = I2C1RXB;                     // reception n data, Stop
    n--;
  }
   while (!I2C1PIR_PCIF);
}

unsigned char Lecture_Affichage_Registre_DS3231(char n, char Imprime)
{
  static char Reponse;
    while (!I2C1STAT0_BFRE) ;
    I2C1STAT1_CLRBF = 1;
    I2C1ADB1 =  DS3231_ADDR;      // Adresse Devide avec R/W=0  ( 0xD0)
    I2C1CNT = 1;                  // Charge Nb de bytes à ecrire
    I2C1TXB = n;            // Charge l'adresse du registre concerné
    I2C1PIR_PCIF = 0;             // Razflag STOP
    I2C1CON0_S = 1;               // Start transmission
    while (!I2C1PIR_PCIF) ;       // attente du STOP
    //lecture I2C
       while (!I2C1STAT0_BFRE) ;  // attente bus libre
       p1=&tmp[0]  ;
       I2C1PIR_PCIF=0;
       I2C1ERR=0;
       I2C1IE_bit=1;           // autorise interrupt I2C
       I2C1RXIE_bit=1;         // arme interrupt I2C reception
       I2C1ADB1 = (DS3231_ADDR+1);
       I2C1CNT =1;
       I2C1IE_bit=;
       I2C1CON0_S = 1;
       Delay_us(10);
       while (!I2C1PIR_PCIF) ;
       I2C1STAT1_CLRBF =0; // RAZ du bit interrupt I2C1RXIF
       I2C1IE_bit=0;       // inhibe IT I2C
       I2C1PIR_PCIF=0;
       SQA=0;
       Reponse=tmp[0];  // recupère la valeur Minute de la RTC
     if (Imprime==1)
       { 
        BCD_To_Ascii
(tmp[0],CRam1);
        Print(CRam1); Envoi_Char(TAB);
        }
       return Reponse;
      // CRLF1();
  }
  

void My_ADC_Init 
()
{
// basic acquisition
  ADCON0.B2=1; // right justified  FM bit
  ADON_bit=1; // ADCON0.B7
  ADCON0.GO_nDONE=1;
  ADCON2=0;
  ADCON3=0;
  ADCLK=63; //  FOSC/128   ADC CLOCK selection.    page 623

  //b7-5=0   b4=NREF=0=VREF- conneted to VSSS.    bit 3-2=0
  // PREF bit 1-0    11=VREF+ connected to Fixed voltage ref FVR
   ADREF=0b00000011;
   ADPCH = 0x01; //RA1 is Analog channel
   //ADPCH=0b00010010;// = ANC2       page 623
   ADPREH=0b0000010; // ADREF=0b0000011;
   ADACQL=64;
   ADACQH=2;
   ADCAP=;
   ADRPT=0;
   ADCNT=0;
   ADFLTRH=0;
   ADON_bit=1; // ADCON0.B7
   ADFLTRL=0;

}

//------------------------------------------------------
void main(void)
//------------------------------------------------------
{

  OSCCON1 = 0x60;   // Div =1:1
  OSCFRQ = 0x08;        // FOSC = 64MHz

  ANSELA  = 0x02;
  TRISA = 0b10000011;
  PORTA=0;
  Led_Dir=0;
  SQA_Dir=0;    // declencheur SQA analyser
  ANSELB = 0x00;     // pins numériques
  ANSELC = 0x00;     // pins numériques
  TRISC=0b10000011;
  Test_Presence_Device_Dir =1;
  RTC_Forcee_Dir=1;
  
  for 
(i=0;i< sizeof(Buffer1);i++)Buffer1[i]=0;
  for (i=0;i<sizeof(tmp);i++) tmp[i]=0;
  p1=&tmp[0];
  p2=&Buffer1;


  SLRCONA.B6=0; // clockout 16Mhz
  // uart1 PINS
  RC6PPS  = 0x13;      // tx1 -> C6
  U1RXPPS = 0x17;      // rx1 <- C7
  // speed
  U1BRGL = 0x40;   //0x40       0x0340 => 832
  U1BRGH = 0x03; // BRGH 3;
  // uart1 : BRGS=1, Auto-baud disabled,TXEN =1   RXEN=1  MODE=0=// Asynchronous 8-bit UART mode
  U1CON0  = 0xb0;
  U1CON1  = 0x80;  // uart1 ON   WUE=0
  //U1CON2 = 0x80; // RUNOVF =1     RX input shifter continues to synchronize with Start bits after overflow condition
  U1ERRIE=0; // 0b00001010; // FERIE=1 Framing Error RXFOIE=1 Receive FIFO Overflow
  U1FIFO=0;
  
  
// Change IVTBASE if required
  IVTBASEU = 0x00; // Optional
  IVTBASEH = 0x00; // Default is 0x0008
  IVTBASEL = 0x08;

  CPrint("\r\n Presentation : \r\n");
  for (i=0;i<9;i++)   CPrint(Messages[i]);
  SWDTEN_bit=0;
  CRLF1();
  txt=&TEXTE[0];

   CPrint(" Init speciale  I2C1 Hardware (sans MC)  \r\n");
   I2C1_Hw_Init();
  
   CPrint
( " Etat pin < Test Presence Device> =");
   Envoi_Char(PORTC.B1+48);
   CRLF1();
   if  (Test_Presence_Device==0) // RC1 Pin
   {
     CPrint(" Test presence device(s) sur le bus I2C1 avec RC1=0 \r\n");
     Delay_ms(100);
     j=I2cScan();
     if (j>0)
     {
       CRLF1();
       CPrint(" Device(s) trouvés sur le bus\r\n");
        for (i=0;i<j;i++)
        {                     //0123456789012345678
          if( I2C_Adresses_Devices[i]==0) break;
          strConstRamCpy(CRam1," Device #1 at @xx \r\n");
          *(CRam1+9)=i+49;
          ByteToHex( I2C_Adresses_Devices[i],CRam1+15);
          *(CRam1+17)=' ';
          Print (CRam1);
        }
     }
      else
      
{
        CRLF1();
        CPrint(" AUCUN Device(s) trouvés sur le bus\r\n");
        CRLF1();
      }
    }
    else
    CPrint
(" donc ,Pas de test presence Device\r\n");

  //------------------------------------------------------

  I2C1IE_bit=0;
  I2C1TXIE_bit =0;
  I2C1RXIE_bit =0;
  Init_Timer1();
  GIE_bit=1;
  CPrint(" #1 Active sortie SQW=1Hz: \r\n");
  Wait_TimeOut_Only(30,0);
  CPrint(" GO\r\n");
  tmp[0]=0x0E; tmp[1]=0x40; // set SQW output  Start oscillateur
  p1=&tmp[0];
  I2C1_Write(DS3231_ADDR,0,p1,2);
  CPrint(" ok\r\n");
   //-----------------------

    Delay_ms(100);
    for (i=1;i<32;i++) tmp[i]=0;
    CPrint( " Etat pin RC0 = ");
    Envoi_Char(PORTC.B0+48);
    CRLF1();
    if(RTC_Forcee==0)    // RC0 input
    {
     CPrint( " Init RTC Forcee à samedi 02/03/21 18:46:57 via  RC0=0 \r\n");
     tmp[0]=0x57;  //second
      tmp[1]=0x16;  //write min
       tmp[2]=0x18; //write hour;
        tmp[3]=0x46;  ///write day of week
         tmp[4]=0x02;    // write date
          tmp[5]=0x03;      // write month
            tmp[6]=0x21;    // write year
            tmp[7]=0x00;
     p1=&tmp[0];
     Adr= DS3231_ADDR;
     I2C1_Write(Adr,0,p1,8);
     SQA=0;
    }
    CPrint(" Lecture et affichage individuel des 7 Registres DS3231 \r\n");
    j=0;
    do
    
{
    CPrint(" Registre #");
    Envoi_Char(j+48);
    Envoi_Char(TAB);
    cx=Lecture_Affichage_Registre_DS3231(j,1);
      CRLF1();
    j++;
    }
    while(j<8) ;
  
    CPrint
(" ADC 12bit  Init Advenced sur EA1\r\n");
    //My_ADC_Init();
    //  ADC_Init_Advanced(_ADC_INTERNAL_VREFL | _ADC_INTERNAL_FVRH1);
    ADC_Init_Advanced(_ADC_INTERNAL_VREFL | _ADC_INTERNAL_VREFH);   // 0 à VCC

   CPrint(" ========== main Loop ======\r\n");
   do
   
{
     Display_Date_Time(1);
     // display Temperature interne RTC
     Ds3231_Temp_CP(0);  // 0=pour UART  1=pour LCD
     Envoi_Char(TAB);
     Print(DS_Temp);
     Envoi_Char(TAB);

     EA1= ADC_Get_Sample(1);
     WordToStr(EA1,CRam1);
    //  OLED_SetPos(1,6);
    // OLED_ShowStr(1,6,CRam1,1);

     txt=&TEXTE[0];    //012345678901234567890
     strConstRamCpy(txt," ;  EA1(12b)=         ");
     strncpy(txt+15,CRam1,5);
     Print(txt);
     CRLF1();
     
     Raz_Buffer1
() ;   // arme Interrupt UART Rx
     Delay_ms(1000);

    if (Flag_Buffer1==1)
    {
       Flag_Buffer1=0;
       p2=&Buffer1[0];
        //U;03;03;21;15;14;03;#
      if (  (*(p2)=='U') && (*(p2+1)==';') && ( *(p2+19)==';') )
      {
        CPrint("\r\n MAJ RTC \r\n");
      //  Print(Buffer1);    CRLF1();
        MAJ_RTC();
        CRLF1();
        p2=0;
      }
      if ((*(p2)=='H') && (*(p2+1)=='e') && ( *(p2+2)=='l') )
      {
        CPrint("\r\n Help Commandes :\r\n");
        CPrint(" MAJ RTC  \r\n");
        CPrint(" ex: U;03;03;21;15;14;03;#  pour 03 mars 2021 , 15H14  Mercredi \r\n");
        CPrint(" Help \r\n");
        Print(Buffer1);    CRLF1();
        p2=;
      }
      // autre tests ...
     }
    } while (1);
}


l ' execution sur terminal
Execution_P18F27K42_I2C1_HW_RTC_sans_MC_Lib_2021_0304.jpg


Statistics
SANS PPS
Stat_P18F27K42_I2C1_HW_RTC_sans_MC_Lib_2021_0304.jpg


avec lib mikroc UART1 Hw + PPS (d'office!)
Stat_P18F27K42_I2C1_HW_RTC_sans_MC_Lib_avec_PPS.jpg


le projet mikroC

_18F27K42_UART1_ADC1_RTC_I2C_Hw_SANS_MC_lib_2021.zip
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Aide toi, le ciel ou FantasPic t'aidera

Test mini OLED SSD1306 20x10mm 128x32 18F27K42
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#66 Message par paulfjujo » sam. 6 mars 2021 19:54

bonsoir,


Suite et fin, OUF !

RTC et OLED ..OK SANS LIB MikroC ! pour gerer l'UART,l'I2C et PPS
une petite video

je vais pouvoir passer à autre chose et continuer à utiliser ce 18F27K42 , vraiment costaud .
Aide toi, le ciel ou FantasPic t'aidera

Test mini OLED SSD1306 128x32 18F27K42 [Resolu]
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#67 Message par satinas » sam. 6 mars 2021 20:19

Bonsoir, joli travail

J'ai lu tout son datasheet en prenant des notes, au début en résumant les fonctionnalités, à la fin je n'écrivais que le nom des chapitres qui n'en finissaient plus :-)
Pas mal de choses, la table de vecteurs d'interruption, le DMA, la capture SMT, l'ADCC, le DAC, le capteur de température, le calcul CRC 16 bits qui doit pouvoir raccourcir les temps d'accès sdcard, ...

Test mini OLED SSD1306 128x32 18F27K42 [Resolu]
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#68 Message par paulfjujo » ven. 19 mars 2021 18:17

bonjour à tous ,

je continue sur ce post, car concerne encore le 18F27K42 et LCD OLEDs ..
je suis repassé sur MPLABX + XC8 , et rajouté La RTC , + gestion de 2 OLEDS SSD1306, qui malgré leur point commun
qui serait le driver SSD1306 , ne se comporte pas pareil .. d'ou l'echec que j'avais auparavant..
cette version permet l'usage de l'un ou de l'autre , via l'etat de la pin RB1 ,pour le choix de type OLED
(le model 28x28mm 0,96" 1ere ligne jaune et 3 suivantes bleues (douteux 128x32 au lieu de 128x64) , ou le mini OLED 20x10mm 128x32 )
en modifiant certains parametres de la fonction OLED_Init()

Rajout de la RTC DS3231
et RX UART1 interrupt ..

remarques :
la "presence test device n'est plus possible " ... je suppose à cause de l'usage de MCC et ressources associée I2C
Ma gestion RX UART1 me semble pas tres claire, vis à vis de l'existant crée par MCC et Ressource UART
Ma seule consolation est que l'I2C1 HW va bien ..

les warning 373 avec l'option option compilateur -wconversion ne sont plus affichés...
ainsi que ceux-ci
#pragma warning disable 520
#pragma warning disable 1510
#pragma warning disable 759
#pragma warning disable 2053
ce qui laisse paraitre une compilation plus propre .. la poussiere sous le tapis !
exit Je SAIS ! il faudrait TOUT FAIRE pour corriger ces warnings !

mais pour l'instant , j'hesite encore à renoncer à MikroC pour passer à 100% sur MPLABX - ou Necto Studio !! :eek:
Le passage de l'un ,à l'autre n'est pas super évident .. meme si on reste en C
Je regrette d'ailleur le C18 !!!! ( tiens ! je me repète souvent ! ..)

a Satinas :
Q1:
Penses-tu qu'on puisse faire ce test "presence device" avec tout l'attirail apporté par MCC et Ressources I2C
sachant que les fonctions I2C sont bien encapsulées..
ou faut-il passer à un include asm

Code : Tout sélectionner


char I2C1_DevicePresent
(uint8_t address)
{
   static char Status;
    SQA = 1 ;                             // debug bit high
    I2C1PIRbits.PCIF = 0;                // clear STOP bit flag
    I2C1ADB1 = address;  // load slave addr and R/W
    I2C1CNT = 1; 
    I2C1CON0bits
.= 1;                 // send START + addr
    while (I2C1PIRbits.PCIF == 0);      // wait for STOP                      
    Status=!I2C1CON1bits.ACKSTAT;
     SQA = 0 ; // debug bit low
    return Status;



Q2:
Quant je fait un Package ( click droit sur le titre du projet)
j'obtiens bien un zip du projet avec les sources et MCC files, mais il n'y a pas le résultat de compilation, pourtant bien présent.
directory "dis" (distribution non inclus) donc pas de *.HEX
y-a-t-il une option à cocher ou paramètre à renseigner quelque part ?


projet MPLABX XC8 (Packing + rajout manuel du *.hex dans le Zip)
_18F27K42_OLED_SSD1306_RTC_UART_IT_RX_XC8_2021-03.zip

plus de detail sur ma page


je me retouve maintenant avec 3 solutions testées OK avec ce MCU,... il est donc temps de passer à autre chose..
MikroC I2C1 Soft
MikroC I2C1 Hardw SANS lib MikroC
MPLABX I2C1 Hardw
d'ici que ça finisse avec une 4em 100% ASM ... (TempsX ?)
exit dehors!!
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Aide toi, le ciel ou FantasPic t'aidera

Test mini OLED SSD1306 128x32 18F27K42 [Resolu]
Temps-x
Avatar de l’utilisateur
Expert
Expert
Messages : 2595
Enregistré en : juillet 2016
Localisation : Terre

#69 Message par Temps-x » ven. 19 mars 2021 18:39

Bonsoir paulfjujo, satinas, et tout le forum,

:+1:
paulfjujo a écrit :Source du message d'ici que ça finisse avec une 4em 100% ASM ... (TempsX ?)


Je sais tu attends une version 100% ASM, je vais en faire une, mais surement pas avec un écran Oled 128x64, elle sera faite avec un MCP9600

==> A+
:roll: Les requins, c'est comme le langage ASM, c'est le sommet de la chaîne alimentaire. :wink:

Test mini OLED SSD1306 128x32 18F27K42 [Resolu]
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#70 Message par satinas » ven. 19 mars 2021 19:53

Bonsoir
Faire le test ou scan device, cela doit être possible avec la flopée de fonctions MCC, je regarderai.
Je suis pas un expert de MCC, trop touffu. C'est quand même la bonne solution pour faciliter la programmation des fonctionnalités du Pic sans partir de zéro. Je l'utilise avec Mplab Xpress en cas d'impasse, mais une fois la situation débloquée je repars sur mon propre code.
C'est drôle, en compilant ton projet MpLabX, on trouve aussi des warnings signedness dans les fichiers MCC.
Pour le Package, je pense qu'il ne met dedans que les sources et le makefile du projet.

Tu as essayé la fonction I2C1_DevicePresent(uint8_t address) après avoir exécuté le SYSTEM_Initialize() de MCC ?


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 30 invités