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
Temps-x
Avatar de l’utilisateur
Expert
Expert
Messages : 2617
Enregistré en : juillet 2016
Localisation : Terre

#21 Message par Temps-x » dim. 24 janv. 2021 14:01

Bonjour paulfjujo, satinas, et tout le forum,

:eek:
satinas a écrit :Source du message Cela peut intéresser Temps-x car entre C et ASM il y a pas trop de différence.

:sifflotte:

Merci ! satinas.... encore une fois de plus tu nous à bien rendu service,

Mais maintenant je ne vais pas me contenter de prendre le tout et de faire fonctionner mon écran Oled 128x64 en I²C (car ça j'aime pas, j'aime bien comprendre ce que je fais)

Certain dirons : du moment que ça marche ça me suffit.... ouais, mais c'est la seule façon de ne pas savoir le faire pour un autre cas de figure.

Rassure moi satinas .... tu ne dors pas avec ton clavier. exit

PS : La source ASM se trouve dans le zip que tu à joints, 18F27K42_Oled.zip surement généré automatiquement par le compilateur C

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

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

#22 Message par satinas » dim. 24 janv. 2021 14:19

Je dors très bien, merci, mais pas trop longtemps :) et je sais bien que tu préfères comprendre et faire par toi même :)
Tu as déjà fait toutes les parties initialisation et graphismes de l'afficheur.
Ce qui peut t'intéresser se sont les fonctions I2cInit() OledCmd() et OledData(), tu dois avoir des sous-programmes similaires.
Ces fonctions bien qu'en C sont lisibles car elles ne font que tester des bits de registres et écrire des registres.
Les while ne sont rien d'autre que des btfss ou btfsc.
On devrait pouvoir éviter d'envoyer le Start à la main, comme expliqué plus haut. Je n'y suis pas arrivé.
Et pour la vitesse j'ai constaté 100kHz, sans savoir où c'est défini exactement, donc pour passer à 400kHz, faut chercher :)

Test mini OLED SSD1306 20x10mm 128x32 18F27K42
Temps-x
Avatar de l’utilisateur
Expert
Expert
Messages : 2617
Enregistré en : juillet 2016
Localisation : Terre

#23 Message par Temps-x » dim. 24 janv. 2021 16:28

Re

satinas a écrit :Source du message Et pour la vitesse j'ai constaté 100kHz, sans savoir où c'est défini exactement, donc pour passer à 400kHz, faut chercher :)


Si j'ai compris c'est le registre I2C1CLK, pour plus d'information lire le chapitre 2 du cours de Monsieur Bigonoff.

Code : Tout sélectionner


    movlw 
B'00000011'                     100kHz
    movwf I2C1CLK 




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

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

#24 Message par paulfjujo » dim. 24 janv. 2021 17:19

bonjour Satinas,Temps-X et à tous

Merci ! Satinas pour ton exemple qui tourne OK sur mon OLED 128x32
effacement / remplissage de l'ecran OK
il faut que je modifie un peu d'init pour le passer en 128x32 au lieu de 128x64
mais déja j'ai bien un affichage (tronqué) des caracteres A ..à ..Q car sur 2 lignes au lieu de 4 , puisque ecran defini en 64 sens Y..
:-D c'est bon signe !

Used RAM (bytes): 135 (2%) Free RAM (bytes): 8035 (98%)
Used ROM (bytes): 680 (1%) Free ROM (bytes): 130392 (99%)
:+1: 680 bytes
alors que MikroC rajoute d'office la lib PPS de 1580 bytes avec la lib I2C1 Hardware ou si je veux utiliser la lib MikroC UART1 !!!

