Bài 12: Lập trình STM32 với giao thức SPI

Giao thức SPI

Lập trình STM32 sử dụng giao thức SPI sẽ giúp chúng ta hiểu được.

  • Nguyên lý truyền nhận của chuẩn SPI
  • Cách thiết lập giao tiếp SPI trên STM32 Cube MX
  • Lập trình với  giao thức SPI 

Bài số 12 trong serie Học lập trình STM32 từ A tới Z

Giao thức SPI là gì

Cơ bản về giao thức SPI

SPI Serial Peripheral Interface là một chuẩn truyền thông nối tiếp đồng bộ dùng để chuyền dữ liệu ở chế độ song công toàn phần (full duplex).

Giao thức SPI thường được sử dụng On Board hoặc các đường tín hiệu ngắn. Tốc độ của SPI khá cao thường phụ thuộc vào tốc độ xung truyền vào bộ SPI

Giao thức SPI là dao thức dạng Master –Slave trong đó Master giữ quyền điều khiển xung Clock và chọn Slave nào giao tiếp với mình.

Bus SPI bao gồm 4 đường tín hiệu:

  • MOSI (Master Out Slave In): Đường truyền tín hiệu từ Master đến Slave
  • MISO (Master In Slave Out): Đường truyền tín hiệu từ Slave đến Master
  • CLK (Serial Clock): Đường phát xung đồng hồ được điều khiển bởi Master
  • CS (Chip Select): Đường chọn chip giao tiếp với Master, được kéo xuống 0 khi được chọn
H1 9
Bài 12: Lập trình STM32 với giao thức SPI 21

Nguyên lý hoạt động của giao thức SPI

Nguyên lý hoạt động như sau:

  1. Khi muốn truyền nhận dữ liệu tới các Slave, đầu tiên Master kéo đường CS kết nối từ Master tới Slave đó xuống 0.
  2. Gửi xung Clock, tương ứng với mỗi Clock sẽ gửi DATA trên chân MOSI tại thời điểm Clock ở mức cao (hoặc thấp tùy người lập trình)
  3. Slave cũng có thể gửi ngược lại DATA tại chân MISO tới Master
  4. Sự truyền nhận dữ liệu là liên tục nên SPI thường có tốc độ rất cao
H2 2
Bài 12: Lập trình STM32 với giao thức SPI 22

Chế độ hoạt động của giao thức SPI

Có 4 chế độ hoạt động của SPI dựa trên hai Bit CPOLCPHA

CPOL: Clock Polarity xác định mức tín hiệu tại Clock lúc nhàn rồi (Idle), Nếu CPOL = 0, lúc không gửi dữ liệu (nhàn rỗi) Clock sẽ ở mức thấp CPOL = 1 sẽ ngược lại

CPHA: Phase Clock xác định quá trình truyền dữ liệu tại cạnh lên (CPHA = 0) hay cạnh xuống CPHA = 1

Mode 0:

  1. Mode 0: xảy ra khi Clock Polarity và Clock Phase là 0 (CPOL = 0 và CPHA = 0). Trong Mode 0, truyền dữ liệu xảy ra trong khi cạnh lên của xung đồng hồ.
  2. Mode 1: xảy ra khi Clock Polarity là 0 và Clock Phase là 1 (CPOL = 0 và CPHA = 1). Trong mode 1, truyền dữ liệu xảy ra trong khi cạnh xuống của xung đồng hồ.
  3. Mode 2:  xảy ra khi Clock Polarity là 1 và Clock Phase là 0 (CPOL = 1 và CPHA = 0). Trong mode 2, truyền dữ liệu xảy ra trong khi cạnh lên của xung đồng hồ.
  4. Mode 3:  xảy ra khi Clock Polarity là 1 và Clock Phase là 1 (CPOL = 1 và CPHA = 1). Trong mode 3, truyền dữ liệu xảy ra trong khi cạnh lên của xung đồng hồ.
H3 2
Bài 12: Lập trình STM32 với giao thức SPI 23

Các kiểu cấu hình  giao thức SPI

Có 2 loại cấu hình SPI

  • Cấu hình Master và các Slave độc ​​lập (Independent Slave Configuration)
  • Cấu hình Daisy Chain (Daisy Chain Configuration).

Trong cấu hình Master và các Slave độc ​​lập, Master đã dành riêng các đường Slave Select cho tất cả các Slave và mỗi Slave có thể được chọn riêng lẻ. Tất cả tín hiệu đồng hồ của các Slave được kết nối với chung với SCK của Master.

H4 8
Bài 12: Lập trình STM32 với giao thức SPI 24

Trong cấu hình Daisy Chain, chỉ có một đường Slave Select được kết nối với tất cả các Slave. MOSI của Master được kết nối với MOSI của Slave 1. MISO của Slave 1 được kết nối với MOSI của Slave 2 và v.v.. MISO của Slave cuối cùng được kết nối với MISO của Master.

H5 2
Bài 12: Lập trình STM32 với giao thức SPI 25

