SPI Arduino Debido conflicto con pinMode (), error?


9

Considere el siguiente ejemplo mínimo, donde configuré pinModeantes de llamar a las funciones 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);
}

Ahora cuando SPI.transfer(10,1)se llama loop(), siempre veo que el pin esclavo seleccionado baja a 1.65V, ¡pero no a 0 como debería! (ver imagen a continuación)

modo pin configurado antes de llamar a funciones SPI

Si no llamamos pinMode(), así:

#include <SPI.h>

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

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

Obtenemos lo que esperaríamos al llamar SPI.transfer:

Modo pin no establecido

¿Es eso un error o tienes una explicación para ese comportamiento?

¡Muchas gracias de antemano por su tiempo e interés!


¿No debería ser SPI.setDataMode(10, SPI_MODE1);? También solo el segundo es útil, ya que begin()llama a setDataMode. Al mirar el código fuente , parece que la biblioteca SPI no altera el pin que especificó (aunque no conozco ARM).
Gerben

Ja tienes razón, por accidente estoy llamando a setDataMode () dos veces. Mañana probaré el efecto de SPI.setDataMode (10, SPI_MODE1); Pero, ¿por qué llamar a pinMode () tiene este efecto aún no está claro o? @Gerben
newandlost

@Gerben Modifiqué mi publicación
newandlost

Respuestas:


1

Puede tener algo que ver con la resistencia interna pull-up. De acuerdo con la hoja de datos SAM3X / A,

El control de la resistencia pull-up es posible independientemente de la configuración de la línea de E / S.

Después de restablecer, todos los pull-ups están habilitados.

Si busca en todos los archivos de inclusión que encuentre:

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

La línea 124 define la pinMode(uint32_t ulPin, uint32_t ulMode)función. Al examinar la declaración de cambio / caso para INPUT vs INPUT_PULLUP vs OUTPUT, verá lo siguiente:

  1. INPUT establece un registro en reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP establece un registro en reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. SALIDA establece un registro en reg &= ~PORT_PINCFG_INEN.

El 'registro' en cada caso es el mismo. Por mi vida no puedo encontrar qué valor se define como PORT_PINCFG_INEN o PORT_PINCFG_PULLEN, pero sin duda son solo máscaras de 8 bits (se envían a uint8_t cuando se asignan al 'registro'). Por lo tanto, podemos suponer que cualquier bit que controla la entrada / salida está activo cuando se afirma, como es el bit pullup. Por ejemplo:

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

Si los pull-ups están habilitados después del reinicio, podemos decir que en el reinicio:

 reg = b'xxxxxx1x';

El punto (3) anterior implica fuertemente que la instrucción es:

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

Por lo tanto, si llama a pinMode (X, OUTPUT) antes que nada , terminará con la resistencia pullup habilitada. Establecer el pin en una entrada borrará el bit de activación de pullup, después de lo cual puede configurar el pin en una salida y el bit permanecerá limpio.

Sin embargo, todo el argumento se cae con el simple hecho de que si usted no llama pinMode () en absoluto , el problema no se produce ...

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.