je vais aussi verifier si mon probleme n'etait pas dù ,à une mauvaise init de l'OLED ( puisque c'etait OK coté RTC).
et que cette meme init OLED était OK, en version I2C Software ! ou avec MPLABX !!

je cherche aussi à trouver le bon parametre permettant de detecter si le(s) device(s) est (sont) bien sur le bus
RTC DS31231, EEPROM module RTC (et l'OLED)
à ma connaissance il existe deja une fonction timeout sur cet I2C specifique .
et enfin à faire une lecture .. SANS la lib I2C Hardw MikroC .
Aide toi, le ciel ou FantasPic t'aidera

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

#25 Message par satinas » lun. 25 janv. 2021 09:47

Bonjour,

voir page 569 du datasheet.
On peut simplifier, pas la peine d'attendre la fin du Start pour placer le premier octet data dans le registre I2C1TXB.
On remplit I2C1TXB, ensuite on génère le Start, l'adresse et la data partent dans la foulée. Ensuite, on a juste à scruter le bit I2C1STAT1bits.TXBE, pour remplir I2C1TXB avec les autres data. Quand I2C1CNT arrive à 0, le Stop est généré.

Code : Tout sélectionner

//--------------------------------------------------------------------------------------------
void OledCmd(unsigned char c)
//--------------------------------------------------------------------------------------------
{
  while (!I2C1STAT0bits.BFRE) { } // attente bus libre
  I2C1CNT = 2;                    // on envoie 2 octets data
  I2C1TXB = CMD_SINGLE;
  I2C1CON0bits.S = 1;             // envoi Start, adresse, CMD_SINGLE
  while (!I2C1STAT1bits.TXBE) { }
  I2C1TXB = c;                    // envoi commande, Stop
}

//--------------------------------------------------------------------------------------------
void OledData(unsigned char *b, unsigned char n)
//--------------------------------------------------------------------------------------------
{
  while (!I2C1STAT0bits.BFRE) { } // attente bus libre
  I2C1CNT = 1+n;                  // on envoie 1+n octets data
  I2C1TXB = DATA_STREAM;
  I2C1CON0bits.S = 1;             // envoi Start, adresse, DATA_STREAM
  while (n--) {                   // envoi n data, Stop
    while (!I2C1STAT1bits.TXBE) { }
    I2C1TXB = *b++;
  }
}


Pour le scan, j'ai trouvé ça, on n'envoie que l'adresse et on teste la réponse ACK ou NAK de l'esclave.

Code : Tout sélectionner

//--------------------------------------------------------------------------------------------
void I2cScan()
//--------------------------------------------------------------------------------------------
// Scan bus I2C, envoi Start + adresse + Stop
{
  unsigned char addr;
  for (addr=0; addr<128; addr++) {
    while (!I2C1STAT0bits.BFRE) { }       // attente bus libre
    I2C1ADB1 = (unsigned char)(addr<<1);  // 2 * adresse esclave
    I2C1CNT  = 0;                         // aucun octet data
    I2C1CON0bits.S = 1;                   // envoi Start et adresse
    __delay_ms(10);
    if (!I2C1CON1bits.ACKSTAT) {
      ...                                 // l'adresse i2c répond
    }
  }
}

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

#26 Message par paulfjujo » lun. 25 janv. 2021 15:14

bonjour Satinas, et à tous,


J'ai essayé le test de decouverte devices sur le bus ...NIB
ne marche pas ??

compilation conditionelle pour rester dans la limite des 2K
#define Limited_MikroC_2K // 1704 bytes Reduction table ascii au 26 lettres majuscules
#ifndef Limited_MikroC_2K //3827 bytes ROM 3029 sans le (BAD) Test_Presence

(0.000) Init speciale I2C1 Hardware
(0.029) Test presence device(s) sur le bus I2C1
(1.706)
(0.018) AUCUN Device(s) trouvés sur le bus
(0.020)
(0.000) Oled SSD1306 128x32 init
(2.745)
(0.019) Affiche lettres A B C ...Q
(0.000) avec Write_Char_At(X en pixel (0 à 127), ligne Y (0 à 3),code ascii char)


Code : Tout sélectionner


 
#define Version "2021_0126"
 // V.O. Myproject.c by SATINAS   680 bytes  seulement
 
#define Limited_MikroC_2K        // 1704 bytes     Reduction table ascii au 26 lettres majuscules
#ifndef Limited_MikroC_2K        //3827 bytes ROM     3029 sans le (BAD) Test_Presence
#define  With_UART1
#define With_Interrupts
#define Test_Presence      // BAD test !!!!!
#define With_Timers
#endif

#include "ssd1306.h"

#define OLED_ADDR   0x78                // oled i2c 0x3C<<1
#define OLED_PAG    8                   // oled 32*128
#define OLED_COL    128

#define CR 13    //0x0D
#define LF 10
#define TAB 9
#ifndef Byte
#define Byte unsigned char
#endif
#ifndef Word
#define Word unsigned int
#endif

sbit I2C1CON0_EN     at I2C1CON0.B7;
sbit I2C1CON0_S      at I2C1CON0.B5;
sbit I2C1STAT0_BFRE  at I2C1STAT0.B7;
sbit I2C1STAT1_TXBE  at I2C1STAT1.B5;

//0 = Acknowledge was received for most recent transmission  1 = No Acknowledge was not received
sbit I2C1CON1_ACK at I2C1CON1.B6;
sbit I2C1CON2_ADB at I2C1CON2.B4;

sbit Led at LATA.B4;
sbit Led_Dir at TRISA.B4;
sbit SQA at LATA.B3;
sbit SQA_Dir at TRISA.B3;

 
#ifdef Limited_MikroC_2K
 
const unsigned char font_regular_6x8[26][6]=     //156 bytes
 
{
 
#else
const unsigned char font_regular_6x8[96][6]=     //576 bytes
{
    
0x000x000x000x000x000x00,   // sp
    
0x000x000x000x2f0x000x00,   // !
    
0x000x000x070x000x070x00,   // "
    
0x000x140x7f0x140x7f0x14,   // #
    
0x000x240x2a0x7f0x2a0x12,   // $
    
0x000x620x640x080x130x23,   // %
    
0x000x360x490x550x220x50,   // &
    
0x000x000x050x030x000x00,   // '  élidé
    
0x000x000x1c0x220x410x00,   // (
    
0x000x000x410x220x1c0x00,   // )
    
0x000x140x080x3E0x080x14,   // *
    
0x000x080x080x3E0x080x08,   // +
    
0x000x000x000xA00x600x00,   // ,
    
0x000x080x080x080x080x08,   // -
    
0x000x000x600x600x000x00,   // .
    
0x000x200x100x080x040x02,   // /
    
0x000x3E0x510x490x450x3E,   // 0
    
0x000x000x420x7F0x400x00,   // 1
    
0x000x420x610x510x490x46,   // 2
    
0x000x210x410x450x4B0x31,   // 3
    
0x000x180x140x120x7F0x10,   // 4
    
0x000x270x450x450x450x39,   // 5
    
0x000x3C0x4A0x490x490x30,   // 6
    
0x000x010x710x090x050x03,   // 7
    
0x000x360x490x490x490x36,   // 8
    
0x000x060x490x490x290x1E,   // 9
    
0x000x000x360x360x000x00,   // :
    
0x000x000x560x360x000x00,   // ;
    
0x000x080x140x220x410x00,   // <
    
0x000x140x140x140x140x14,   // =
    
0x000x000x410x220x140x08,   // >
    
0x000x020x010x510x090x06,   // ?
    
0x000x320x490x590x510x3E,   // @
    #endif
    
    
0x000x7C0x120x110x120x7C,   // A
    
0x000x7F0x490x490x490x36,   // B
    
0x000x3E0x410x410x410x22,   // C
    
0x000x7F0x410x410x220x1C,   // D
    
0x000x7F0x490x490x490x41,   // E
    
0x000x7F0x090x090x090x01,   // F
    
0x000x3E0x410x490x490x7A,   // G
    
0x000x7F0x080x080x080x7F,   // H
    
0x000x000x410x7F0x410x00,   // I
    
0x000x200x400x410x3F0x01,   // J
    
0x000x7F0x080x140x220x41,   // K
    
0x000x7F0x400x400x400x40,   // L
    
0x000x7F0x020x0C0x020x7F,   // M
    
0x000x7F0x040x080x100x7F,   // N
    
0x000x3E0x410x410x410x3E,   // O
    
0x000x7F0x090x090x090x06,   // P
    
0x000x3E0x410x510x210x5E,   // Q
    
0x000x7F0x090x190x290x46,   // R
    
0x000x460x490x490x490x31,   // S
    
0x000x010x010x7F0x010x01,   // T
    
0x000x3F0x400x400x400x3F,   // U
    
0x000x1F0x200x400x200x1F,   // V
    
0x000x3F0x400x380x400x3F,   // W
    
0x000x630x140x080x140x63,   // X
    
0x000x070x080x700x080x07,   // Y

  #ifdef Limited_MikroC_2K
     
0x000x610x510x490x450x43   // Z
     
};
    
#else
    
0x000x610x510x490x450x43,   // Z
    
0x000x000x7F0x410x410x00,   // [ 91
    
0x000x020x040x080x100x20,    // \92
    
0x000x000x410x410x7F0x00,   // ]
    
0x000x040x020x010x020x04,   // ^
    
0x000x400x400x400x400x40,   // _
    
0x000x000x010x020x040x00,   // ' accens
    
0x000x200x540x540x540x78,   // a
    
0x000x7F0x480x440x440x38,   // b
    
0x000x380x440x440x440x20,   // c
    
0x000x380x440x440x480x7F,   // d
    
0x000x380x540x540x540x18,   // e
    
0x000x080x7E0x090x010x02,   // f
    
0x000x180xA40xA40xA40x7C,   // g
    
0x000x7F0x080x040x040x78,   // h
    
0x000x000x440x7D0x400x00,   // i
    
0x000x400x800x840x7D0x00,   // j
    
0x000x7F0x100x280x440x00,   // k
    
0x000x000x410x7F0x400x00,   // l
    
0x000x7C0x040x180x040x78,   // m
    
0x000x7C0x080x040x040x78,   // n
    
0x000x380x440x440x440x38,   // o
    
0x000xFC0x240x240x240x18,   // p
    
0x000x180x240x240x180xFC,   // q
    
0x000x7C0x080x040x040x08,   // r
    
0x000x480x540x540x540x20,   // s
    
0x000x040x3F0x440x400x20,   // t
    
0x000x3C0x400x400x200x7C,   // u
    
0x000x1C0x200x400x200x1C,   // v
    
0x000x3C0x400x300x400x3C,   // w
    
0x000x440x280x100x280x44,   // x
    
0x000x1C0xA00xA00xA00x7C,   // y
    
0x000x440x640x540x4C0x44,   // z
    
0x140x140x140x140x140x14,    // horiz lines   123
    
0x0F0x090x0F0x090x000x00    //°C            124
  
};
#endif




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

unsigned int i,j,k,l,m,n;
volatile unsigned char Temp=0;
volatile unsigned char Buffer1[MAX_LEN1];
unsigned char p1;
unsigned char p2;
unsigned char CRam1[MAX_LEN2];
unsigned char TEXTE [MAX_LEN3];
unsigned char *txt;

volatile struct chbits {   // 8 flags
       
unsigned FrameErr:1;
       
unsigned RAZ:1;
       
unsigned Tmr0_Elapsed:1;
       
unsigned Togle:1;
       
unsigned Tmr1_Elapsed:1;
       
unsigned Gie:1;
       
unsigned Full:1;
      
unsigned Melodie:1;
 }
Drapeaux ;

unsigned char I2C_Adresses_Devices[8];
unsigned char buff[OLED_COL];
char tmp[16];
volatile int Flag_Buffer1;
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;
volatile int Flag_Timer0=0;
volatile int Flag_Timer1=0;
volatile int Flag_Timer2=0;


void I2cInit(void);
void OledInit(void);
void OledFill(unsigned char flag);
void OledCmd(unsigned char c);
void OledData(unsigned char *bunsigned char n);
#define OledSet(c,d)  OledCmd(c),OledCmd(d)
#define OledPag(first,last) OledCmd(SET_PAG),OledCmd(first),OledCmd(last)
#define OledCol(first,last) OledCmd(SET_COL),OledCmd(first),OledCmd(last)
void OLED_SetPos(unsigned char x1unsigned char y1);
void Write_Char_At(unsigned char X,unsigned char Yunsigned char C);

 
#ifdef With_UART1
void CRLF1(void) ;
void strConstRamCpy(unsigned char *dest, const code char *source);
#endif

   #ifdef  With_Interrupts
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 ;
        }
        
PIR3.TMR0IF0;
    }
     
