• How to Use SPI Communication in STM32 Microcontroller

QC

How to Use SPI Communication in STM32 Microcontroller

 How to Use SPI Communication in STM32 Microcontroller



Trong các hướng dẫn trước đây, chúng ta đã tìm hiểu về giao tiếp SPI và I2C giữa hai bo mạch Arduino. Trong hướng dẫn này, chúng tôi sẽ thay thế một bảng Arduino bằng bảng Blue Pill là STM32F103C8 và sẽ giao tiếp với bảng Arduino bằng cách sử dụng bus SPI. Trong Ví dụ STM32 SPI này, chúng ta sẽ sử dụng Arduino UNO làm Slave và STM32F103C8 làm Master với Hai màn hình LCD 16X2 được gắn vào nhau riêng biệt. Hai chiết áp cũng được kết nối với STM32 (PA0) và Arduino (A0) để xác định các giá trị gửi (0 đến 255) từ chính đến phụ và phụ đến chính bằng cách thay đổi chiết áp.

SPI in STM32F103C8

So sánh bus SPI trong bảng Arduino & STM32F103C8 Blue Pill, STM32 có 2 bus SPI trong khi Arduino Uno có một bus SPI. Arduino Uno có vi điều khiển ATMEGA328 và STM32F103C8 có ARM Cortex-M3 làm cho nó nhanh hơn Arudino Board.

STM32 SPI Pins STM32F103C8


SPI Line1Pin in STM32F103C8
MOSI1PA7 or PB5
MISO1PA6 or PB4
SCK1PA5 or PB3
SS1PA4 or PA15
SPI Line2 
MOSI2PB15
MISO2PB14
SCK2PB13
SS2PB12

SPI Pins in Arduino



SPI LinePin in Arduino
MOSI11 or ICSP-4
MISO12 or ICSP-1
SCK13 or ICSP-3
SS10

Components Required

  • STM32F103C8
  • Arduino
  • LCD 16x2 - 2
  • 10k Potentiometer – 4
  • Breadboard
  • Connecting Wires

Circuit Diagram and Connections for STM32 SPI Tutorial



The Table Below shows the Pins Connected for STM32 SPI communication with Arduino.

SPI PinSTM32F103C8Arduino
MOSIPA711
MISOPA612
SCKPA513
SS1PA410

The table below shows the pins connected for Two LCD (16x2) with STM32F103C8 and Arduino separately.

LCD pinSTM32F103C8Arduino
VSSGNDGND
VDD+5V+5V
V0To Potentiometer Centre PIN for LCD contrastTo Potentiometer Centre PIN for LCD contrast
RSPB02
RWGNDGND
EPB13
D4PB104
D5PB115
D6PC136
D7PC147
A+5V+5V
KGNDGND

Important:

  • Don’t forget to connect the Arduino GND and STM32F103C8 GND together.

STM32 SPI Programming

Master STM32 SPI


#include<SPI.h>                                                               // Including Library for using SPI Communication

#define SS PA4                                                              

#include<LiquidCrystal.h>                                                     // Including LCD display library

const int rs = PB0, en = PB1, d4 = PB10 , d5 = PB11 , d6 = PC13, d7 = PC14;   // Declaring pin names and pin numbers of lcd

LiquidCrystal lcd(rs,en,d4,d5,d6,d7);                                         // Setting lcd and its paramaters

void setup (void)

{
  lcd.begin(16,2);                                                            // Setting lcd as 16x2 mode
  lcd.setCursor(0,0);                                                         // Setting cursor at first row and first column
  lcd.print("CIRCUIT DIGEST");                                                // Puts CIRCUIT DIGEST in LCD
  delay(3000);                                                                // Delays for 3 seconds
  lcd.clear();                                                                // Clears lcd display
  
  Serial.begin(9600);                                                         // Starts Serial Communication at Baud Rate 9600
  pinMode(SS,OUTPUT);                                                         // Puts SS as Output
  SPI.begin();                                                                // Begins the SPI commnuication
  SPI.setClockDivider(SPI_CLOCK_DIV16);                                       // Sets clock for SPI communication at 16 (72/16=4.5Mhz)
  digitalWrite(SS,HIGH);                                                      // Setting SlaveSelect as HIGH (So master doesnt connnect with slave)
}

void loop(void)

  
  byte MasterSend,MasterReceive;
  
  int pot = analogRead(PA0);                                                   // Analog read the input pot value at pin 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);                                                       // Starts communication with Slave connected to master
  
  MasterReceive=SPI.transfer(MasterSend);                                      // Send the mastersend value to slave also receives value from slave
  Serial.println("Slave Arduino to Master STM32");                             // Used in Serial Monitor
  Serial.println(MasterReceive);                                               // Puts value Received im Serail Monitor
  lcd.setCursor(0,0);                                                          
  lcd.print("Master: STM32");
  lcd.setCursor(0,1);                                                    
  lcd.print("SalveVal:");                                                         
  lcd.print(MasterReceive);                                                    // Puts the received value from slave arduino      
  delay(500);
  digitalWrite(SS, HIGH);                                                      // Again make SS line HIGH so that it doesnt communicate with Slave
  lcd.clear();

}

Slave Arduino SPI


