[Programmation] Registre à décalage pour lecture d'une com en Wiegand
Répondre à la discussion
Affichage des résultats 1 à 6 sur 6

Registre à décalage pour lecture d'une com en Wiegand



  1. #1
    Unknow

    Registre à décalage pour lecture d'une com en Wiegand


    ------

    Bonjour,

    Je vais commencer par une mise en contexte, je suis alternant auprès d'une entreprise, mon travail consiste
    en la réparation et la conception de divers cartes électroniques.
    Je travaille actuellement sur la conception d'une carte donc l'objectif est de lire une communication en Wiegand une méthode de branchement relativement utilisé en sécurité, celui-ci peut être décrit simplement, on retrouve deux fils de communication (+ la masse)
    que l'on appelle DATA_0 et DATA_1 leur état au repos (pas de communication) est à 1 (dans mon cas +12V) lorsque l'on cherche à envoyer 1 on
    va faire passer DATA_1 à 0 (0V) est maintenir DATA_0 à 1 (donc +12V) pour 0 on répète le même processus mais on inverse ( DATA_0 =0V et DATA_1= +12V).
    Cette communication en Wiegand est ni plus ni moins que le code d'un badge RFID lu par un lecteur de badge, ce genre d'équipement tombant souvent en panne je me suis lancer dans le projet de la conception d'un outil de test portable pour les postés ayant besoin de diagnostiquer rapidement les lecteurs. En bref le projet peut se présenter comme ceci, on viens brancher un lecteur de carte sur notre outils, le lecteur est alimenter par celui-ci, notre outil est muni d'un écran LCD qui au passage d'un badge auprès du lecteur vient envoyer le numéro de badge sur nos deux câbles DATA_0 et DATA_1, ce code est un code à 6 chiffres chaque chiffre étant en hexa cela nous fait 3 octets de données que je dois venir récupérer mais je dois aussi vérifier le code entreprise et les bits de parité ce qui nous fait le joli nombre de 86 bits.
    Pour mon projet j'utilise un PIC16F1827, je compile mon programme avec XC8 2.0, mon problème et la lecture, je viens attendre un changement sur les pins RB0 (où est branché DATA_0) et RB1 (où est branché DATA_1) puis je vérifie qu'elle FLAG est à 1 après quoi viens le point qui pose problème je cherche à stocker cette valeur au sain d'un tableau de char or je travaille avec des valeurs binaire je ne vais donc pas créer un tableau de 86 char (de plus le micro ne peut pas c'est trop pour lui) je dois donc venir lire ma valeur et la stocker dans une case de ma colonne puis venir la décaler d'un rang, cela me permettra de transférer 8 valeurs dans une case de tableau, enfin c'est ce que je veux faire mais reste à voir si c'est possible car jusqu'à présent je n'y arrive pas.

    Code:
    //DEBUT DU PROGRAMME
    
    /* Main.c file generated by New Project wizard
     *
     * Created:   mer. juin 19 2024
     * Processor: PIC16F1827
     * Compiler:  MPLAB XC8
     */
     // CONFIG1
    
    // PIC16F1827 Configuration Bit Settings
    
    // 'C' source line config statements
    
    // CONFIG1
    #pragma config FOSC = XT        // Oscillator Selection (XT Oscillator, Crystal/resonator connected between OSC1 and OSC2 pins)
    #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
    #pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
    #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
    #pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
    #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
    #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
    #pragma config IESO = OFF        // Internal/External Switchover (Internal/External Switchover mode is enabled)
    #pragma config FCMEN = OFF    // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
    
    // CONFIG2
    #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
    #pragma config PLLEN = OFF        // PLL Enable (4x PLL enabled)
    #pragma config STVREN = OFF   // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
    #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
    #pragma config LVP = OFF          // Low-Voltage Programming Enable (Low-voltage programming enabled)
    
    // #pragma config statements should precede project file includes.
    // Use project enums instead of #define for ON and OFF.
    
    #include <xc.h>
    
    #define _XTAL_FREQ 4000000
    //Définition de nos macros
    #define E PORTAbits.RA7
    #define RS PORTAbits.RA6
    #define D4 PORTAbits.RA0
    #define D5 PORTAbits.RA1
    #define D6 PORTAbits.RA2
    #define D7 PORTAbits.RA3
    #define LCD_EN_Delay 500
    //Variables globalesvoid Init()
    
    char i=0;
    char Wieg[];
    char display=0;
    char erreur[] = {"ERREUR"};
    
    void interrupt PORTBChange()
    {
       Wieg[] << 1; //Je viens décaller mon bit
       if (IOCBF == 0x01) //DATA_0 envoie un 0
       {
          Wieg[i] | 0; 
          i++;
          IOCBF = 0x00;
          TMR1L = 0x00; //Je remets le 
          TMR1H = 0x00;
          TMR1ON = 1;
        
       }
       else if (IOCBF == 0x02) //DATA_1 envoie un 1
       {
          Wieg[i] | 1;
          i++;
          IOCBF = 0x00;
          TMR1L = 0x00;
          TMR1H = 0x00;
          TMR1ON = 1;
       }
       else if (TMR1IF == 1) 
       {
          TMR1IF = 0;
          display=1;
          TMR1ON = 0;
          TMR1L = 0x00;
          TMR1H = 0x00;      
       }
    }
    
    void Init() //J'initialise mes différents registre
    {
       ANSELB = 0x08;
       TRISB = 0xFF;
       IOCBP = 0x03;
       IOCBN = 0x00;
       IOCBF = 0x00;
       ANSELA = 0x00;
       TRISA = 0x00;
       OSCCON = 0x6A;
       OPTION_REG = 0x88;
       INTCON = 0xC8;
       PIE1 = 0x01;
       PIR1 = 0x00;
       T1CON = 0x34;
    }
    
    void main(void)
    {
       Init();
       LCD_Init();
       LCD_Clear();
       LCD_Set_Cursor(0,0);
       while (1)
       {
    
       }   
    }
    
    //FIN DU PROGRAMME
    Cela serait mentir de dire que je suis expert en C je dois avour avoir du mal avec mes opérateurs, je ne suis pas là pour demander à ce que l'on fasse le projet à ma place mais en l'absence d'avancer je me retourne vers vous afin de me corriger quant à mes erreurs de débutants, désolé pour le pavé ceci dit.
    (Simple info j'ai retirer la majorité du programme pour ne pas perdre de vue le plus important).

    Si besoin je peux rajouter le schéma Proteus du circuit partiel.

    Merci d'avance pour vos réponse, Cordialement.

    -----
    Dernière modification par Antoane ; 21/06/2024 à 11h45. Motif: Ajout [/code]

  2. #2
    umfred

    Re : Registre à décalage pour lecture d'une com en Wiegand

    A mon avis, un des problèmes peut venir du fait que tu ne déclares pas la taille de ton tableau Wieg (en tout cas, ce n'est pas visible dans le code montré)
    Ensuite, Wieg[i] | 0; ne fait rien, au mieux ça renvoie une valeur qui n'est pas récupéré.
    Ce qu'il faut que tu fasses:
    -identifier le bit reçu (0 ou 1)
    -placer cette valeur dans ton octet (ou tableau d'octets)
    -incrémenter un compteur
    -effacer les flags d'interruptions

    Une fois que tout est reçu, tu recomposes tes octets et fais tes vérifications

    (Je me demandais comment était transmis plusieurs 0 (ou 1) de suite, mais j'ai vu qu'il y avait un retour à l'état haut à chaque fois, et que la transmission se fait à une vitesse définie, donc il n'y a plus de problème finalement)

  3. #3
    Unknow

    Re : Registre à décalage pour lecture d'une com en Wiegand

    Bonjour, pour commencer merci pour votre réponse

    Si je reprends votre réponse je définirai les actions à réaliser dans l'ordre suivant,
    identifier le bit reçu, pour cela je vérifie qu'elle flag d'interruptions de changements de sur le PORTB c'est déclencher, ensuite il faut que je place ma valeur dans un tableau, ici je le définirai comme un tableau de char soit une case contient un octet, je cherche donc à stocker mes 86 bits ( le microcontrôleur est incapable de prendre un tableau de 86 octets (ou je ne sais pas comment le définir) dans le cas où je stocke mes 86 bits cela fait donc un tableau de 11 octets (cases) maintenant je sais comment stocker une valeur "classique" (un int, char, long, short,...) sur 8 octets néanmoins c'est la partie manipulation des bits qui me pose problème, je ne suis pas sûre de la méthode à entreprendre pour stocker mon bits dans l'un des bits de ma case de tableau puis au bout de ma case suis-je censé définir que j'écris dans une autre case suivante ?
    Une forme de programme dans lequel je vais bouler mes cases de tableau de 0 à 10 que j'incrémenterai au fur et à mesure que une boucle interne à la première écris les 8 bits de ma cases ?

    Exemple :
    Code:
    for (i=0;i<11;i++) //Boucle d'incrémentation des cases de tableau
    {
        for (j=0;j<8;j++) //boucle d'incrémentation des cases
        {
               // attribution des bits aux différents bits des cases de mon tableau
        }
    }
    Le problème que j'ai ici est que je cherche à détecter à chaque interruption un nouveau bit, la communication Wiegand se fait à une fréquence de 1 KH dans mon cas cela laisse donc une grande marge entre chaque bit.
    J'ai placer dans mon premier programme un Timer, lorsque le µC détecte un bit je vais mettre le Timer à 0 puis l'allumer (si il l'est déjà il reste allumé)
    l'intérêt et que le timer overflow à partir de 2 ms ainsi la période étant de 1 ms entre chacun de mes bits si je n'ai plus de bits communiquer je ne remets plus le compteur à 0 il Overflow se qui déclenche l'interruption Timer 0 qui vient déclarer la communication comme terminé. Ensuite le µC devra traduire la communication et la display sur le LCD. Mon problème et donc que cette forme de boucle que j'ai décris plus haut ne peux pas marcher car je cherche à sortir de l'interruption entre chaque bits, de plus je ne suis pas sûr de la méthode pour attribuer mes bits à mon tableau.

    Encore merci pour votre réponse, Cordialement.

  4. #4
    umfred

    Re : Registre à décalage pour lecture d'une com en Wiegand

    les façons classiques pour position un bit en C:
    Code:
    N |= 1 << K; // met à 1 le bit K de N
    N &= ~(1 << K); // met à 0 le bit K de N
    N ^= 1 << K; // inverse le bit K de N (opérateur ^est le XOR, OU-Exclusif)
    Le mieux pour travailler sur des octets est d'utiliser des unsigned char.

    Pour déterminer où le mettre, sachant le nombre de total que tu es censé recevoir, il suffit de calculer le numéro d'octet et le numéro du bit
    (et comme tu sais aussi l'ordre de réception, tu peux remplir "les bons octets" à réception du bit.
    cpt_bit =0 => octet 0, bit 0
    ...
    cpt_bit = 8 => octet 1, bit 0
    ....
    octet = cpt_bit / 8; //division entière forcée par le fait que les 2 termes sont des entiers, donc on récupère la partie entière.
    bit= cpt_bit % 8; // opérateur modulo renvoyant le reste

    et pas de boucle dans l'interruption, les interruptions doivent être les plus rapides possibles.
    ça devrai, je pense, être un truc comme ça (je n'exclus pas de possibles erreurs de syntaxe)
    Code:
    unsigned char octets[8];
    ...
    void __interrupt ISR() /// à vérifier la façon d'écrire les fonctions d'interruptions
    {
        unsigned char num_octet= cpt_bit /8;
        unsigned char num_bit = cpt_bit %8;
        cpt_bit++;
        if (IOCBF == 0x01) //DATA_0 envoie un 0
        {
            octets[num_octet]&=~(1<<num_bit);
            IOCBF = 0x00;
            TMR1L = 0x00;
            TMR1H = 0x00;
            TMR1ON = 1;
       }
       else if (IOCBF == 0x02) //DATA_1 envoie un 1
       {
            octets[num_octet] |= 1<< num_bit;
            IOCBF = 0x00;
            TMR1L = 0x00;
            TMR1H = 0x00;
            TMR1ON = 1;
       }
       else if (TMR1IF == 1) 
       {
          TMR1IF = 0;
          display=1;
          TMR1ON = 0;
          TMR1L = 0x00;
          TMR1H = 0x00;      
       }
       if(cpt_bit>=86) cpt_bit=0; // remise à 0 du compteur de bit si on atteint la valeur max
    }
    Après on peut peut-être mieux adapter en connaissant l'ordre des bits reçus
    Dernière modification par umfred ; 21/06/2024 à 18h28.

  5. A voir en vidéo sur Futura
  6. #5
    Unknow

    Re : Registre à décalage pour lecture d'une com en Wiegand

    Rebonjour,

    Désolé pour ma réponse tardive, je vais tester quelque chose de similaire encore merci pour votre réponse,
    néanmoins quitte à écrire un programme autant le comprendre,
    je comprends le principe d'opération avec division et division euclidienne c'est très bien penser et je travaillerais plus avec ces opérateurs au futur.
    Mais je dois avouer avoir plus de mal avec la suite d'opérateur &=~ , & signifie le ET, = l'affectation et ~ la négation sauf erreur de ma part,
    et (1<< num_bit) le décalage d'un bit de 1 rang sur la gauche comment est ce que cela fonctionne ensemble sur une opération de bit comme exemple?

    Encore merci pour vos conseils qui me permettent d'avancer et de m'améliorer.

    Cordialement.

  7. #6
    umfred

    Re : Registre à décalage pour lecture d'une com en Wiegand

    n &= ... est équivalent à n = n & ... (ça vaut pour pratiquement tous les opérateurs en C, et ça évite de répéter la variable)
    le << ou >> c'est du décalage de bit en effet de x position vers la gauche ou la droite

    si on prend un exemple
    n= b'0101 0101' (0x55 = 85 en décimal); b0= bit 0 le poids faible
    si on veut mettre à 1 le bit 3, 1<<3 = b'0000 1000'
    ensuite on fait un OU logique entre les 2 nombres:
    b'01010 0101'
    +b'0000 1000'
    =>b'0101 1101' (0x5A)

    si, sur le n de départ, on veux mettre à 0 le bit 4, 1<<4 = b'0001 0000'
    ~(1<<4) = ~(b'0001 0000') = b'1110 1111'
    on fait ensuite le ET logique avec le n initial:
    b'0101 0101'
    &b'1110 1111'
    =>b'0100 0101' (0x45)

    PS_Bonus: on peut utiliser << ou >> pour diviser ou multiplier par une puissance de 2 plus rapidement qu'une opération de division (sur des entiers) (le compilateur peut savoir transformer ce type de division par un décalage)
    20=1; 21=2; 22=4; 23=8; ...
    56 * 4 = 56 << 2= b'0011 1000' <<2 = b'1110 0000' = 224

Discussions similaires

  1. [Analogique] adapter une tension pour une entrée sur un registre à décalage de type 74HC165
    Par brunop37 dans le forum Électronique
    Réponses: 4
    Dernier message: 10/04/2018, 21h46
  2. Registre à décalage 16 bit
    Par Gérard dans le forum Électronique
    Réponses: 7
    Dernier message: 11/05/2014, 20h26
  3. Erreur dans mon schéma pour un registre à décalage.
    Par invite3ddba663 dans le forum Électronique
    Réponses: 8
    Dernier message: 21/08/2010, 19h11
  4. Registre à décalage
    Par invite1a530f8d dans le forum Électronique
    Réponses: 6
    Dernier message: 26/06/2009, 11h50
  5. registre à décalage
    Par invite74efa975 dans le forum Électronique
    Réponses: 3
    Dernier message: 30/05/2009, 18h54
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...