//RX UART IT
     
if (( U1RXIF_bit==1) && ( U1RXIE_bit==1))  //RC1IE_bit==1) )
     
{
      
// U1TXB=='?';
      //c1 = UART1_Read();
      
c1=U1RXB;

      if (
U1ABDOVF_bit==1)    // voir parag  31.2.2.4   page 479
      
{
       
U1ABDOVF_bit ;
       
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-1Flag_Buffer1=2;
        
TMR2IE_bit=0;
       }
       else
       {
       
Flag_Buffer1=0;
       
Buffer1[i1]=c1;
       
Index1=i1;
       
i1++;
       }
     }
   
#ifdef With_Timers
     
if (( TMR1IE_bit) && (TMR1IF_bit))
    {
     
//  U1TXB='.';
      
Cpt1--;
      if (
Cpt1 <1)   // x25ms at 64MHz
      
{
       
TMR1ON_bit=0;
       
TMR1IE_bit=0// stop comptage  timer1
       
Flag_Timer1=1;
      }
      else
      {
        
TMR1H         0x3C;
        
TMR1L         0xB0;
      }
       
TMR1IF_bit  0;
    }
    
#endif
}
    
#endif

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

void Envoi_char(char c)
{
 while(
U1TXIF_bit==0);
  
U1TXB=c;
  }
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;
   
