Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    janvier 2005
    Messages
    565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : janvier 2005
    Messages : 565
    Points : 115
    Points
    115

    Par défaut Ne mettre à jour que la pinoche qui doit l'être

    Re bonjour,

    Cette fois-ci, je suis à la recherche d'une solution pour éviter de toujours écrire sur l'intégralité du port. Chez moi, ce port est coupé volontairement en 2, le LSB et le MSB. Si bien que quand j'écris un byte 0x05, j'ai bien 00000101. mais sur les deux ports 0000 et 0101.

    Donc je passe à la suite. J'aimerais bien éviter de voir de inversions de pinoches involontaires. Ce qui peut, hélas arrivé quand le timing est serré et que le fait de couper en 2 le port pose problème.

    Viens la solution de ne mettre a jour la pinoche tel que:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    portWrite = (pin7 << 7) | (pin6 << 6) | (pin5 << 5) | (pin4 << 4) | (pin3 << 3) | (pin2 << 2) | (pin1 << 1) | (pin0 << 0);
    Il faut chargé pin7 avec 0/1 selon le cas etc pour les autres pin...

    Jusque là, c'est pareil, je me dis que si je fais ceci:
    //Un peu de pseudo code
    Prendre la nouvelle valeur de port
    Rentrer dans une boucle de 7 à 0
    Pour chaque bit du port actuel
    comparer avec le même bit du précédent port mémorisé
    si le nouveau bit != au bit ancien
    mettre a jour le code précédent

    placer dans le précédent port, le nouveau port
    Tout ça est bien beau. Je rencontre un souci toute fois. Pour des raisons de simplicité de protocole, je transmet la valeur en décimale (oui, c'est mal mais j'ai pas le choix car le mode série hein...). Du coup, comment parcours-t-on un byte, bit à bit quand celui-ci est chargé avec du décimal ?

    Je vous remercie par avance.

  2. #2
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Ancien développeur matériel électronique (Hard/Soft)
    Inscrit en
    avril 2002
    Messages
    2 433
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ancien développeur matériel électronique (Hard/Soft)
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 2 433
    Points : 8 167
    Points
    8 167

    Par défaut

    Salut,
    Citation Envoyé par Caxton Voir le message
    Pour des raisons de simplicité de protocole, je transmet la valeur en décimale
    Très bonne idée

    Citation Envoyé par Caxton Voir le message
    oui, c'est mal mais j'ai pas le choix car le mode série hein....
    Au contraire !
    La très grandes majorités des protocoles éprouvés dialoguent via des valeurs numériques (qu'elles soient binaires, décimales ou hexa ça ne changent rien puisque dans le processeur tout est en binaire) car c'est bien plus efficace et très rares sont ceux qui le font en texte ou suite de caractères.

    Si tu veux envoyer la valeur 1000, il te faut 2 octets. Si tu veux envoyer la chaîne de caractères "1000", donc la suite des caractères '1', '0', '0', '0', il te faut 4 octets, le double ! On voit vite l'intérêt d'envoyer des valeurs numériques.

    Citation Envoyé par Caxton Voir le message
    Du coup, comment parcours-t-on un byte, bit à bit quand celui-ci est chargé avec du décimal ?
    Ce n'est pas nécessaire contrairement à une chaîne de caractère représentant un nombre. C'est encore un avantage d'envoyer des valeurs numériques.


    pour mémoire :
    unsigned char nombre = 0x41; sera stocké sous la forme 0100 0001 en mémoire.
    unsigned char nombre = 65; sera stocké sous la forme 0100 0001 en mémoire.
    unsigned char nombre = 'A'; sera stocké sous la forme 0100 0001 en mémoire.

    Donc peu importe la base utilisée, décimale ou hexadécimale, ou même octale et même si on parle de caractère ASCII de toute façon à la fin c'est en binaire dans la mémoire.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    unsigned char portWrite = 129; // 129 en décimal se code 1000 0001 en binaire, remarquons que j'aurai pu aussi écrire 0x81 ou encore 'ü' 
     
    // je veux mettre les bits 3 et 4 à 1 sans toucher aux autres
    // je veux ceci 1001 1001 
     
    portWrite = portWrite | 0x18; 
     
    // j'ai fait un masque logique OU avec la valeur 0x18 qui se code 0001 1000 en binaire
    Exemple 100% équivalent mais écrit autrement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    unsigned char portWrite = 129; // 129 en décimal se code 1000 0001 en binaire, remarquons que j'aurai pu aussi écrire 0x81 ou encore 'ü' 
     
    // je veux mettre les bits 3 et 4 à 1 sans toucher aux autres
    // je veux ceci 1001 1001 
     
    portWrite = portWrite | (1 << 4) | (1 << 3); 
     
    // j'ai fait un masque logique OU avec la valeur 0x18 qui se code 0001 1000 en binaire
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  3. #3
    Expert éminent
    Avatar de Auteur
    Profil pro
    Inscrit en
    avril 2004
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : avril 2004
    Messages : 7 152
    Points : 9 977
    Points
    9 977

    Par défaut

    Bonsoir,

    j'avoue ne pas avoir compris ce que tu souhaites faire. Tu veux convertir un entier décimal en binaire ?

    Si tu veux aller vite, et si tu travailles avec un Arduino, tu peux réaliser des accès directs sur tes ports, en prenant tout de même quelques précautions :
    https://www.arduino.cc/en/Reference/PortManipulation

  4. #4
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    janvier 2005
    Messages
    565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : janvier 2005
    Messages : 565
    Points : 115
    Points
    115

    Par défaut

    Wah, très cool ces réponses.

    Bon, alors, j'en ai... bref; il est un temps pour toute choses. finir ou avancer. Je pense passer en mode recodage avec des classes ensuite. En attendant, je vous livre le résultat en pièce jointe. D'où l'utilité de piloter qu'une pinoche a la fois.

    Donc, mon problème est le suivant. Le code actuel récupère une valeur de 0-255. Elle doit être ensuite écrite sur les ports. C'est très bien mais du coup, j'écris a chaque fois tout les bits du port, alors que je ne veux que modifier celui qui doit être.

    Code actuelle (qui doit évoluer):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void outSquare(byte port)
    {
      PORTD = port << 2;
      PORTB = (port & 0xf0) >> 4;
    }
    Donc, je décale de 2 sur le portD car les deux premières pattes sont réservés au TX/TX.
    et suite je masque et je décale à gauche pour travailler sur le second portB.

    Cela m'évite de croiser les fils (bah oui, c'est chiant ensuite sur le PCB...).

    Et enfin, je rentre depuis un int via un byte et ça c'est très très moche ! Il dit y avoir moyen d'optimiser ça ; en théorie !

    En attendant de continuer, je vous souhaite une bonne soirée.

  5. #5
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    septembre 2008
    Messages
    791
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : septembre 2008
    Messages : 791
    Points : 2 508
    Points
    2 508

    Par défaut

    Bonjour à tous

    Il y a plusieurs façons de faire en fonction de ce que l'on veut faire exactement!
    Ne modifier qu'un pin:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    PORTB |= _BV(6); // met à 1 la patte 6 du Port B
    PORTB &= ~_BV(6); // met à 0 la patte 6 du Port B
    Cela sera compilé avec SBI et CBI (Set ou Clear Bit in I/O register) qui est très rapide (2 cycles CPU) et efficace à condition que le Port et le bit soient écrit en dur dans le code (ou alors avec une constante) car sinon SBI et CBI ne sont pas utilisable.

    Modifier une partie d'un Port, dans cet exemple les 4 bits hauts:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    uint8_t var; // var doit être défini sur 8 bits, byte ou char aussi possible.
    ... 
    var &= 0xF0; // on s'assure que la variable n'a à 1 que les bits que l'on veut modifier, peut être ignoré en fonction du code précédent par exemple si var = foo << 4;
    PORTB = (PORTB & 0x0F) | var;
    C'est le principe du masquage! & 0 met le bit à 0; & 1 et | 0 laissent le bit dans son état; | 1 force le bit à 1. Appliqué à l'entier d'un byte cela permet de choisir sur quels bits on veux agir.

    Enfin sur AVR écrire un 1 sur PinX inverse l'état de sortie des pattes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PINB = 0x55; // les sorties 0, 2, 4 et 6 sont inversées par rapport à leur état précédent
    Bonne journée,
    Delias

    PS tous ces exemples supposent que le PortB est configuré en sortie (DDRB = 0xFF;). C'est écrit sans vérification sur compilateur, il y a éventuellement de petites coquilles.

    [Edit] Les exemples sont prévu pour un micro avec un Port B complet, ce n'est pas le cas de l'ATmega328p en configuration Arduino désolé j'ai l'habitude des 20 et 40 pattes qui eux ont un port B au complet.
    Il est inutile et contre-productif de conserver dans une variable l'état du Port. L'accès en SRAM à la variable est au minimum autant couteux que l'accès à PortX dans l'espace I/O.

Discussions similaires

  1. Ne mettre à jour que les données modifié
    Par demanghonj dans le forum Hibernate
    Réponses: 3
    Dernier message: 10/06/2009, 15h21
  2. Réponses: 11
    Dernier message: 23/01/2009, 08h47
  3. [Linq To SQL] Champ qui refuse de se mettre à jour
    Par nicolas.pied dans le forum Accès aux données
    Réponses: 1
    Dernier message: 20/10/2008, 08h34
  4. Réponses: 16
    Dernier message: 19/02/2008, 14h10
  5. [WD-2003] Renvois qui ne veulent pas se mettre à jour
    Par Veronyc dans le forum Word
    Réponses: 6
    Dernier message: 11/01/2008, 23h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo