Como usar a comunicação SPI no microcontrolador STM32
Neste tutorial, substituiremos uma placa Arduino pela placa Blue Pill que é Stm32f103c8t6 e nos comunicaremos com a placa Arduino usando o barramento SPI.
Neste exemplo STM32 SPI, usaremos Arduino UNO como escravo e STM32F103C8 como mestre com dois monitores LCD 16X2 conectados um ao outro separadamente. Dois potenciômetros também são conectados com STM32 (PA0) e Arduino (A0) para determinar os valores de envio (0 a 255) do mestre para o escravo e do escravo para o mestre variando o potenciômetro.
Conteudo
SPI em STM32F103C8
Comparando o barramento SPI no Arduino e a placa STM32F103C8 Blue Pill, o STM32 possui 2 barramentos SPI enquanto o Arduino Uno possui um barramento SPI. O Arduino Uno possui o microcontrolador ATMEGA328 e o STM32F103C8 possui o ARM Cortex-M3, o que o torna mais rápido que a placa Arudino.
Pinos SPI STM32F103C8
SPI Line1 | Pino em STM32F103C8 |
MOSI1 | PA7 ou PB5 |
MISO1 | PA6 ou PB4 |
SCK1 | PA5 ou PB3 |
SS1 | PA4 ou PA15 |
SPI Line2 | |
MOSI2 | PB15 |
MISO2 | PB14 |
SCK2 | PB13 |
SS2 | PB12 |
Pinos SPI no Arduino
SPI Line | Pino no Arduino |
MOSI | 11 ou ICSP-4 |
MISO | 12 ou ICSP-1 |
SCK | 13 ou ICSP-3 |
SS | 10 |
Componentes necessários
STM32F103C8
Arduino
LCD 16×2 – 2
Potenciômetro de 10k – 4
ProtoBoard
Fios de conexão
Diagrama de circuito e conexões
A tabela abaixo mostra os pinos conectados para comunicação STM32 SPI com o Arduino.
SPI Pino | STM32F103C8 | Arduino |
MOSI | PA7 | 11 |
MISO | PA6 | 12 |
SCK | PA5 | 13 |
SS1 | PA4 | 10 |
A tabela abaixo mostra os pinos conectados para Dois LCD (16×2) com STM32F103C8 e Arduino separadamente.
LCD pino | STM32F103C8 | Arduino |
VSS | GND | GND |
VDD | +5V | +5V |
V0 | Para o Pino do centro do potenciômetro para contraste do LCD | Para o Pino do centro do potenciômetro para contraste do LCD |
RS | PB0 | 2 |
RW | GND | GND |
E | PB1 | 3 |
D4 | PB10 | 4 |
D5 | PB11 | 5 |
D6 | PC13 | 6 |
D7 | PC14 | 7 |
A | +5V | +5V |
K | GND | GND |
Importante:
Não se esqueça de conectar o Arduino GND e o STM32F103C8 GND juntos.
Programação STM32 SPI
A programação é semelhante ao código do Arduino. A mesma biblioteca <SPI.h> é usada na programação STM32F103C8. Pode ser programado usando a porta USB sem usar o programador FTDI, para aprender mais sobre a programação STM32 com Arduino IDE siga o link.
Neste exemplo STM32 SPI, usaremos Arduino UNO como escravo e STM32F103C8 como mestre com dois monitores LCD 16X2 conectados um ao outro separadamente. Dois potenciômetros também são conectados com STM32 (PA0) e Arduino (A0) para determinar os valores de envio (0 a 255) do mestre para o escravo e do escravo para o mestre variando o potenciômetro.
A entrada analógica é feita no pino PA0 do STM32F10C8 (0 a 3,3 V) girando o potenciômetro. Em seguida, esse valor de entrada é convertido em valor analógico para digital (0 a 4096) e esse valor digital é posteriormente mapeado para (0 a 255), pois podemos enviar apenas dados de 8 bits (bytes) por meio da comunicação SPI de uma vez.
Da mesma forma, no lado escravo, pegamos o valor da entrada analógica no pino A0 do Arduino de (0 a 5V) usando o potenciômetro. E novamente este valor de entrada é convertido em valor analógico para digital (0 a 1023) e este valor digital é posteriormente mapeado para (0 a 255)
Este tutorial tem dois programas, um para o STM32 mestre e outro para o Arduino escravo. Programas completos para ambos os lados são fornecidos no final deste projeto.
Explicação de programação Master STM32 SPI
1. Em primeiro lugar, precisamos incluir a biblioteca SPI para usar as funções de comunicação SPI e a biblioteca LCD para usar as funções LCD. Defina também os pinos de LCD para LCD 16×2. Saiba mais sobre a interface do LCD com o STM32 aqui.
#include<SPI.h> #include<LiquidCrystal.h> const int rs = PB0, en = PB1, d4 = PB10 , d5 = PB11 , d6 = PC13, d7 = PC14; LiquidCrystal lcd(rs,en,d4,d5,d6,d7);
2. No void setup()
- Inicie a comunicação serial na taxa Baud 9600.
Serial.begin(9600);
- Em seguida, comece a comunicação SPI
SPI.begin();
- Em seguida, defina o divisor de relógio para comunicação SPI. Eu configurei o divisor 16.
SPI.setClockDivider(SPI_CLOCK_DIV16)
- Em seguida, defina o pino SS para ALTO, pois não iniciamos nenhuma transferência para o arduino escravo.
digitalWrite(SS,HIGH);
3. No void loop()
- Antes de enviar qualquer valor para o escravo, precisamos BAIXAR o valor de seleção do escravo para iniciar a transferência do mestre para o escravo.
digitalWrite(SS, LOW);
- Em seguida, leia o valor analógico do POT STM32F10C8 mestre conectado ao pino PA0.
int pot = analogRead(PA0);
Em seguida, converta esse valor em termos de um byte (0 a 255).
byte MasterSend = map(pot,0,4096,0,255);
- Aí vem a etapa importante, na instrução a seguir enviamos o valor convertido do POT armazenado na variável Mastersend para o Arduino escravo, e também recebemos o valor do Arduino escravo e o armazenamos na variável mastereceive.
Mastereceive = SPI.transfer(Mastersend);
- Em seguida, exiba os valores recebidos do arduino escravo com um atraso de 500 microssegundos e, em seguida, receba e exiba continuamente os valores.
Serial.println("Slave Arduino para Master STM32"); Serial.println(MasterReceive lcd.setCursor(0,0); lcd.print("Master: STM32"); lcd.setCursor(0,1); lcd.print("SalveVal:"); lcd.print(MasterReceive delay(500); digitalWrite(SS, HIGH);
Nota: Usamos serial.println() para visualizar o resultado no Serial Motor do Arduino IDE.
Explicação de programação SPI do Slave Arduino
1. Da mesma forma que o mestre, em primeiro lugar, precisamos incluir a biblioteca SPI para usar as funções de comunicação I2C e a biblioteca LCD para usar as funções LCD. Defina também os pinos de LCD para LCD 16×2.
#include<SPI.h> #include<LiquidCrystal.h> LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // Definir os pinos do módulo LCD (RS, EN, D4, D5, D6, D7)
2. No void setup()
- Iniciamos a comunicação serial na taxa Baud 9600.
Serial.begin(9600);
- A instrução abaixo define MISO como OUTPUT (tem que enviar dados para Master IN). Assim, os dados são enviados via MISO do Slave Arduino.
pinMode(MISO,OUTPUT);
- Agora ligue o SPI no modo escravo usando o registro de controle do SPI
SPCR |= _BV(SPE);
- Em seguida, ligue a interrupção para comunicação SPI. Se um dado for recebido do mestre, a rotina de serviço de interrupção é chamada e o valor recebido é obtido do SPDR (Registro de dados SPI)
SPI.attachInterrupt();
- O valor do master é retirado do SPDR e armazenado na variável Slavereceived. Isso ocorre na seguinte função de rotina de interrupção.
ISR (SPI_STC_vect) { Slavereceived = SPDR; received = true; }
3. Próximo em void loop ()
- Leia o valor analógico do Slave Arduino POT conectado ao pino A0.
int pot = analogRead(A0);
- Converta esse valor em termos de um byte de 0 a 255.
Slavesend = map(pot,0,1023,0,255);
- O próximo passo importante é enviar o valor convertido para o Master STM32F10C8, então coloque o valor no registrador SPDR. O registro SPDR é usado para enviar e receber valores.
SPDR = Slavesend;
- Em seguida, exiba o valor recebido (SlaveReceive) do Master STM32F103C8 no LCD com um atraso de 500 microssegundos e, em seguida, receba e exiba continuamente esse valor.
lcd.setCursor(0,0); lcd.print("Slave: Arduino"); lcd.setCursor(0,1); lcd.print("MasterVal:"); Serial.println("Master STM32 para Slave Arduino"); Serial.println(SlaveReceived); lcd.print(SlaveReceived); delay(500);
Girando o potenciômetro de um lado, você pode ver os valores variáveis no LCD do outro lado:
Portanto, é assim que a comunicação SPI ocorre no STM32. Agora você pode conectar qualquer sensor SPI com a placa STM32.
Código
Master STM32 SPI
//Código mestre SPI para STM32F103C8 //Comunicação SPI entre STM32 e Arduino #include<SPI.h> // Incluindo biblioteca para usar a comunicação SPI #define SS PA4 #include<LiquidCrystal.h> // Incluindo biblioteca de display LCD const int rs = PB0, en = PB1, d4 = PB10 , d5 = PB11 , d6 = PC13, d7 = PC14; // Declarando nomes e números de pinos de LCD LiquidCrystal lcd(rs,en,d4,d5,d6,d7); // Configurando lcd e seus parâmetros void setup (void) { lcd.begin(16,2); // Configurando lcd como modo 16x2 lcd.setCursor(0,0); // Setting cursor at first row and first column lcd.print("Cap Sistema"); // Coloque Cap Sistema no LCD delay(3000); // Delays por 3 segundos lcd.clear(); // Limpa o LCD Serial.begin(9600); // Inicia a comunicação serial na taxa Baud 9600 pinMode(SS,OUTPUT); // Coloca SS como saída SPI.begin(); // Começa a comunicação SPI SPI.setClockDivider(SPI_CLOCK_DIV16); // Define o relógio para comunicação SPI em 16 (72/16 = 4,5 MHz) digitalWrite(SS,HIGH); // Configurando Slave Select como HIGH (portanto, o mestre não se conecta ao escravo) } void loop(void) { byte MasterSend,MasterReceive; int pot = analogRead(PA0); // Analógico lê o valor do potenciômetro de entrada no pino PA0 MasterSend = map(pot,0,4096,0,255); // Used to convert pot value in terms of 0 to 255 from 0 to 4096 digitalWrite(SS, LOW); // Inicia a comunicação com o Slave conectado ao mestre MasterReceive=SPI.transfer(MasterSend); // Envia o valor do mastersend para o escravo também recebe o valor do escravo Serial.println("Slave Arduino para Master STM32"); // Usado no Monitor Serial Serial.println(MasterReceive); // Coloca valor recebido no monitor serial lcd.setCursor(0,0); lcd.print("Master: STM32"); lcd.setCursor(0,1); lcd.print("SalveVal:"); lcd.print(MasterReceive); // Coloca o valor recebido do arduino escravo delay(500); digitalWrite(SS, HIGH); // Novamente torna a linha SS ALTA para que não se comunique com o Slave lcd.clear(); }
Slave Arduino SPI
Slave Arduino SPI //Código SPI Slave para Arduino //Comunicação SPI entre STM32F103C8 e Arduino #include<SPI.h> // Incluindo biblioteca para usar a comunicação SPI #include<LiquidCrystal.h> // Incluindo biblioteca de display LCD LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // Defina os pinos do módulo LCD (RS, EN, D4, D5, D6, D7) volatile boolean received; volatile byte SlaveReceived,Slavesend; void setup() { lcd.begin(16,2); // Inicializar display LCD lcd.setCursor(0,0); // Define o cursor na primeira linha do display lcd.print("Cap Sistema"); // Imprime Cap Sistema no LCD delay(3000); // Delay por 3 secondos lcd.clear(); // Limpa o LCD Serial.begin(9600); // Inicia a comunicação serial na taxa Baud 9600 pinMode(MISO,OUTPUT); // Define MISO como OUTPUT (tem que enviar dados para Master IN (STM32F103C8) SPCR |= _BV(SPE); // Ligue o SPI no modo Slave received = false; SPI.attachInterrupt(); // A interrupção ON está definida para comunicação SPI } ISR (SPI_STC_vect) // Função de rotina de entrada { SlaveReceived = SPDR; // O valor recebido do mestre STM32F103C8 é armazenado na variável slavereceived received = true; // Conjuntos recebidos como verdadeiros } void loop() { int pot = analogRead(A0); // Analógico lê o valor do potenciômetro de entrada do pino analógico A0 Slavesend = map(pot,0,1023,0,255); // Converte o valor do potenciômetro (0-1023) em (0-255) para enviar ao mestre stm32 SPDR = Slavesend; // Envia o valor salvesend para o mestre STM32F103C8 via SPDR lcd.setCursor(0,0); lcd.print("Slave: Arduino"); lcd.setCursor(0,1); lcd.print("MasterVal:"); Serial.println("Master STM32 para Slave Arduino"); Serial.println(SlaveReceived); // Coloca o valor recebido do Mestre STM32F103C8 no Monitor Serial lcd.print(SlaveReceived); // Coloca o valor recebido do Mestre STM32F103C8 no display LCD delay(500); lcd.clear(); }
Conclusão
Neste artigo, mostrei como usar a Transferencias de dados SPI entre o Arduino e o STM32. Espero que você tenha achado útil e informativo. Se sim, compartilhe com um amigo que também gosta de eletrônica e de fazer coisas!
Eu adoraria saber quais projetos você planeja construir (ou já construiu) com esses tipo de transferencia usando os dois tipos. Se você tiver alguma dúvida, sugestão ou se achar que falta algo neste tutorial, por favor, deixe um comentário abaixo.