Delay_us(10);
 }
}


void CRLF1()
{
Envoi_char(CR);
Envoi_char(LF);

}
 
#endif
 
 #ifdef With_Interrupts
void Raz_Buffer1()
{
        
// nettoye le debut de buffer ,car utilisé pour init BT
        
for(i1=0;i1<MAX_LEN1-1;i1++) Buffer1[i1]=0;
        
Buffer1[0]=0;
        
i1=0;
        
p1=0;
        
Index1=0;
        
Flag_Buffer1 =;
        
//c1=RCREG1;
        
c1=0;
        
U1RXEN_bit=1;
         
U1ERRIR 0x00;
         
U1ERRIE 0x00;
        
U1RXIE_bit=1;
        
//RC1IE_bit = 1;
}
#endif




//------------------------------------------------------
void I2cInit(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    = 0x06;      // i2c1, 0110 TMR2 post scaled output      BAD !!!
    
I2C1CLK    0x03;      // i2c1, 0011 MFINTOSC  500Khz  ..OK
 // I2C1CLK =0x01;  // HFINTOSC  100KHz  BAD ????
 // I2C1CLK =0x00;  // FOSC/4   16MHz BAD
 // SLRCONC=0b11100111; //RC3 ,RC4 maximum rate
  
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
  
I2C1ADB1   OLED_ADDR// i2c1, 2 * adresse esclave
  
I2C1CON0_EN 1;        // i2c1 on
  //I2C1BTO=0x01;

}



