SPI Arduino Devido conflito com pinMode (), erro?

9

Considere o seguinte exemplo mínimo, em que eu defino pinModeantes de chamar as funções 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);
}

Agora, quando SPI.transfer(10,1)é chamado loop(), sempre vejo que o pino selecionado do escravo desce para 1,65V, mas não 0 como deveria! (veja a imagem abaixo)

modo pin definido antes de chamar as funções SPI

Se não ligarmos pinMode(), assim:

#include <SPI.h>

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

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

Conseguimos o que esperávamos ao chamar SPI.transfer:

pin modo não definido

Isso é um bug ou você tem uma explicação para esse comportamento?

Muito obrigado antecipadamente pelo seu tempo e interesse!

newandlost
fonte
Não deveria ser SPI.setDataMode(10, SPI_MODE1);? Além disso, apenas o segundo é útil, como begin()chama setDataMode. Observando o código - fonte , parece que a biblioteca SPI não altera o pino especificado (embora eu não conheça o ARM).
Gerben
Ja você está certo, por acidente eu estou chamando setDataMode () duas vezes. Amanhã testarei o efeito de SPI.setDataMode (10, SPI_MODE1); Mas por que chamar pinMode () tem esse efeito ainda não está claro ou? @Gerben
newandlost
@Gerben eu modifiquei meu post
newandlost 7/11

Respostas:

1

Pode ter algo a ver com o resistor pull up interno. De acordo com a folha de dados SAM3X / A,

O controle do resistor de pull-up é possível independentemente da configuração da linha de E / S.

Após a redefinição, todas as pull-ups são ativadas.

Se você pesquisar em todos os arquivos de inclusão, encontrará:

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

A linha 124 define a pinMode(uint32_t ulPin, uint32_t ulMode)função. Examinando a instrução switch / case para INPUT vs INPUT_PULLUP vs OUTPUT, você vê o seguinte:

  1. INPUT define um registro para reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP define um registro para reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. OUTPUT define um registro para reg &= ~PORT_PINCFG_INEN.

O 'registro' em cada caso é o mesmo. Eu não consigo encontrar o valor PORT_PINCFG_INEN ou PORT_PINCFG_PULLEN definido, mas sem dúvida são apenas máscaras de 8 bits (elas são convertidas em uint8_t quando atribuídas ao 'registrador'). Portanto, podemos assumir que qualquer bit que controla a entrada / saída está ativo quando afirmado, assim como o bit pullup. Por exemplo:

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

Se as pull-ups estiverem ativadas após a redefinição, podemos dizer que na redefinição:

 reg = b'xxxxxx1x';

O ponto (3) acima implica fortemente que a instrução é:

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

Portanto, se você chamar pinMode (X, OUTPUT) antes de qualquer outra coisa , acabará com o resistor de pullup ativado. Definir o pino como uma entrada limpará o bit de ativação de pullup, após o qual você poderá definir o pino para uma saída e o bit permanecerá limpo.

No entanto, todo o argumento cai com o simples fato de que se você não chamar pinMode () em tudo , o problema não ocorre ...

CharlieHanson
fonte