Voila quelques jours que je bosse sur mon chrono .
J'ai fais tout bien comme il faut mais je rencontre quelques soucis d'ordre inconnu ?
En effet quand je tourne mon encodeur incrémental, celui-ci a pour but de modifier la valeur de mes chiffres à l'écran.
Mais bizarrement, il se produit un phénomène que je ne comprends pas, et qui m’énerve car voila un moment que je suis dessus .
Aléatoirement l'affichage de l'écran bug, suite à des erreurs certainement . Mais je comprends vraiment pas pourquoi .
Voici le programme :
[spoil]
Code : Tout sélectionner
//############################# DECLARATION ############################
#include <Chiffre.h>
#include <Oled_M.h>
#include <Encodeur.h>
unsigned int i, j, k, Led_State = 0x0001, compteur=0, valeur_s=0, valeur_m=0;
unsigned char ENCA_bit, ENCB_bit, ENC_Button_State=0, flag=0, seconde, D_seconde, minute, D_minute;
sbit flag0 at flag.B0 ; // Déclaration d'un drapeau
//############################ FONCTION ###############################
void interrupt() { // Ici c'est notre interruption
// On regarde quel drapeau a été mis à 1, pour connaitre la source de l'interutpion
if (INTCON.TMR0IF){ // Ici le bit TMR0IF (bit2) du registre INTCON est testé
TMR0IF_bit = 0; // IMPORTANT !!! On ré-arme notre drapeau en le remettant à 0
TMR0H = 11; // chargement de la valeur 11 dans le TIMER du haut
TMR0L = 220; // chargement de la valeur 220 dans le TIMER du bas
compteur = compteur++; // On incrémente un compteur
}
}
void HC595_Write(int value){ // Fonction qui envoi les valeurs des leds au HC595
char first_byte, second_byte; // Déclaration de variables temporaires
second_byte = value; // Enregistrement du premier byte
value = value>>8; // On décale de 8 bit pour afficher le second byte
first_byte = value; // Enregistrement du second Byte
HC595_cs = 0; // Selection du module HC595 sur le BUS SPI
SPI1_write(first_byte); // Envoi du premier byte au HC595
SPI1_write(second_byte); // Envoi du second Byte
HC595_cs = 1;
}
//##################################################################################
//###################### PROGRAMME PRINCIPAL ###############################
//##################################################################################
void main(){
ANSELA = 0 ; // Configure PORTA en digital
ANSELB = 0 ; // Configure PORTB en digital
ANSELC = 0 ; // Configure PORTC en digital
ANSELD = 0 ; // Configure PORTD en digital
ANSELE = 0 ; // Configure PORTE en digital
ENCA_direction = 1; // Configure RC1 en entrée
ENCB_direction = 1; // Configure RA3 en entrée
ENC_SW_direction = 1; // Configure RB1 en entrée
HC595_cs_direction = 0; // Configure RA5 en sortie
TRISE0_bit = 0; // Configure la broche 0 du PORT E en sortie
TRISE1_bit = 0; // Configure la broche 1 du PORT E en sortie
TRISC0_bit = 0; // Configure la broche 0 du PORT C en sortie
//----------- CONFIGURATION DE L'INTERRUPTION POUR 1 SECONDE ------------------
T0CON = 0b10000100; // Configuration du TIMER0 ( bit7 : activé, bit3: prescaler, bit2,1 et presacaler à 32 )
TMR0H = 11; // chargement de la valeur 11 dans le TIMER du haut
TMR0L = 220; // Chargement de la valeur 220 dans le TIMER du bas
INTCON = 0b10000000; // Configuration de l'interruption (bit7 : activation GIE, bit5: autorisation débordement TMR0)
SPI1_Init(); // Initialisation du SPI
Delay_ms(200);
OLED_M_Init(); // Initialisation de l'ecran LCD
Delay_ms(100);
HC595_Write(Led_State); // Initialisation du HC595
Delay_ms(100);
efface_ecran(); // on efface l'écran
deux_points(); // On affcihes les deux points
curseur(1); // On affiche le curseur en position 1 a gauche ou 0 à droite
Affichage(0,78); // Initialisation du chiffre des secondes
Affichage(0,58); // Initialisation du chiffre des Dizaines de secondes
Affichage(0,22); // Initialisation du chiffre des minutes
Affichage(0,2); // Initialisation du chiffre des Dizaines de minutes
//############################ BOUCLE INFINIE ##############################
while(1){
if((ENCA_bit != RC1_bit)||(ENCB_bit != RA3_bit)){ // SI l'état logique change sur la PinA ou la PinB
// On compare le dernier état logique de la PinB ET le nouvel état logique de la PinA
if(ENCB_bit|RC1_bit==1){ // Si ENCB_old OU ENCA_new est à 1
Led_State = (Led_State << 1) | (Led_State >> 15);
if ( flag0 == 0)valeur_s = valeur_s++;
if ( flag0 == 1)valeur_m = valeur_m++;
}
if(ENCA_bit|RA3_bit==1){ // Si ENCA_old OR ENCB_new est à 1
Led_State = (Led_State >> 1) | (Led_State <<15);
if ( flag0 == 0)valeur_s = valeur_s--;
if ( flag0 == 1)valeur_m = valeur_m--;
}
ENCA_bit = RC1_bit ; // On enregistre la nouvelle valeur dans ENCA_bit
ENCB_bit = RA3_bit ; // On enregistre la nouvelle valeur dans ENCB_bit
// HC595_Write(Led_State); // Execute la fonction pour mettre a jour les leds
}
if (ENC_SW ==1){ // Detection d'un appui sur le BP de l'encodeur
delay_ms(10); // Anti -rebond
if (ENC_SW ==1){ // Anti -rebond
while (ENC_SW ==1); // Anti -rebond
curseur(flag0++); // On affiche les curseurs apres un appui
ENC_Button_State++; // Incremente la valeur du Bouton
if (ENC_Button_State == 4) ENC_Button_State = 0; // Si le bouton arrive à 4 On le passe à 0 .
// Switch pour selectionner l'etat des leds suivant la valeur du Bouton
// Cette valeur en Hexa correspond à une valeur en binaire sur 16 bits
switch (ENC_Button_State){
case 0 : Led_State = 0x0001; // 1 led allumée = 00000000 - 00000001
break;
case 1 : Led_State = 0x0101; // 2 leds allumées = 00000001 - 00000001
break;
case 2 : Led_State = 0x1111; // 4 leds allumées = 00010001 - 00010001
break;
case 3 : Led_State = 0x5555; // 8 leds allumées = 01010101 - 01010101
break;
default : // Secours toujours mettre un defaut avec un switch
break;
}
HC595_Write(Led_State); // MAJ des leds apres appui : Execute la fonction
}
}
if (flag0 == 0){ // Si le curseur est sur les secondes
if (valeur_s > 200) valeur_s = 59; // En dessous de zéro on passe a 255 donc on remet à 59
if (valeur_s >= 60) valeur_s =0; // Au dessus de 60 on repasse à 0
seconde = valeur_s%10 ; // Determine les unités des secondes
D_seconde = valeur_s /10; // Determine les dizaines de seconde
Affichage(seconde,78); // Affiche les secondes
Affichage(D_seconde,58); // Affiches les dizaines de secondes
}
if (flag0 == 1){ // Si le curseur est sur les minutes
if (valeur_m > 200) valeur_m = 99;
if (valeur_m >= 100) valeur_m =0;
minute = valeur_m%10 ;
D_minute = valeur_m /10;
Affichage(minute,22);
Affichage(D_minute,2);
}
}
}
void efface_ecran(){ // On efface l'écran
OLED_M_command(SSD1306_COLUMNADDR); // determine la largeur de l'ecran
OLED_M_command(32); // de 32 à 127
OLED_M_command(127);
OLED_M_command(SSD1306_PAGEADDR); // Détermine la hauteur de l'écran
OLED_M_command(0); // De 0 à 4
OLED_M_command(4);
for (j=0;j<96;j++) // Efface tout les colonnes de 0 à 96
{
Set_Column_Address(j);
for (i=0;i<5;i++) // Efface tout les lignes de 0 à 4
{
Set_Page_Address(i);
OLED_M_data(0x00);
}
}
}
void deux_points (){
OLED_M_command(SSD1306_COLUMNADDR); // definition de la largeur du rectangle de dessin du chiffre
OLED_M_command(78); // 16 colonnes de large
OLED_M_command(81);
OLED_M_command(SSD1306_PAGEADDR); // definition de la hauteur du rectangle de dessin du chiffre
OLED_M_command(2); // 3 pages de haut
OLED_M_command(3);
for (k=0;k<8;k++)
{OLED_M_data(points[k]);}
}
void Affichage(unsigned char chiffre, unsigned char position) {
OLED_M_command(SSD1306_COLUMNADDR); // definition de la largeur du rectangle de dessin du chiffre
OLED_M_command(position+32); // 16 colonnes de large
OLED_M_command(position+47);
OLED_M_command(SSD1306_PAGEADDR); // definition de la hauteur du rectangle de dessin du chiffre
OLED_M_command(1); // 3 pages de haut
OLED_M_command(3);
delay_us(100);
if ( chiffre == 0)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre0[k]);}
}
if ( chiffre == 1)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre1[k]);}
}
if ( chiffre == 2)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre2[k]);}
}
if ( chiffre == 3)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre3[k]);}
}
if ( chiffre == 4)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre4[k]);}
}
if ( chiffre == 5)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre5[k]);}
}
if ( chiffre == 6)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre6[k]);}
}
if ( chiffre == 7)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre7[k]);}
}
if ( chiffre == 8)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre8[k]);}
}
if ( chiffre == 9)
{
for(k=0;k<48;k++)
{OLED_M_data(chiffre9[k]);}
}
}
void OLED_M_Init(){ // Initialisation de l'écran
OLED_RST=0; // Reset de l'écran
Delay_ms(200); // Pause
OLED_RST=1; // Arret du Reset
Delay_ms(200); // pause
OLED_M_command(SSD1306_DISPLAYOFF); //0xAE Ecran en mode veille (désactivé)
OLED_M_command(SSD1306_SETDISPLAYCLOCKDIV); //0xD5 Set Display Clock Divide Ratio/Oscillator Frequency
OLED_M_command(0x80);
OLED_M_command(SSD1306_SETMULTIPLEX); //0xA8 Set Multiplex Ratio
OLED_M_command(0x27);
OLED_M_command(SSD1306_SETDISPLAYOFFSET); //0xD3 Set Display Offset
OLED_M_command(0x00);
OLED_M_command(SSD1306_SETSTARTLINE); //0x40 Set Display Start Line
OLED_M_command(SSD1306_CHARGEPUMP); //0x8D Set Charge Pump
OLED_M_command(0x14); //0x14 Enable Charge Pump
OLED_M_command(SSD1306_COMSCANDEC); //0xC8 Set COM Output Scan Direction
OLED_M_command(SSD1306_SETCOMPINS); //0xDA Set COM Pins Hardware Configuration
OLED_M_command(0x12);
OLED_M_command(SSD1306_SETCONTRAST); // 0x81 réglage du contraste
OLED_M_command(0xAF); // Envoi de la valeur du contraste
OLED_M_command(SSD1306_SETPRECHARGE); // 0xD9 Set Pre-Charge Period
OLED_M_command(0x25);
OLED_M_command(SSD1306_SETVCOMDETECT); //0xDB Set VCOMH Deselect Level
OLED_M_command(0x20);
OLED_M_command(SSD1306_DISPLAYALLON_RESUME); //0xA4 ??? pas compris - Set Entire Display On/Off
OLED_M_command(SSD1306_NORMALDISPLAY); //0xA6 mode normal ou inverse
OLED_M_command(SSD1306_SETSEGMENTREMAP); //0xA1 Inverse l'ordre de lecture des colonnes gauche vers droite
OLED_M_command(SSD1306_MEMORYMODE); // Selection du mode de defilement
OLED_M_command(0x00); // Horizontal adressing mode
OLED_M_command(SSD1306_DISPLAYON); //0xAF Active l'écran OLED
}
void Set_Page_Address(unsigned char add) { //Set page adress for Page Addressing Mode
add=0xb0|add;
OLED_M_command(add);
}
void Set_Column_Address(unsigned char add) { //Set column adress for Page Addressing Mode
add += 32; //L'ecran n'a que 96 colonnes au lieu de 128. on rajoute donc 32 en offset
OLED_M_command((0x10|(add>>4)));
OLED_M_command((0x0f&add));
}
void curseur(unsigned char flag){ // affiche les curseurs au dessus et en dessous
OLED_M_command(SSD1306_COLUMNADDR); // definition de la largeur du rectangle de dessin du chiffre
OLED_M_command(32); // 16 colonnes de large
OLED_M_command(127);
OLED_M_command(SSD1306_PAGEADDR); // definition de la hauteur du rectangle de dessin du chiffre
OLED_M_command(0); // 3 pages de haut
OLED_M_command(4);
if (flag == 0){
Set_Column_Address(17);
Set_Page_Address(4);
for(k=0;k<7;k++){OLED_M_data(fleche_bas[k]);}
Set_Column_Address(73);
for(k=0;k<7;k++){OLED_M_data(0);}
Set_Column_Address(17);
Set_Page_Address(0);
for(k=0;k<7;k++){OLED_M_data(fleche_haut[k]);}
Set_Column_Address(73);
for(k=0;k<7;k++){OLED_M_data(0);}
}
if (flag == 1){
Set_Column_Address(73);
Set_Page_Address(4);
for(k=0;k<7;k++){OLED_M_data(fleche_bas[k]);}
Set_Column_Address(17);
for(k=0;k<7;k++){OLED_M_data(0);}
Set_Column_Address(73);
Set_Page_Address(0);
for(k=0;k<7;k++){OLED_M_data(fleche_haut[k]);}
Set_Column_Address(17);
for(k=0;k<7;k++){OLED_M_data(0);}
}
}
void OLED_M_command (unsigned char temp){ //Envoi d'une commande
OLED_CS=0; // Chip Select , actif à l'état bas
OLED_DC=0; // Data/Command selection: 1=Data; 0=Command
SPI1_Write(temp); // Envoi de l'info sur le BUS
OLED_CS=1; // on arrrete la com en desactivant le chip
}
void OLED_M_data(unsigned char temp){ //Envoi d'une donnée
OLED_CS=0;
OLED_DC=1;
SPI1_Write(temp);
OLED_CS=1;
}Avez vous une idée ?
Je précise que j'ai virer les leds de l'encodeur, qui utilise le SPI aussi . et que ca bug aussi en allant doucement .