void My_OLED_Init(void)
{
//SSD1306.pdf
//Software Configuration

       
OledCmd(0xAE); //display off
       
Delay_ms(100);
       
OledCmd(0xAF); //display on
       
Delay_ms(10);
       
OledCmd(0xB0);// Set GDDRAM Page start adresse [2:0]  0 à 7
       
OledCmd(0x00);   // mini 0
       
OledCmd(0x03);   // maxi
       //  OledCmd(0x07);   // maxi  pour 128x64
       
OledCmd(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
        
OledCmd(0x00); //    Page Addressing Mode (RESET)
        
OledCmd(0x21); // Setup column start and end address
        
OledCmd(0);   //A[6:0] : Column start address, range : 0-127d,(RESET=0d)
        
OledCmd(0x7F);  // B[6:0]: Column end address, range : 0-127d,(RESET =127d)
        
OledCmd(0x22);//  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)
        
OledCmd(0x00);
        
OledCmd(0x03);     //was 0x07
       // OledCmd(0xA0); //--set segment re-map colum 0 to SEG 0     de droite -> gauche
       
OledCmd(0xA1); //--set segment re-map to 127     de gauche -> droite
       
OledCmd(0xA4);//command enable display outputs according to the GDDRAM contents.
       //  OledCmd(0xA5);//command forces the entire display to be “ON”, regardless of the contents of the display data RAM.
       
OledCmd(0xA6);//normal display
       //  OledCmd(0xA7);//reverse display
       
OledCmd(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
       
OledCmd(0xD3); //--set start line address 40h =  set   to 0
       
OledCmd(0x40);  //0x40  ou 0x3F
       // was     OledCmd(0x00);
       //0xD3,0x3F, // DISPLAY offset ROW0 - L0xD3,0x00,leaves one row of pixels at top. 0xD3,0x3F is better
       
OledCmd(0xD5); //--set display clock divide ratio/oscillator frequency
       
OledCmd(0x80); //--set divide ratio   80h
       
OledCmd(0xA8); //--set multiplex ratio to 63
       
OledCmd(0x3F); //  was 3F
       
OledCmd(0xD6); //-- This command is to set the vcommon signals padconfiguration.
       
OledCmd(0x80); // --set divide ratio   80h
       
OledCmd(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 )
       
OledCmd(0x22); //  22h --reset values   22h
       //0xDA, (C.OLED_HEIGHT==64)?0x12:0x02,
       
OledCmd(0xDA); //--set com pins hardware configuration
       
OledCmd(0x20);  // was 0x20      32
       //        OledCmd(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
       
OledCmd(0xEE);      // Read-Modify-Write end.
       
OledCmd(0x81); //--set contrast control register
       
OledCmd(0x7F); // 0x00~0xff
       
OledCmd(0x2E); // no scrolling
       
OledCmd(0xDB); //--set VComH deselect level
       
OledCmd(0x20); // 20H => 0.77x Vcc (Reset value)
       
OledCmd(0x8D); //--set DC-DC enable  Charge Pump Setting
       
OledCmd(0x14); // 0x14 Enable Charge Pump
       
OledCmd(0xAF); //--turn on oled panel
}
//------------------------------------------------------
void OledFill(unsigned char flag)
//------------------------------------------------------
{
  
unsigned char pc;
  for (
p=0p<OLED_PAGp++) {
    
OledPag(pp);                  // page 0 à 7
    
OledCol(0OLED_COL-1);         // colonnes 0 à 127
    
for (c=0c<OLED_COLc++){
      if       (!
flag )   buff[c] = 0x00;                   // effacer
      
else if (flag == 1buff[c] = p&1||c&0x00 0xff// un quart des colonnes sur les lignes paires
      
else if (flag == 2buff[c] = 0xff;                   // remplir
    
}
    
OledData(buffOLED_COL);
  }
}

//------------------------------------------------------
void OledCmd(unsigned char c)
//------------------------------------------------------
{
  while (!
I2C1STAT0_BFRE) { } ;    // attente bus libre
  
I2C1CNT 2;                    // on envoie 2 octets
  
I2C1TXB CMD_SINGLE;
  
I2C1CON0_S 1;                 // envoi Start
  //while (I2C1CON0_S) { };          // attente fin Start
  
while (!I2C1STAT1_TXBE) { };
  
I2C1TXB c;                    // envoi commande puis Stop
}


//------------------------------------------------------
void OledData(unsigned char *p1,  char nb)
{
  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++);
  }
}

void OLED_SetPos(unsigned char x1unsigned char y1)
{
       
OledCmd(0xB0+y1);
       
OledCmd(x1 0x0F) ;
       
OledCmd(((x1 0xF0)>>4)|0x10);

}


// rev 19-01-2020
void Write_Char_At(unsigned char X,unsigned char Yunsigned char C)
int i;
unsigned char ca;
      
//OLED_SetPos(X,Y);
      //remplace OLED_SetPos(X,Y);
      
OledCmd(0xB0+Y);
      
OledCmd(X&0x0F) ;
      
OledCmd(((X&0xF0)>>4)|0x10);
      if (
C>=32)  /// caractere imprimable
        
{
        
#ifdef Limited_MikroC_2K
        
ca=C-65;
        
#else
         // codage °C
         
if (C!=176)  ca=C-32; else ca=124-32;
         
#endif
         
OledCmd(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];
         
OledData(tmp6);
       }
}
//------------------------------------------------------

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

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;
  
Flag_Timer1=0;
  
TMR1ON_bit=0;
  
TMR1IE_bit =0;
}

 
void Wait_Keyb(unsigned int T)
  { 
char Tx[8];
    
int T1;
    
Led=~Led;
    if (
T>999T=999;
    
T1=T;
    
#ifdef With_UART1_MC
     
Raz_Buffer1() ;
     
#endif
    
Arme_Timer1(T<<2);    // T * 4 * 25mS
     #ifdef With_UART1
    
CPrint(" ... Waiting Keyboard Touch 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;
     
//    IntToStr(T,CRam1);
    //   Ltrim(CRam1);
     //  UART1_Write_Text(CRam1);
    //UART1_Write_CText(" x 100mS >\r\n");
      
Print(Tx);
      
CPrint(" Sec >\r\n");
      
#endif
    #ifdef With_UART1_MC
      
while ( (Flag_Buffer1==0) && (Flag_Timer1==0));
    
#else
     
while (Flag_Timer1==0);
     
#endif
     
    
Flag_Timer1=0;
   
#ifdef With_UART1
   
CRLF1();
   
#endif
 
}


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;
}
 
#endif

//------------------------------------------------------
void main(void)
//------------------------------------------------------
{
  
OSCCON1 0x60
  
OSCFRQ 0x08;        // FOSC = 64MHz
  
ANSELA  ANSELB ANSELC 0x00;     // pins numériques
  
TRISA 0xFF;
  
Led_Dir=0;
  
SQA_Dir=0;    // declencheur SQA analyser
  
LATA 0x00;            // led A4

  #ifdef  With_UART1
     // 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
  
U1ERRIE0b00001010// FERIE=1 Framing Error RXFOIE=1 Receive FIFO Overflow
  
U1FIFO=0;
  
Delay_ms(100);
   
CPrint(" Init speciale  I2C1 Hardware \r\n");
   
#endif
   
  #ifdef With_Timers
  
Init_Timer2();
  
/* 33.3.9 BUS TIME-OUT
  The I2CxBTO register can be used to select the
  timeout source for the module. The I2C module is reset
  when the selected bus time out signal goes high. This
  feature is useful for SMBus and PMBus™ compatibility.
  For example, Timer2 can be selected as the bus
  timeout source and configured to count when the SCL
  pin is low. If the timer runs over before the SCL pin
  transitioned high, the timer-out pulse will reset the
  module.*/
  //I2C1BTO=0x01;
  #endif
   
   
I2cInit();
   
  
// GIE_bit=1;
   
 #ifdef Test_Presence
   #ifdef With_UART1
   
CPrint(" Test presence device(s) sur le bus I2C1  \r\n");
   
#endif
   
Delay_ms(100);
   
I2C1CON2_ADB=0;  // ADB  0 = Received address data is loaded only into the I2CxADB
  // ADB  1 = Received address data is loaded into I2CxRXB,
  //Transmitted address data is loaded from the I2CxTXB
   // Transmitted address data is loaded from the I2CxADB0/1 registers.
   
j=0;
   
// depart au plus pres de l'adresse OLED pour bien visualiser la capture avec SQA analyser
   
I2C1CON2.B7=0;  //0 = Auto-load of I2CxCNT disabled
   
for (i=48i<128;i=i+1)
   {
    
I2C1ERR=0;
    while (!
I2C1STAT0_BFRE) ;    // attente bus libre
    // I2C1TXB = (unsigned char)(i<<1);    // adresse
    
I2C1ADB1 = (unsigned char)(i<<1);    // adresse
    
I2C1CNT 0;                    // on envoie 0 octets
    
I2C1TXB 0x00;
    
I2C1CON0_S 1;                 // envoi Start
    
if (!I2C1CON1_ACK)
     {
       
I2C_Adresses_Devices[j]=i;
       
j++;
       
j=j0x0007;    // limite à 8 maxi
     
}
     
_asm btg LATA,4
     Delay_ms
(10);
     
I2C1CON0_EN 0;
       
Delay_ms(10);
     
I2C1CON0_EN 1;
   }  
// for

   
if (j>0
   { 
     
#ifdef With_UART1
     
CRLF1();
     
CPrint(" Device(s) trouvés sur le bus\r\n");
     
#endif
     
for (i=0;i<j;i++)
     {                     
//0123456789012345678
      
if( I2C_Adresses_Devices[i]==0) break;
      
#ifdef With_UART1
       
strConstRamCpy(CRam1," Device #1 at @xx \r\n");
      *(
CRam1+9)=i+49;
      
ByteToHexI2C_Adresses_Devices[i],CRam1+15);
      *(
CRam1+17)=' ';
      Print (
CRam1);
      
#endif
     
}
   }
   else
   
    
#ifdef With_UART1
      
CRLF1();
      
CPrint(" AUCUN Device(s) trouvés sur le bus\r\n");
      
CRLF1();
    
#endif
  // reinit pour OLED adresse
  
I2C1ADB1   OLED_ADDR// i2c1, 2 * adresse esclave
  
I2C1CON0_EN 1;        // i2c1 on
    
    
    
 #endif   // test presence device sur le bus


   #ifdef With_UART1
   
CPrint(" Oled SSD1306 128x32 init\r\n");
   
#endif
  // OledInit();
   
My_OLED_Init();
   
OledFill(1); Delay_ms(100);        // lignes verticales
   
OledFill(2); Delay_ms(1000);        // remplir
   
while (1)
  {  
     
OledFill(2); Delay_ms(1000);        // remplir
     
OledFill(0); Delay_ms(100);        // effacer
    //LATA ^= 0x10;                       // led blink
    
_asm btg LATA,4  ;   // led
    #ifdef With_UART1
    
CRLF1();
    
CPrint(" Affiche lettres A B C ...Q \r\n");
    
CPrint(" avec Write_Char_At(X en pixel (0 à 127), ligne Y (0 à 3),code ascii char)\r\n");
    
#endif

    
SQA=1;  // arme capture SQA Analyser
    
Write_Char_At(0,0,'A');
    
SQA=0;
    
Write_Char_At(8,1,'B');
    
Write_Char_At(16,2,'C');
    
Write_Char_At(24,3,'D');
    
Write_Char_At(32,3,'E');
    
Write_Char_At(40,2,'F');
    
Write_Char_At(48,1,'G');
    
Write_Char_At(56,0,'H');
    
Write_Char_At(56,1,'I');
    
Write_Char_At(64,2,'J');
    
Write_Char_At(72,3,'K');
    
Write_Char_At(80,3,'L');
    
Write_Char_At(88,3,'M');
    
Write_Char_At(96,2,'N');
    
Write_Char_At(104,1,'O');
    
Write_Char_At(112,0,'P');
    
Write_Char_At(120,1,'Q');
    
Delay_1sec();

  }
}
 
Aide toi, le ciel ou FantasPic t'aidera

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

#27 Message par satinas » lun. 25 janv. 2021 15:59

J'ai testé le scan uniquement avec xc8. Sur MikroC le programme ne démarre plus :(
Sais-tu comment restreindre lez zones flash lors de la compilation MikroC. J'aimerais charger le HEX avec le bootloader série, mais le C et le bootloader utilise la fin de la mémoire flash, problème. Je modifie dans MpLabX le memory model xc8, pour dire au compilateur de laisser de la place en fin de flash. J'aimerais le faire aussi sur MikroC.

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

#28 Message par satinas » lun. 25 janv. 2021 16:32

Ca marche aussi sur MikroC, mais derrière l'oled ne démarre pas bien.

Code : Tout sélectionner

  ...
  UartSendStr("\nStarting\n");
  I2cInit();
  UartSendStr("Scanning\n");
  I2cScan();
  UartSendStr("Scan finished\n");
  OledInit();
  ...

//--------------------------------------------------------------------------------------------
void I2cScan()
//--------------------------------------------------------------------------------------------
// Scan bus I2C, envoi Start + adresse + Stop
{
  unsigned char addr;
  for (addr=0; addr<128; addr++) {
    while (!I2C1STAT0_BFRE) { }           // attente bus libre
    I2C1ADB1 = (unsigned char)(addr<<1);  // 2 * adresse esclave
    I2C1CNT  = 0;                         // aucun octet data
    I2C1CON0_S = 1;                       // envoi Start et adresse
    Delay_ms(10);
    if (!I2C1CON1_ACKSTAT) {
      UartSendHex(addr);                  // l'adresse i2c répond
      UartSendByte('\n');
    }
  }
}



sur le terminal PC :

Starting
Scanning
3C
Scan finished

Et l'oled marche derrière le scan, j'avais oublié de sélectionner son adresse après le scan, dans le OledInit() :)

