Comunicação SPI (Serial Peripheral Interface), protocolo síncrono serial, entre dois Arduinos Uno.
Referências para consultar:
* https://www.arduino.cc/en/reference/SPI
* https://learn.sparkfun.com/tutorials/serial-peripheral-interface-sp...
* https://arduino.stackexchange.com/questions/16348/how-do-you-use-sp...
Explicando este experimento:
* Neste experimento são necessários 2 Arduinos, um para master e outro para slave.
* O Arduino master enviará automaticamente e seguidamente, a cada 5 segundos, duas sequências de caracteres...
* A primeira sequência de caracteres é composta de um caracter 'a' seguido dos números 10, 17, 33 e 42, da seguinte forma:
* 1. o slave recebe o primeiro byte do master, o caracter 'a' e espera pelo próximo byte do master. O caracter 'a' sinaliza para o slave adicionar 10 aos números que receber a seguir
* 2. o slave receber o segundo byte, o número 10, e então adiciona 10 ao número 10 recebido, resultando 20, e espera
* 3. o slave recebe o terceiro byte do master, o número 17, somando 10 a ele, e aproveita esta conexão para enviar, ao mesmo tempo (comunicação full duplex) em que recebe, o resultado da operação de adição anterior, o númro 20
* 4. o slave recebe o quarto byte do master, o número 33, somando 10 a ele, e aproveita esta conexão para enviar, ao mesmo tempo (comunicação full duplex) em que recebe, o resultado da operação de adição anterior, o número 27
* 5. o slave recebe o quinto byte do master, o número 42, somando 10 a ele, e aproveita esta conexão para enviar, ao mesmo tempo (comunicação full duplex) em que recebe, o resultado da operação de adição anterior, o número 43
* 6. o master não tem mais números a enviar para o slave mas o slave tem uma resposta a enviar para o master, o número 52, resultado da adição de 10 + 42
* 7. então o master, para não ficar sem esse resultado, envia um caracter qualquer para o slave e o slave aproveita esta conexão para enviar o número 52 para o master, finalizando a sequencia numérica enviada pelo master
* A segunda sequência de caracteres é composta de um caracter 's' seguido dos mesmos números 10, 17, 33 e 42, porém o 's' sinaliza para o slave agora fazer a subtração de 10 nestes números na mesma sequencia anterior
Pinagem entre os dois Arduinos Uno:
* Master <==> Slave
* D10 (SS) D10 (SS)
* D11 (MOSI) D11 (MOSI)
* D12 (MISO) D12 (MISO)
* D13 (SCK) D13 (SCK)
* 5V Vin
* GND GND
Código (sketch) para o Arduino master:
* Neste sketch (master) usaremos a biblioteca <SPI.h>
-------------------------------------------------------------------------------------------------------------------------------------------------
#include <SPI.h>
SPISettings settings(4000000, MSBFIRST, SPI_MODE0); // define velocidade desta conexão SPI em
// 4MHz (16MHz do Uno / 4 = 4MHz, default)
void setup(){
Serial.begin (9600);
Serial.println();
digitalWrite(SS, HIGH); // desabilitar comunicação com o slave. Garantir que o pino SS do
// master não inicie habilitando a comunicação com o slave (SS em
//estado ALTO = desconectado)
SPI.begin();
}
byte charInOut(const byte charOut){ // rotina para transferir 1 byte do master para o slave
byte charIn = SPI.transfer(charOut); // transfer 1 byte para o slave e, ao mesmo tempo, recebe 1
// byte do slave armazenando-o em 'a'
delayMicroseconds(20); // pausa por 0,000.02 segundos ou 20 microsegundos
return charIn;
}
void loop(){
byte a, b, c, d;
digitalWrite(SS, LOW); // habilitar comunicação SPI com o slave
SPI.beginTransaction(settings); // inicializar a conexão SPI usando o SPIsettings definido
charInOut('a'); // enviar o caracter 'a' para o slave. Neste sketch o caracter 'a'
// sinaliza para o slave fazer uma operação de adição
charInOut(10); // enviar o número 10 para o slave e, ao mesmo tempo, não
// receber o que quer que seja do slave
a = charInOut(17); // enviar o número 17 para o slave e, ao mesmo tempo, receber
// o dado enviado do slave armazenando-o na variável "a"
b = charInOut(33); // enviar o número 33 para o slave e, ao mesmo tempo, receber
// o dado enviado do slave armazenando-o na variável "b"
c = charInOut(42); // enviar o número 42 para o slave e, ao mesmo tempo, receber
// o dado enviado do slave armazenando-o na variável "c"
d = charInOut(0); // enviar o número 0 (ou qualquer outro caracter) para o slave e,
// ao mesmo tempo, receber o dado enviado do slave
// armazenando-o na variável "d". Esta operação só existe para
// receber dado do slave
SPI.endTransaction(); // finalizar a conexão SPI
digitalWrite(SS, HIGH); // desabilitar comunicação SPI com slave
Serial.print("O números são 10, 17, 33 e 42. Adicionando 10: ");
Serial.print(a, DEC);
Serial.print(", ");
Serial.print(b, DEC);
Serial.print(", ");
Serial.print(c, DEC);
Serial.print(", ");
Serial.print(d, DEC);
digitalWrite(SS, LOW); // habilitar comunicação SPI com o slave
SPI.beginTransaction(settings); // inicializar a conexão SPI usando o SPIsettings definido
charInOut('s'); // enviar o caracter 's' para o slave. Neste sketch o caracter 's'
// sinaliza para o slave fazer uma operação de subtração
charInOut(10); // enviar o número 10 para o slave e, ao mesmo tempo, não
// receber o que quer que seja do slave
a = charInOut(17); // enviar o número 17 para o slave e, ao mesmo tempo, receber o
// dado enviado do slave armazenando-o na variável "a"
b = charInOut(33); // enviar o número 33 para o slave e, ao mesmo tempo, receber o
// dado enviado do slave armazenando-o na variável "b"
c = charInOut(42); // enviar o número 42 para o slave e, ao mesmo tempo, receber o
// dado enviado do slave armazenando-o na variável "c"
d = charInOut(0); // enviar o número 0 (ou qualquer outro caracter) para o slave e,
// ao mesmo tempo, receber o dado enviado do slave
// armazenando-o na variável "d". Esta operação só existe para
// receber dado do slave
SPI.endTransaction(); // finalizar a conexão SPI
digitalWrite(SS, HIGH); // desabilitar comunicação SPI com slave
Serial.print(". Subtraindo 10: ");
Serial.print(a, DEC);
Serial.print(", ");
Serial.print(b, DEC);
Serial.print(", ");
Serial.print(c, DEC);
Serial.print(", ");
Serial.println(d, DEC);
Serial.println();
delay (5000); // esperar 5 segundos para fazer isso tudo novamente
}
-------------------------------------------------------------------------------------------------------------------------------------------------
Código (sketch) para o Arduino slave:
* Neste sketch não usaremos a biblioteca <SPI.h> mas trabalharemos diretamente com os registradores SPI
-------------------------------------------------------------------------------------------------------------------------------------------------
volatile byte command = 'x'; // Para ter certeza que dados de variáveis globais sejam
// passados entre as ISRs e o programa principal, use definir
// a variável como "volatile"
void setup(){
pinMode(MISO, OUTPUT); // pino MISO deste slave é definido como de output
SPCR |= _BV(SPE); // Habilitar a comunicação SPI neste slave atribuindo 1 ao bit
// SPE do registrador SPCR do SPI do Arduino, ou seja,
// habilitar SPI neste slave
SPCR |= _BV(SPIE); // Habilitar a interrupção SPI atribuindo 1 ao bit SPIE do
// registrador SPCR do SPI do Arduino
}
ISR(SPI_STC_vect){ // Interrupt Service Routine (ISR), SPI_STC_vect, esta
// interrupção será executada enquanto estiver recebendo
// dados do master, ou seja, a interrupt do pino SS em estado
// BAIXO
byte c = SPDR; // lê o registrador "de troca" SPDR que contém o dado (o byte)
// enviado pelo master, armazenado-o na variável 'c'
switch (command){
case 'x': // se 'command' = 0, ou seja, se não tem uma ação de adição
// ou subtração
command = c; // atribui à variável 'command' o caracter recebido na variável 'c'
SPDR = 0; // escreve o número 0 no registrador SPDR, enviando-o ao
// master
break;
case 'a': // se 'command' = 'a' (de adição)
SPDR = c + 10; // soma 10 ao número armazenado em 'c' escrevendo o
// resultado no registrador SPDR, enviando-o ao master
break;
case 's': // se 'command' = 's' (de subtração)
SPDR = c - 10; // subtrai 10 ao número armazenado em 'c' escrevendo o
// resultado no registrador SPDR, enviando-o ao master
break;
}
}
void loop(){ // permanecerá dentro do void loop() enquanto a interrupção
// ISR(SPI_STC_vect) estiver em estado ALTO, ou seja, com a
// SPI inativa
if (digitalRead (SS) == HIGH) // se a interrupção estiver em estado ALTO, ou seja, se SPI
// inativa (não estiver recebendo dados do master)
command = 'x';
}
-------------------------------------------------------------------------------------------------------------------------------------------------
Tags:
Análise do gráfico, especificamente para a rotina destes sketchs:
* verificar que a linha SPI-Enable habilita a comunicação entre master e slave colocando-se em estado BAIXO.
* só então, e inicialmente, o master (Channel 3 - MOSI) envia um caracter para o slave (possivelmente o caracter 'a', ou 's') e, ao mesmo tempo, o slave (Channel 4 - MISO) envia um byte ao master (neste momento, conforme o sketch do slave, não há transmissão de dados para o master).
* no segundo momento, o master envia o número '10' mas o slave ainda não tem nada a enviar ao master
* no terceiro momento o master envia o número '17' e, ao mesmo tempo, o slave agora envia o número '20' (a adição de 10 + 10, conforme manda o sketch do slave) ao master.
* segue assim para os demais números do sketch (que não são demonstrados neste gráfico) até findar a execução dos sketch's, quando SPI-Enable desabilita a comunicação entre master e slave colocando-se em estado ALTO.
Conclusão: observa-se então ser a comunicação SPI full duplex.
Bem-vindo a
Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)
© 2024 Criado por Marcelo Rodrigues. Ativado por