Tuy nhiên, cầu hình Daisy Chain không phải lúc nào cũng áp dụng được cho tất cả các thiết bị Slave. Do đó, ta cần phải tham khảo datasheet trước khi tiến hành kết nối.

Cấu hình STM32 SPI trong Cube MX

Trong bài này chúng ta sẽ sử dụng Bộ SPI1 ở chế độ Master và SPI2 ở chế độ Slave. Truyền nhận ở chế độ ngắt và DMA

Trong CubeMX cấu hình như sau. SYS debug: Serial Wire

SPI1Chế độ Full Duplex, Hard ware NSS: Disable, chân chọn chip ta sẽ sử dụng chân GPIO khác để dễ dàng điều khiển nếu sử dụng nhiều Slave

Parameter cấu hình như trong hình

H6 9
Bài 12: Lập trình STM32 với giao thức SPI 26

SPI2 chế độ Full-Duplex Slave, Hard ware NSS: Enable Bật chân chọn chip cho SPI2

Parameter cấu hình giống SPI1

H7 11
Bài 12: Lập trình STM32 với giao thức SPI 27

Chọn thêm chân PA4 làm chân Chip Select cho SPI1

H8 9
Bài 12: Lập trình STM32 với giao thức SPI 28

Bật ngắt cho SPI1 và SPI2

H9 10
Bài 12: Lập trình STM32 với giao thức SPI 29

Chọn toolchain đặt tên và Gen code

H10 8
Bài 12: Lập trình STM32 với giao thức SPI 30

Lập trình giao thức SPI trong Keil C

Trong Keil C thêm các biến u8_SPI1_TxBuff để làm bộ đệm truyền SPI1, u8_SPI2_RxBuff làm bộ đệm nhận từ SPI2, biến Count để xem sự thay đổi của mảng truyền đi

H11 8
Bài 12: Lập trình STM32 với giao thức SPI 31

Tìm hàm HAL_SPI_RxCpltCallback copy và dán vào trên hàm main(), bên trong chúng ta kiểm tra có phải ngắt SPI2 không, sau đó bật ngắt nhận RX để nhận thêm chuỗi

H12 7
Bài 12: Lập trình STM32 với giao thức SPI 32

Trước while(1) chúng ta truyền dữ liệu đầu tiên lên SPI1 bằng hàm:

HAL_SPI_Transmit(&hspi1,u8_SPI1_TxBuff,sizeofBuff,100);

, sau đó bận nhận SPI2 bằng ngắt bằng hàm:

HAL_SPI_Receive_IT(&hspi2, u8_SPI2_RxBuff,sizeofBuff);

Trong While (1) copy dữ liệu vào SPI1_TxBuff

Cho chân CS xuống 0 để chọn chip, gửi dữ liệu, cho chân CS về 1 để kết thúc quá trình gửi.

Tăng biến Count và delay 1s

H13 5
Bài 12: Lập trình STM32 với giao thức SPI 33

Nhấn Build và nạp chương trình. Kết nối phần cứng như sau:

Các chân MOSI MISO CLK nối với nhau, chân CS của SPI1 nối với chân NSS của SPI2

H14 5
Bài 12: Lập trình STM32 với giao thức SPI 34

Vào chế độ debug, chuột phải vào 2 Buffer truyền và nhận, chọn Add to watch 1

H15 3
Bài 12: Lập trình STM32 với giao thức SPI 35

Nhấn Run và xem kết quả

H16 3
Bài 12: Lập trình STM32 với giao thức SPI 36

Giá trị truyền và nhận đã giống nhau

Nhận dữ liệu bằng DMA

Trong SPI2 ta chuyển sang tab DMA,  nhấn Add

DMA Request là SPI2_RX, Mode là Circular (ta chỉ cần gọi hàm nhận DMA 1 lần , không cần phải gọi lại trong ngắt )

Data Width là Byte

H17 3
Bài 12: Lập trình STM32 với giao thức SPI 37

Trong Keil C comment hoặc xóa phần xử lý ngắt (không dùng tới hoặc dùng để làm tác vụ nào đó khi truyền xong)

Phần trước While (1) thay hàm Recive_IT bằng Recive_DMA

H18 2
Bài 12: Lập trình STM32 với giao thức SPI 38

Nhấn Build và nạp chương trình, chạy debug để xem kết quá

H20 1
Bài 12: Lập trình STM32 với giao thức SPI 39

Kết luận

Giao thức SPI là một trong những giao thức cơ bản và phổ biến nhất trong lập trình vi điều khiển. Với SPI bạn có thể sử dụng để giao tiếp với nhiều loại device khác nhau như: TFT LCD, RFID, Camera ….

Giao thức SPI có thể được bắt gặp tại bất cứ một sản phẩm nhúng nào, hãy rèn luyện và làm chủ giao thức này nhé.

5 thoughts on “Bài 12: Lập trình STM32 với giao thức SPI

  1. Lâm says:

    Em làm theo không biết sao chỉ có các ký tự từ 0 đến 12 là bên truyền và nhận giống nhau, còn từ 13 đến 19 thì khác nhau?

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 *