Bravo pour ton programme, il tourne bien sur mon oled :)

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

#29 Message par paulfjujo » lun. 25 janv. 2021 19:13

OK !
je m'etais trompé sur la position du bit, mis 6 au lieu de 5..

sbit I2C1CON1_ACKSTAT at I2C1CON1.B5; //0 = Ack was received 1 = No Ack was not received
ça roule ..raoul !

(0.000) Init speciale I2C1 Hardware
(0.027) ... Waiting Keyboard Touch for < 3,0 Sec >
(2.981)
(0.019) Test presence device(s) sur le bus I2C1
(1.288)
(0.008) Device(s) trouvés sur le bus
(0.030) Device #1 at @3C
(0.000) Device #2 at @57
(0.000) Device #3 at @68
(0.022) OLED SSD1306 128x32 init
(1.479)
(0.010) Affiche lettres A B C ...Q
(0.050) avec Write_Char_At(X en pixel (0 à 127), ligne Y (0 à 3),code ascii char)
(1.078) Affiche Texte de 21 cars par ligne (Taille mini= 1) :
(0.040) ABCDEFGHIJKLMNOPQRSTUVWXYZ
(0.067) ... Waiting Keyboard Touch for < 3,0 Sec >
(2.967)
(0.053) Affichage (Taille 2) de : HELLO Friends, How are you ?. at x=0
(0.145) ... Waiting Keyboard Touch for < 2,0 Sec >
(1.993)
(0.153)

