Arduino - Chuẩn giao tiếp truyền nhận dữ liệu SPI
Chương này chúng ta sẽ tìm hiểu về một chuẩn giao tiếp khá thông dụng
trong truyền nhận dữ liệu, đó là chuẩn giao tiếp truyền nhận SPI. Điểm
qua 1 số nội dung sẽ tìm hiểu ở chương này:
Giới thiệu về chuẩn SPI, lịch sử hình thành và nguyên lí hoạt động.
Một số ví dụ sử dụng SPI trong truyền, nhận dữ liệu như điều khiển
LED matrix và đọc giá trị nhiệt độ, áp suất, độ cao bằng cảm biến
BMP280 hiển thị giá trị lên màn hình OLED.
Giao thức SPI
Giới thiệu
Với tốc độ phát triển của công nghệ ngày nay thì việc truyền dữ liệu qua
các chuẩn truyền I2C, UART chưa đáp ứng được đối với các dự án cần
truyền dữ liệu với tốc độ cao, để đáp ứng điều đó hãng Motorola đã đề
xuất ra chuẩn truyền SPI.
SPI là chữ viết tắt của Serial Peripheral Interface, chuẩn giao tiếp nối
tiếp đồng bộ tốc độ cao do hãng Motorola đề xuất được sử dụng cho truyền
thông khoảng cách ngắn, chủ yếu là trong các hệ thống nhúng. Giao diện
được Motorola phát triển vào giữa những năm 1980 và đã trở thành tiêu
chuẩn trong thực tế. Các ứng dụng điển hình như Secure Digital cards
(các loại thẻ nhớ SD ví dụ: miniSD, microSD cards) và liquid crystal
displays (màn hình tinh thể lỏng).
Đôi khi SPI còn được gọi là chuẩn truyền thông "4 dây" vì nó có 4 đường
giao tiếp là SCK (Serial Clock), MISO (Master Input/Slave Output), MOSI
(Master Output/Slave Input) và SS(Slave Select).
SCK (Serial Clock): Là đường xung giữ nhịp cho chuẩn SPI, là
chân output từ master, do chuẩn SPI là giao tiếp đồng bộ nên phải
cần dùng một đường giữ nhịp. Đây là sự khác biệt giữa truyền thông
đồng bộ và truyền thông không đồng bộ như chuẩn giao tiếp UART. SCK
giúp chuẩn SPI có tốc độ truyền/nhận dữ liệu cao và ít xảy ra lỗi
trong quá trình truyền/nhận dữ liệu.MISO (Master Input/Slave Output): Với master thì MISO là chân
input và với slave là chân output, 2 chân MISO của master và slave
nối trực tiếp với nhau.MOSI (Master Output/Slave Input): Với chip master thì MOSI là
chân output và với chip slave là chân input, 2 đường MOSI của master
và slave nối trực tiếp với nhau.SS (Slave Select): Là chân chọn thiết bị slave cần giao tiếp,
trên thiết bị slave sẽ có một chân slave kết nối với chân SS của
master và trên thiết bị master sẽ có nhiều chân SS điều khiển thiết
bị slave. Chân SS trên các chip slave sẽ ở mức cao khi không giao
tiếp, nếu chip master kéo đường SS của một slave nào đó xuống mức
thấp thì master sẽ giao tiếp với slave đó.
Chuẩn truyền SPI sử dụng kiểu truyền thông master-slave, với một master
có thể điều khiển nhiều slave thông qua việc lựa chọn các đường SS
(Slave Select), muốn điều khiển slave nào thì chỉ cần chọn SS của slave
đó. Các thiết bị sử dụng chuẩn truyền SPI sẽ truyền dữ liệu song công
(duplex communication) là truyền và nhận dữ liệu cùng lúc, master có thể
gửi dữ liệu đến slave và nhận dữ liệu từ slave cùng một thời điểm.
SPI, ưu và nhược điểm
Ưu điểm
Chuẩn truyền thông nối tiếp SPI có tốc độ truyền dữ liệu và ít lỗi
phát sinh trong quá trình truyền/nhận dữ liệu hơn các chuẩn truyền
nối tiếp khác.Hỗ trợ truyền thông song công (duplex communication) là dữ liệu có
thể truyền và nhận cùng một thời điểm.Có giao diện phần cứng khá đơn giản.
Không giới hạn tốc độ xung clock, cho phép truyền dữ liệu với tốc độ
cao.Hỗ trợ điều khiển nhiều slave.
Nhược điểm:
Tốn năng lượng.
Chỉ hỗ trợ một master.
Không có giao thức kiểm tra lỗi.
SPI đòi hỏi các slave có một đường SS (slave Select) riêng biệt, vì
thế nếu cần nhiều slave thì sẽ cần nhiều đường SS sẽ làm tốn chân
của chip master và nhiều dây sẽ gây rối.
Nguyên lý hoạt động
Thiết bị master và slave mỗi thiết bị có thanh ghi dữ liệu 8 bit. Khi
đường SCK của master tạo ra một xung nhịp thì một bit trong thanh ghi dữ
liệu của master truyền qua slave trên đường MOSI, và ngược lại một bit
dữ liệu từ slave sẽ truyền qua master trên đường MISO, do 2 dữ liệu được
truyền cùng một lúc trên một nhịp xung nên quá trình truyền dữ liệu này
gọi là truyền dữ liệu "song công".
SPI, các ví dụ mẫu
Hiển thị chữ trên LED matrix
Yêu cầu
Đây là một ví dụ cơ bản của chuẩn giao tiếp nối tiếp SPI. Vi điều khiển
giao tiếp với module LED matrix để hiển thị chữ.
LED matrix 8x8 MAX7219 dùng IC 7219 để điều LED matrix 1 cách dễ dàng và
đơn giản hơn, dùng 3 dây dữ liệu để truyền dữ liệu và 2 dây nguồn.
Module 8x8 LED matrix sử dụng khá đơn giản, có thể điều chỉnh độ sáng
của LED ngay trên phần mềm.
Linh kiện cần dùng
Board Arduino Uno
Module LED matrix MAX7219
Dây kết nối
Kết nối Arduino Uno với LED matrix
Board Arduino Uno sẽ là master và LED matrix sẽ là slave.
Master sẽ gửi dữ liệu ra từ chân D11 (MOSI) và slave sẽ nhận dữ liệu
bằng chân DIN.Chân D13 (SCK) của master sẽ tạo xung clock qua chân CLK của slave
mỗi nhịp sẽ gửi 1bit dữ liệu qua slave.Chân D10 (SS) của master nối với chân CS của slave khi muốn giao
tiếp với slave thì chân D10 (SS) của master sẽ kéo chân CS của slave
xuống mức thấp.
LED matrix | Board Arduino Uno |
---|---|
VCC | 5V |
GND | GND |
DIN | D11 (MOSI ) |
CLK | D13 (SCK) |
CS | D10 (SS) |
Bảng kết nối LED matrix và board Arduino Uno
Thư viện cần dùng:
Với những thư viện không có sẵn trong trình biên dịch Arduino IDE thì
cần phải clone (dùng với git) hoặc Download về máy và add vào
chương trình. Các thư viện cần dùng cho ứng dụng được kiệt kê bên dưới:
Thư viện "SPI.h" là thư viện đã có sẵn trong trình biên dịch Arduino
IDE.Thư viện bitBangedSPI.
Thư viện MAX7219_Dot_Matrix.
Source code
#include <SPI.h>
#include <bitBangedSPI.h>
#include <MAX7219_Dot_Matrix.h>
MAX7219_Dot_Matrix display (chips, 10); // Chân D10 là chân SS của board Iotmaker Uno X
const byte chips = 1; // Số chip MAX7219 được sử dụng
const char message [] = "IOT MAKER VN"; // Nội dung được hiển thị
unsigned long lastMoved = 0;
unsigned long MOVE_INTERVAL = 40; // Thời gian chạy chữ đơn vị (ms)
int messageOffset;
void updateDisplay ()
{
// Hiển thị chữ của mảng message, bắt đầu từ pixel mesageOffset
display.sendSmooth (message, messageOffset);
// Mỗi thời gian hiển thị một pixel từ phải qua trái
if (messageOffset++ >= (int) (strlen (message) * 8))
messageOffset = -chips * 8;
}
void setup ()
{
display.begin (); // Khởi tạo hiển thị
}
void loop ()
{
// Nội dung được hiển thị lại sau khi chạy
if (millis() - lastMoved >= MOVE_INTERVAL) {
updateDisplay ();
lastMoved = millis();
}
}
Đọc dữ liệu từ cảm biến BMP280, hiển thị trên OLED
Yêu cầu
Ứng dụng này giúp chúng ta đọc dữ liệu từ cảm biến áp suất và hiển thị
giá trị lên màn hình OLED.
Module cảm biến áp suất BMP280
BPM280 là cảm biến nâng cấp thế hệ tiếp theo cho
BMP085/BMP180/BMP183. Với chi phí thấp, độ chính xác cao. Module có chức
năng đo áp suất khí quyển và nhiệt độ. Chúng ta cũng có thể sử dụng nó
như một module đo độ cao (sai số ± 1m) bởi mối liên hệ giữa áp suất và
độ cao.
Linh kiện cần dùng
Board Arduino Uno
Module cảm biến áp suất BPM280
Màn hình OLED
Dây kết nối
Kết nối :
Arduino sẽ là master và cảm biến BMP280 sẽ là slave, slave sẽ gửi dữ
liệu qua đường SDI.Mỗi nhịp xung clock từ chân SCK (D13) của master tạo ra sẽ ứng với
1bit dữ liệu được truyền.Chân D10 (SS) của master nối với chân CS của slave khi muốn giao
tiếp với slave thì chân D10 (SS) của master sẽ kéo chân CS của slave
xuống mức thấp.
BMP280 | Arduino Uno |
---|---|
VCC | 3.3V |
GND | GND |
SDI | D11 (MOSI ) |
SCK | D13 (SCK) |
CSE | D10 (SS) |
SDO | D12(MISO) |
Bảng đấu nối cảm biến BMP280 và board Arduino Uno
Kết nối board Arduino Uno với OLED
Xem chương I2C để hiểu hơn về giao tiếp Arduino giao tiếp với OLED,
chúng ta có thể cắm trực tiếp OLED vào header đã được thiết kế sẵn trên
board Arduino Uno hoặc kết nối theo hướng dẫn bên dưới.
OLED | Arduino Uno |
---|---|
VCC | 3.3V |
GND | GND |
SDA | SDA(hoặc A4) |
SCL | SCL(hoặc A5) |
Bảng đấu nối OLED với board Arduino Uno
Thư viện cần dùng:
Thư viện "SPI.h" và "Wire.h" là hai thư viện có sẵn trong Arduino
IDE.Thư viện Adafruit_SSD1306.h.
Thư viện Adafruit_GFX.h.
Thư viện Adafruit_Sensor.h.
Thư viện Adafruit_BMP280.h.
Source code
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS 10
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
// Chọn giao tiếp SPI (BMP280 có 2 chuẩn giao tiếp SPI và I2C)
Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
void setup()
{
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Lấy địa chỉ I2C của oled
display.clearDisplay(); // Lệnh xóa màn hình hiển thị
display.setTextColor(WHITE); // Chọn màu chữ
display.setTextSize(1); // Chọn kích thước chữ
display.setCursor(15, 15); // Chọn vị trí của chữ
Serial.println(F("BMP280 test"));
if (!bmp.begin()) { // In ra thông báo nếu kết nối thất bại
Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
while (1);
} else
Serial.println("BMP280 OK"); // Hiển thị "BMP280 OK" khi kết nối thành công
}
void loop()
{
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Temperature:");
display.print(bmp.readTemperature()); // Lấy giá trị nhiệt độ
display.print("*C");
// Hiển thị giá trị nhiệt độ trên serial monitor
Serial.print("Temperature:");
Serial.print(bmp.readTemperature()); // Lấy giá trị nhiệt độ
Serial.println("*C");
display.setCursor(0, 10);
display.print("Pressure:");
display.print(bmp.readPressure()); // Lấy giá trị áp suất
display.print("Pa");
// Hiển thị giá trị áp suất trên serial monitor
Serial.print("Pressure:");
Serial.print(bmp.readPressure()); // Lấy giá trị áp suất
Serial.println("Pa");
display.setCursor(0, 20);
display.print("h:");
display.print(bmp.readAltitude()); // Lấy giá trị độ cao
display.print("m");
// Hiển thị giá trị độ cao trên serial monitor
Serial.print("h:");
Serial.print(bmp.readAltitude()); // Lấy giá trị độ cao
Serial.println("m");
display.display();
delay(2000);
}
Tổng kết
Qua phần này, bạn đã tìm hiểu được những khái niệm quan trọng trong giao
tiếp SPI, các chân giao tiếp theo chuẩn SPI là SCK, MISO, MOSI, SS. Cách
chọn slave để giao tiếp của master và SPI hoạt động theo kiểu truyền
song công là như thế nào. Từ đó, chúng ta có thể dễ dàng xây dựng các
ứng dụng có hỗ trợ giao tiếp SPI.
Latest comments (0)