#include<SPI.h>                           // Including Library for using SPI Communication
#include<LiquidCrystal.h>                 // Including LCD display library
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);      // Define LCD Module Pins (RS,EN,D4,D5,D6,D7)
volatile boolean received;
volatile byte SlaveReceived,Slavesend;
void setup()


  lcd.begin(16,2);                        // Initilize LCD display
  lcd.setCursor(0,0);                     // Sets Cursor at first line of Display 
  lcd.print("CIRCUIT DIGEST");            // Prints CIRCUIT DIGEST in LCD 
  delay(3000);                            // Delay for 3 seconds
  lcd.clear();                            // Clears LCD display
  
  Serial.begin(9600);                     // Starts Serial Communication at Baud Rate 9600
  
  pinMode(MISO,OUTPUT);                   // Sets MISO as OUTPUT (Have to Send data to Master IN (STM32F103C8)

  SPCR |= _BV(SPE);                       // Turn on SPI in Slave Mode
  received = false;
  SPI.attachInterrupt();                  // Interuupt ON is set for SPI commnucation
}

ISR (SPI_STC_vect)                        // Inerrrput routine function 
{
  SlaveReceived = SPDR;                   // Value received from master STM32F103C8 is stored in variable slavereceived
  received = true;                        // Sets received as True 
}

void loop()

  int pot = analogRead(A0);               // Analog read the input pot value from analog pin A0
  Slavesend = map(pot,0,1023,0,255);      // Converts the value pot (0-1023) to (0-255) for sending to master stm32 
                              
  SPDR = Slavesend;                       // Sends the salvesend value to master STM32F103C8 via SPDR 
  lcd.setCursor(0,0);                     
  lcd.print("Slave: Arduino");
  lcd.setCursor(0,1);                                                     
  lcd.print("MasterVal:");    
  Serial.println("Master STM32 to Slave Arduino");   
  Serial.println(SlaveReceived);                   // Puts the received value from Master STM32F103C8 at Serial Monitor                          
  lcd.print(SlaveReceived);                        // Puts the received value from Master STM32F103C8 at LCD display
  delay(500);
  lcd.clear();
}

Master STM32 SPI Programming Explanation

1. First of all we need to include the SPI library for using SPI communication functions and LCD library for using LCD functions. Also define LCD pins for 16x2 LCD. Learn more about interfacing LCD with STM32 here.

#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. In void setup()

  • Start Serial Communication at Baud Rate 9600.
Serial.begin(9600);  
  • Next begin the SPI communication
SPI.begin(); 
  • Then set the Clock divider for SPI communication. I have set divider 16.
SPI.setClockDivider(SPI_CLOCK_DIV16);   
  • Next set the SS pin HIGH since we didn’t start any transfer to slave arduino.
digitalWrite(SS,HIGH);                 

3. In void loop()

  • Before sending any value to slave we need to LOW the slave select value to begin transfer to slave from master.
digitalWrite(SS, LOW);        
  • Next read the analog value from the master STM32F10C8 POT attached to pin PA0.
int pot = analogRead(PA0);                      

Then convert this value in terms of one byte (0 to 255).

byte MasterSend = map(pot,0,4096,0,255);        
  • Here comes the important step, in the following statement we send the converted POT value stored in Mastersend variable to the slave Arduino, and also receive value from slave Arduino and stored that in mastereceive variable.
 Mastereceive = SPI.transfer(Mastersend);
  • Next display those received values from the slave arduino    with a delay of 500 microseconds and then continuously receive and display the values.
Serial.println("Slave Arduino to 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);  

Note: We use serial.println() to view the result in Serial Motor of Arduino IDE.

Slave Arduino SPI Programming Explanation

1. Same as master, first of all we need to include the SPI library for using I2C communication functions and LCD library for using LCD functions. Also define LCD pins for 16x2 LCD.

#include<SPI.h>  
#include<LiquidCrystal.h> 
 LiquidCrystal lcd(2, 3, 4, 5, 6, 7);    // Define LCD Module Pins (RS,EN,D4,D5,D6,D7)

2. In void setup()

  • We Start Serial Communication at Baud Rate 9600.
Serial.begin(9600);               
  • Below statement sets MISO as OUTPUT (Have to Send data to Master IN).So data is sent via MISO of Slave Arduino.
pinMode(MISO,OUTPUT);                  
  • Now Turn on SPI in Slave Mode by using SPI Control Register
SPCR |= _BV(SPE);                    
  • Then turn ON interrupt for SPI communication. If a data is received from master the Interrupt Service Routine is called and the received value is taken from SPDR (SPI data Register)
SPI.attachInterrupt();         
  • The value from master is taken from SPDR and stored in Slavereceived variable. This takes place in following Interrupt Routine function.
ISR (SPI_STC_vect)
{
  Slavereceived = SPDR;                  
  received = true;                       
}

3. Next in void loop ()

  • Read the analog value from the Slave Arduino POT attached to pin A0.
int pot = analogRead(A0);                     
  • Convert that value in terms of one byte as 0 to 255. 
Slavesend = map(pot,0,1023,0,255);
  • Next important step is to send the converted value to the Master STM32F10C8, so place the value in the SPDR register. The SPDR register is used to send and receive values.
SPDR = Slavesend;
  • Then display the received value (SlaveReceive) from Master STM32F103C8 on LCD with a delay of 500 microseconds and then continuously receive and display those value.
 lcd.setCursor(0,0);                     
 lcd.print("Slave: Arduino");
 lcd.setCursor(0,1);                                                    
 lcd.print("MasterVal:");   
 Serial.println("Master STM32 to Slave Arduino");  
 Serial.println(SlaveReceived);                  
 lcd.print(SlaveReceived);                       
 delay(500);




Nap Code vào PY32F003 dùng Stlink

 Nap Code vào PY32F003 dùng Stlink Bước 1: Cài đặt  KeilC v5.39 theo link sau ( chú ý 5.39 keil c mới nạp ok). https://edge07.111.ir.cdn.ir/...