Aide toi, le ciel ou FantasPic t'aidera

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

#30 Message par paulfjujo » dim. 31 janv. 2021 10:30

bonjour satinas,


voila quelques jours où je bute sur l'affichage de GROS caracteres
je ré-utilise les memes fonctions que celles utilisées avec mon 18F26K22 ( en I2C1 Hardware)
avec bien sur , l'usage des nouvelles fonctions I2C1 hardware pour le 18F27K42
mais je n'obtiens que des gribouillis..
alors qu'avec le mode 6x8, ou 8x16, ou affichage de 6 caracteres speciaux, ou affichage BMP .. c'est OK ( comme sur le 18F26K22)
il y a un truc qui m'echappe ...la seule grosse différence est la commande I2C !
je tourne en rond depuis plusieurs jours ..

:sifflotte: un coup d'oeil serait bien venu

je mets ici le projet complet ( ne tiendra pas dans les 2K !)
mais pourrait tourner avec le minima de fonte gros caractere., sans BMP ..etc ...

seul les tests ecriture taille 3 et taille 4 ne donnent pas le resultat escompté

Code : Tout sélectionner



version 18F27K42 

void Big_affichage
( unsigned char posX, unsigned char N )
{
     int k;
     unsigned  char cc;
     CRLF1();
    OLED_Cde(0x20);
    //OLED_Cde(0x02); // Page mode
    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);
   // Decompile_Byte(cc);
   // CRLF1();
    OLED_Data(cc,1);
    Delay_us(20);
    }
      CRLF1();
    //OLED_Data(*(Big_Numbers[N]),48);
  //  Resize();
 }




