SPI Arduino En raison d'un conflit avec pinMode (), bug?

9

Considérez l'exemple minimal suivant, où j'ai défini pinModeavant d'appeler des fonctions SPI:

#include <SPI.h>

void setup() {
  pinMode(10, OUTPUT);
  SPI.begin(10);
  SPI.setDataMode(10,SPI_MODE1);
}

void loop() {
  delay(1000);
  SPI.transfer(10,1);
}

Maintenant, quand SPI.transfer(10,1)est appelé loop(), je vois toujours que la broche sélectionnée par l'esclave descend à 1,65 V, mais pas à 0 comme il se doit! (voir l'image ci-dessous)

mode pin défini avant d'appeler les fonctions SPI

Si nous n'appelons pas pinMode(), comme ceci:

#include <SPI.h>

void setup() {
  SPI.begin(10);
  SPI.setDataMode(10,SPI_MODE1);
}

void loop() {
  delay(1000);
  SPI.transfer(10,1);
}

Nous obtenons ce à quoi nous nous attendions en appelant SPI.transfer:

Mode PIN non défini

Est-ce un bug ou avez-vous une explication à ce comportement?

Merci d'avance pour votre temps et votre intérêt!

newandlost
la source
N'est-ce pas SPI.setDataMode(10, SPI_MODE1);? De plus, seul le second est utile, comme begin()appelle setDataMode. En regardant le code source, il semble que la bibliothèque SPI ne modifie pas la broche que vous avez spécifiée (bien que je ne connaisse pas ARM).
Gerben
Ja tu as raison, par accident j'appelle setDataMode () deux fois. Demain, je testerai l'effet de SPI.setDataMode (10, SPI_MODE1); Mais pourquoi appeler pinMode () a cet effet n'est toujours pas clair ou? @Gerben
newandlost
@Gerben J'ai modifié mon message
newandlost

Réponses:

1

Cela pourrait avoir quelque chose à voir avec la résistance de rappel interne. Selon la fiche technique SAM3X / A,

Le contrôle de la résistance de rappel est possible quelle que soit la configuration de la ligne d'E / S.

Après la réinitialisation, tous les pull-ups sont activés.

Si vous fouillez tous les fichiers d'inclusion que vous trouvez:

../Arduino/hardware/arduino/samd/cores/arduino/wiring_digtal.c

La ligne 124 définit la pinMode(uint32_t ulPin, uint32_t ulMode)fonction. En examinant l'instruction switch / case pour INPUT vs INPUT_PULLUP vs OUTPUT, vous voyez ce qui suit:

  1. INPUT définit un registre sur reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP définit un registre sur reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. OUTPUT définit un registre sur reg &= ~PORT_PINCFG_INEN.

Le «registre» dans chaque cas est le même. Je ne peux pas pour la vie de trouver quelle valeur PORT_PINCFG_INEN ou PORT_PINCFG_PULLEN sont définis comme, mais ce ne sont sans doute que des masques 8 bits (ils sont castés en uint8_t lorsqu'ils sont affectés au `` registre ''). Ainsi, nous pouvons supposer que le bit qui contrôle l'entrée / la sortie est actif lorsqu'il est activé, tout comme le bit de pullup. Par exemple:

 PORT_PINCFG_INEN   = b'00000001';
 PORT_PINCFG_PULLEN = b'00000010';
~PORT_PINCFG_INEN   = b'11111110';

Si les tractions sont activées après la réinitialisation, nous pouvons dire que lors de la réinitialisation:

 reg = b'xxxxxx1x';

Le point (3) ci-dessus implique fortement que l'instruction est:

 reg = b'xxxxxx1x' & 'b11111110';
   so
 reg = b'xxxxxx10'; // pull-up is enabled!

Par conséquent, si vous appelez pinMode (X, OUTPUT) avant toute autre chose, vous vous retrouverez avec la résistance de pullup activée. Le réglage de la broche sur une entrée effacera le bit d'activation de pullup, après quoi vous pouvez définir la broche sur une sortie et le bit restera clair.

Cependant, toute arguement tombe avec le simple fait que si vous n'appelez pinMode () du tout , le problème ne se produit pas ...

CharlieHanson
la source