Hướng dẫn sử dụng SPI Communication với Vi điều khiển STM32

Hướng dẫn sử dụng SPI Communication với Vi điều khiển STM32

Mục lục

Trong ví dụ SPM STM32 này , chúng tôi sẽ sử dụng Arduino UNO là Slave và STM32F103C8 làm Master với hai màn hình LCD 16X2 gắn liền với nhau. Hai Potentiometer 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ừ master sang Slave và Slave sang master bằng cách thay đổi biến trở.

SPI trong STM32F103C8

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

Chân SPI STM32F103C8

SPI Line1 Chân trong STM32F103C8
MOSI1 PA7 hoặc PB5
MISO1 PA6 hoặc PB4
SCK1 PA5 hoặc PB3
SS1 PA4 hoặc PA15
SPI Line2
MOSI2 PB15
MISO2 PB14
SCK2 PB13
SS2 PB12

Chân SPI trong Arduino

 SPI 

Chân trong Arduino

MOSI

11 hoặc ICSP-4

MISO

12 hoặc ICSP-1

SCK

13 hoặc ICSP-3

SS

10

Linh kiện cần thiết

  • STM32F103C8
  • Arduino
  • LCD 16×2 – 2
  • Biến trở 10k – 4
  • Breadboard
  • Dây dẫn

Sơ đồ mạch và kết nối

Bảng bên dưới hiển thị các chân được kết nối để giao tiếp STM32 SPI với Arduino.

Chân SPI

STM32F103C8

Arduino

MOSI

PA7

11

MISO

PA6

12

SCK

PA5

13

SS1

PA4

10

Bảng bên dưới hiển thị các chân được kết nối cho Hai LCD (16×2) với STM32F103C8 và Arduino riêng biệt .

Chân LCD

STM32F103C8

Arduino

VSS

GND

GND

VDĐ

+ 5V

+ 5V

V0

Để chân Trung tâm Potentiometer cho độ tương phản LCD

Để chânTrung tâm Potentiometer cho độ tương phản LCD

RS

PB0

2

RW

GND

GND

E

PB1

3

D4

PB10

4

D5

PB11

5

D6

PC13

6

D7

PC14

7

Một

+ 5V

+ 5V

K

GND

GND

Quan trọng:

  • Đừng quên kết nối Arduino GND và STM32F103C8 GND với nhau.

Lập trình STM32 SPI

Việc lập trình tương tự như code Arduino. Thư viện <SPI.h> tương tự được sử dụng trong lập trình STM32F103C8. Nó có thể được lập trình bằng cổng USB mà không cần sử dụng FTDI.

Trong ví dụ SPM STM32 này , chúng tôi sẽ sử dụng Arduino UNO là Slave và STM32F103C8 làm Master với hai màn hình LCD 16X2 gắn liền với nhau. Hai Potentiometer 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ừ master sang Slave và Slave sang master bằng cách thay đổi biến trở.

Đầu vào tương tự được lấy ở chân STM32F10C8 PA0 (0 đến 3,3V) bằng cách xoay biến trở. Sau đó, giá trị đầu vào này được chuyển đổi thành giá trị Analog sang Digital (0 đến 4096) và giá trị số này được ánh xạ tiếp theo (0 đến 255) vì chúng tôi chỉ có thể gửi dữ liệu 8 bit (byte) thông qua giao tiếp SPI cùng một lúc.

Tương tự ở phía Slave, chúng ta lấy giá trị đầu vào tương tự ở chân Arduino A0 từ (0 đến 5V) bằng cách sử dụng biến trở. Và một lần nữa giá trị đầu vào này được chuyển đổi từ giá trị Analog sang Digital (0 đến 1023) và giá trị  số này được ánh xạ thêm vào (0 đến 255)

Hướng dẫn này có hai chương trình một cái dành cho STM32 và chương trình còn lại dành cho Arduino. Các chương trình hoàn chỉnh  cho cả hai bên được đưa ra vào cuối dự án này với một  Video trình diễn .

Giải thích về lập trình STM32 SPI

1. Trước hết chúng ta cần  thêm thư viện SPI  để sử dụng các chức năng giao tiếp SPI và thư viện LCD để sử dụng các chức năng LCD. Cũng xác định chân LCD cho LCD 16×2.

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

  • Mở Serial Communication  ở tốc độ Baud 9600.
Serial.begin (9600);  
  • Tiếp theo bắt đầu giao tiếp SPI