void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char *ch, unsigned char TextSize)
....
   case 3:
                      kx=strlen(ch);
                     j=0;
                     //if (yd>2) yd=2;
                    // if (xd>15)xd=15;
                     while((*(ch+j) !=0) && (j<8) )
                     {
                        c = *(ch+j);
                       if ((c>='0') && (c<='9'))
                      {
                       c=c-48;
                       OLED_SetPos(xd,yd);
                       for(i=0;i<32;i++)  
                       
{
                         tmp[0]=Big_Number_16x16[c*16+i];
                          OLED_Data(tmp,1);
                       }
                       //   tmp[i]=Big_Number_16x16[c*16+i];
                       //   }
                       //   OLED_Data(tmp,16);
                        OLED_SetPos(xd+8,yd+1);
                     for(i=0;i<16;i++)  
                     
{
                        tmp[0]=Big_Number_16x16[c*16+i+16];
                        OLED_Data(tmp,1);
                        }
                      //  tmp[i]=Big_Number_16x16[c*16+i+16];
                      //}
                      //  OLED_Data(tmp+16,16);
                      xd=xd+16;
                      }
                       j++;
                    }
                     break;
                 case 4:
                   lx=strlen(ch);
                  if (lx>0)
                   {
                     for (i=0;i<lx;i++)
                     {
                     //cadrage à droite
                      kx=(i+7-lx) *16;
                      c=*(ch+i);
                      if ((c>47) && (c<58))
                       Big_affichage(kx,c-48);
                       else
                        
{
                         switch (c)
                         {
                           case 45:
                             Big_affichage(kx,13) ;   // moins (negatif)
                             break;
                          case 46 :
                            Big_affichage(kx,10) ;     //point
                            break;
                          case 32:
                             Big_affichage(kx,11) ;   // space=Blanc
                             break;
                         case 176:
                             Big_affichage(kx,12) ;   // ° ( degré)
                             break;
                          default:
                             Big_affichage(kx,11) ;   //space
                            break;
                         }
                       }
               Delay_ms(200);
                     }
                   }
                    break



j'ai essayé l'envoi byte par byte , ou l'envoi par paquet ..c'est pareil
j'ai essayé aussi en changeant le mode 00 horizontal ou 02 mode page ... idem

================================
la version 18F26K22
================================

Code : Tout sélectionner


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



_18F27K42_UART1_ADC1_Mini_Oled_20x10mm_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


Retourner vers « Langage C »

Qui est en ligne

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