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
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(); }