Serial.begin(9600);  
  • Sau đó đặt bộ chia xung để giao tiếp SPI. Tôi đã đặt dải phân cách 16.
SPI.setClockDivider (SPI_CLOCK_DIV16);   
  • Tiếp theo, đặt chân SS HIGH vì chúng tôi không bắt đầu chuyển gì sang arduino.
digitalWrite(SS,HIGH); 

3. Trong void loop()

  • Trước khi gửi bất kỳ giá trị nào cho slave, chúng ta cần chọn giá trị LOW cho slave để bắt đầu chuyển từ slave sang master.
digitalWrite(SS, LOW);   
  • Tiếp theo đọc giá trị tương tự từ POT STM32F10C8 chính được gắn vào chân PA0.
int pot = analogRead(PA0); 

Sau đó chuyển đổi giá trị này theo một byte (0 đến 255).

byte MasterSend = map(pot,0,4096,0,255);  
  • Ở đây có bước tiến quan trọng, trong đoạn code sau chúng tôi gửi các giá trị POT chuyển đổi lưu trữ trong biến Mastersend  đến slave Arduino, và cũng có thể nhận được giá trị từ slave Arduino và được lưu trữ trong biến mastereceive.
Mastereceive = SPI.transfer(Mastersend);
  • Tiếp theo hiển thị những giá trị nhận được từ slave arduino với delay 500 micro giây và sau đó liên tục nhận và hiển thị các giá trị.
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);  

Lưu ý: Chúng tôi sử dụng serial.println () để xem kết quả trong Serial Motor của Arduino IDE.

Giải thích về lập trình Arduino SPI

1. Giống như trên, trước hết chúng ta cần thêm thư viện SPI  để sử dụng các chức năng giao tiếp I2C và thư viện LCD để sử dụng các chức năng LCD. Cũng xác định chân LCD cho LCD 16×2.

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

  • Dặt Serial Communication ở tốc độ Baud 9600.
Serial.begin(9600);  
  • Câu lệnh bên dưới đặt MISO là OUTPUT (Phải gửi dữ liệu tới Master IN). Dữ liệu được gửi qua MISO của Slave Arduino.
pinMode(MISO,OUTPUT);   
  • Bây giờ Bật SPI ở Chế độ slave bằng cách sử dụng Đăng ký điều khiển SPI
SPCR |= _BV(SPE);
  • Sau đó bật ON cho SPI. Nếu dữ liệu được nhận từ master, thì Dịch vụ ngắt được gọi và giá trị nhận được lấy từ SPDR (Đăng ký dữ liệu SPI)
SPI.attachInterrupt();   
  • Giá trị từ master được lấy từ SPDR và ​​được lưu trong biến Slavereceured . Điều này diễn ra trong hàm Routine theo sau.
ISR (SPI_STC_vect)
{
  Slavereceived = SPDR;                  
  received = true;                       
}

3. Tiếp theo trong void loop()

  • Đọc giá trị tương tự từ Slave Arduino POT được gắn vào chân A0.
int pot = analogRead(A0);
  • Chuyển đổi giá trị đó theo byte thành 0 thành 255.
Slavesend = map(pot,0,1023,0,255);
  • Bước quan trọng tiếp theo là gửi giá trị được chuyển đổi đến Master STM32F10C8, vì vậy hãy đặt giá trị vào thanh ghi SPDR. Thanh ghi SPDR được sử dụng để gửi và nhận các giá trị.
SPDR = Slavesend;
  • Sau đó hiển thị giá trị nhận được ( SlaveReceive ) từ Master STM32F103C8 trên LCD với delay 500 micro giây và sau đó liên tục nhận và hiển thị các giá trị đó.
 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);

Bằng cách  xoay biến trở ở một bên, bạn có thể thấy các giá trị khác nhau trên LCD ở một mặt khác:

Vì vậy, đây là  cách giao tiếp SPI diễn ra trong STM32 . Bây giờ bạn có thể giao tiếp bất kỳ cảm biến SPI nào với board STM32.

Code hóa hoàn chỉnh cho Master STM32 và Slave Arduino được đưa ra dưới đây với một video trình diễn

CODE:
Master STM32 SPI

//SPI Master code for STM32F103C8
//SPI Communication between STM32 & Arduino
//Circuit Digest

#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

//SPI Slave Code for Arduino
//SPI Communication between STM32F103C8 & Arduino
//Circuit Digest

#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();
}
VIDEO DEMO:
https://youtu.be/-E_MWULHUMQ

 

 

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *