- Giao thức truyền thông SPI là gì?
- Giao thức SPI hoạt động như thế nào?
- Sự khác biệt giữa giao tiếp I2C và SPI
- SPI với PIC16F877A sử dụng Trình biên dịch XC8:
- Giải thích Tệp Tiêu đề SPI:
- Chương trình chính Giải thích:
- Mô phỏng PIC với trình gỡ lỗi SPI:
Bộ vi điều khiển PIC là một nền tảng mạnh mẽ được cung cấp bởi vi mạch cho các dự án nhúng; Bản chất linh hoạt của nó đã cho phép nó tìm ra nhiều cách vào nhiều ứng dụng và vẫn chưa phát triển nhiều. Nếu bạn đã theo dõi các hướng dẫn về PIC của chúng tôi thì bạn sẽ nhận thấy rằng chúng tôi đã bao gồm một loạt các hướng dẫn về vi điều khiển PIC bắt đầu từ những điều cơ bản. Trong cùng một quy trình, chúng tôi đang tiến hành tìm hiểu các giao thức truyền thông có sẵn với PIC và cách sử dụng chúng. Chúng tôi đã bao gồm I2C với Vi điều khiển PIC.
Trong hệ thống rộng lớn của các ứng dụng nhúng, không có vi điều khiển nào có thể tự thực hiện tất cả các hoạt động. Tại một số thời điểm nó phải giao tiếp với các thiết bị khác để chia sẻ thông tin, có nhiều loại giao thức truyền thông khác nhau để chia sẻ những thông tin này, nhưng được sử dụng nhiều nhất là USART, IIC, SPI và CAN. Mỗi giao thức truyền thông đều có ưu và nhược điểm riêng. Bây giờ chúng ta hãy tập trung vào Giao thức SPI vì đó là những gì chúng ta sẽ tìm hiểu trong hướng dẫn này.
Giao thức truyền thông SPI là gì?
Thuật ngữ SPI là viết tắt của “ Giao diện ngoại vi nối tiếp ”. Nó là một giao thức truyền thông phổ biến được sử dụng để gửi dữ liệu giữa hai bộ vi điều khiển hoặc để đọc / ghi dữ liệu từ một bộ cảm biến đến một bộ vi điều khiển. Nó cũng được sử dụng để giao tiếp với thẻ SD, thanh ghi dịch chuyển, bộ điều khiển màn hình và hơn thế nữa.
Giao thức SPI hoạt động như thế nào?
Giao tiếp SPI là giao tiếp đồng bộ, có nghĩa là nó hoạt động với sự trợ giúp của tín hiệu đồng hồ được chia sẻ giữa hai thiết bị đang trao đổi dữ liệu. Ngoài ra nó còn là giao tiếp song công vì nó có thể gửi và nhận dữ liệu bằng cách sử dụng một bus riêng biệt. Giao tiếp SPI yêu cầu 5 dây để hoạt động. Một mạch giao tiếp SPI đơn giản giữa chủ và tớ được hiển thị bên dưới
Năm dây cần thiết cho giao tiếp là SCK (Serial Clock), MOSI (Master Out Slave In), MISO (Master In Slave Out) và SS (Slave Select). Giao tiếp SPI luôn chỉ diễn ra giữa chủ và tớ. Một chủ có thể có nhiều nô lệ được kết nối với nó. Master chịu trách nhiệm tạo xung đồng hồ và nó được chia sẻ với tất cả các nô lệ. Ngoài ra, tất cả các giao tiếp chỉ có thể được bắt đầu bởi chủ.
Chân SCK (hay còn gọi là đồng hồ nối tiếp SCL) chia sẻ tín hiệu đồng hồ do chủ tạo ra với các nô lệ. Chân MOSI (hay còn gọi là SDA –Serial Data Out) được sử dụng để gửi dữ liệu từ cái chính đến bộ lưu trữ. Chân MISO (hay còn gọi là SDI - Serial Data In) được sử dụng để lấy dữ liệu từ bộ lưu trữ đến bản chính. Bạn cũng có thể theo dấu mũi tên trong hình trên để hiểu sự chuyển động của dữ liệu / tín hiệu. Cuối cùng, chân SS (hay còn gọi là CS –Chip select) được sử dụng khi có nhiều hơn một mô-đun phụ được kết nối với chính. Trong này có thể được sử dụng để chọn nô lệ cần thiết. Mạch mẫu trong đó nhiều hơn một phụ được kết nối với chủ để giao tiếp SPI được hiển thị trong mạch bên dưới.
Sự khác biệt giữa giao tiếp I2C và SPI
Chúng ta đã học giao tiếp I2C với PIC và vì vậy chúng ta phải quen thuộc với cách hoạt động của I2C và nơi chúng ta có thể sử dụng chúng như I2C có thể được sử dụng để giao tiếp mô-đun RTC. Nhưng bây giờ, tại sao chúng ta cần giao thức SPI khi chúng ta đã có I2C. Lý do là cả truyền thông I2C và SPI đều có lợi thế theo cách riêng của nó và do đó là ứng dụng cụ thể.
Ở một mức độ nào đó, giao tiếp I2C có thể được coi là có một số lợi thế so với giao tiếp SPI vì I2C sử dụng ít chân hơn và nó rất tiện dụng khi có một số lượng lớn nô lệ được kết nối với bus. Nhưng hạn chế của I2C là nó có cùng một bus để gửi và nhận dữ liệu và do đó nó tương đối chậm. Vì vậy, nó hoàn toàn dựa trên ứng dụng để quyết định giữa giao thức SPI và I2C cho dự án của bạn.
SPI với PIC16F877A sử dụng Trình biên dịch XC8:
Cơ bản là đủ rồi, bây giờ chúng ta hãy tìm hiểu cách sử dụng giao tiếp SPI trên vi điều khiển PIC16F877A bằng trình biên dịch MPLABX IDE và XC8. Trước khi chúng tôi bắt đầu, hãy nói rõ rằng hướng dẫn này chỉ nói về SPI trong PIC16F877a sử dụng trình biên dịch XC8, quy trình sẽ giống như vậy đối với các bộ vi điều khiển khác nhưng có thể cần phải thay đổi một chút. Cũng nên nhớ rằng đối với các bộ vi điều khiển nâng cao như dòng PIC18F, bản thân trình biên dịch có thể có một số thư viện được tích hợp sẵn để sử dụng các tính năng SPI, nhưng đối với PIC16F877A thì không có thứ gì giống như vậy tồn tại vì vậy chúng ta hãy tự xây dựng một thư viện. Thư viện được giải thích ở đây sẽ được cung cấp dưới dạng tệp tiêu đề để tải xuống ở phía dưới có thể được sử dụng cho PIC16F877A để giao tiếp với các thiết bị SPI khác.
Trong hướng dẫn này, chúng ta sẽ viết một chương trình nhỏ sử dụng giao tiếp SPI để ghi và đọc dữ liệu từ bus SPI. Sau đó, chúng tôi sẽ xác minh điều tương tự bằng cách sử dụng mô phỏng Proteus. Tất cả mã liên quan đến thanh ghi SPI sẽ được tạo bên trong tệp tiêu đề có tên PIC16f877a_SPI.h. Bằng cách này, chúng tôi có thể sử dụng tệp tiêu đề này trong tất cả các dự án sắp tới của chúng tôi trong đó yêu cầu giao tiếp SPI. Và bên trong chương trình chính, chúng ta sẽ chỉ sử dụng các hàm từ tệp tiêu đề. Mã hoàn chỉnh cùng với tệp tiêu đề có thể được tải xuống từ đây.
Giải thích Tệp Tiêu đề SPI:
Bên trong tệp tiêu đề, chúng ta phải khởi tạo giao tiếp SPI cho PIC16F877a. Luôn luôn là nơi tốt nhất để bắt đầu là biểu dữ liệu PIC16F877A. Các thanh ghi điều khiển giao tiếp SPI cho PIC16F8777a là SSPSTAT và SSPCON Register. Bạn có thể tìm hiểu về chúng ở trang 74 và 75 của biểu dữ liệu.
Có nhiều tùy chọn tham số phải được chọn trong khi khởi tạo giao tiếp SPI. Tùy chọn thường được sử dụng nhất là tần số đồng hồ sẽ được đặt thành Fosc / 4 và sẽ được thực hiện ở giữa và đồng hồ sẽ được đặt ở mức thấp ở trạng thái lý tưởng. Vì vậy, chúng tôi cũng đang sử dụng cùng một cấu hình cho tệp tiêu đề của mình, bạn có thể dễ dàng thay đổi chúng bằng cách thay đổi các bit tương ứng.
SPI_Initialize_Master ()
Chức năng Master khởi tạo SPI được sử dụng để bắt đầu giao tiếp SPI với tư cách chính. Bên trong chức năng này, chúng tôi đặt các chân tương ứng RC5 và RC3 làm chân đầu ra. Sau đó, chúng tôi cấu hình SSPTAT và đăng ký SSPCON để bật giao tiếp SPI
void SPI_Initialize_Master () { TRISC5 = 0; // SSPSTAT = 0b00000000; // trang 74/234 SSPCON = 0b00100000; // trang 75/234 TRISC3 = 0; // Set as đầu ra cho chế độ nô lệ }
SPI_Initialize_Slave ()
Chức năng này được sử dụng để đặt bộ vi điều khiển hoạt động ở chế độ phụ cho giao tiếp SPI. Trong chế độ phụ, chân RC5 phải được đặt làm đầu ra và chân RC3 phải được đặt làm đầu vào. SSPSTAT và SSPCON được đặt theo cùng một cách cho cả máy chủ và máy chủ.
void SPI_Initialize_Slave () { TRISC5 = 0; // Chân SDO nên được khai báo là đầu ra SSPSTAT = 0b00000000; // trang 74/234 SSPCON = 0b00100000; // trang 75/234 TRISC3 = 1; // Đặt làm đầu ra cho chế độ chính }
SPI_Write (ký tự đến)
Hàm SPI Write được sử dụng để ghi dữ liệu vào bus SPI. Nó lấy thông tin từ người dùng thông qua biến đến và sau đó sử dụng nó để chuyển đến thanh ghi Buffer. SSPBUF sẽ bị xóa trong xung Clock liên tiếp và dữ liệu sẽ được gửi vào bus từng bit.
void SPI_Write (char incoming) { SSPBUF = incoming; // Ghi dữ liệu do người dùng cung cấp vào bộ đệm }
SPI_Ready2Read ()
Chức năng SPI ready to Read được sử dụng để kiểm tra xem dữ liệu trong bus SPI có được nhận hoàn toàn hay không và có thể đọc được không. Thanh ghi SSPSTAT có một bit được gọi là BF sẽ được đặt khi dữ liệu đã được nhận hoàn toàn, vì vậy chúng tôi kiểm tra xem bit này đã được đặt chưa nếu chưa được đặt thì chúng tôi phải đợi cho đến khi nó được thiết lập để đọc bất kỳ thứ gì từ bus SPI.
unsigned SPI_Ready2Read () { if (SSPSTAT & 0b00000001) trả về 1; khác trả về 0; }
SPI_Read ()
SPI Read được sử dụng để đọc dữ liệu từ bus SPI vào vi điều khiển. Dữ liệu hiện diện trong bus SPI sẽ được lưu trữ trong SSPBUF, chúng ta phải đợi cho đến khi dữ liệu hoàn chỉnh được lưu trữ trong Buffer và sau đó chúng ta có thể đọc nó thành một biến. Chúng tôi kiểm tra bit BF của thanh ghi SSPSTAT trước khi đọc bộ đệm để đảm bảo quá trình nhận dữ liệu hoàn tất.
char SPI_Read () // Đọc dữ liệu nhận được { while (! SSPSTATbits.BF); // Giữ cho đến khi bit BF được thiết lập, để đảm bảo dữ liệu hoàn chỉnh được đọc return (SSPBUF); // trả về dữ liệu đã đọc }
Chương trình chính Giải thích:
Các hàm được giải thích trong phần trên sẽ nằm trong tệp tiêu đề và chúng có thể được gọi vào tệp c chính. Vì vậy, hãy viết một chương trình nhỏ để kiểm tra xem giao tiếp SPI có hoạt động hay không. Chúng tôi sẽ chỉ ghi một số dữ liệu vào bus SPI và sử dụng mô phỏng proteus để kiểm tra xem dữ liệu tương tự có đang được nhận trong trình gỡ lỗi SPI hay không.
Như mọi khi, hãy bắt đầu chương trình bằng cách thiết lập các bit cấu hình và sau đó, điều rất quan trọng là thêm tệp tiêu đề mà chúng tôi vừa giải thích vào chương trình như hình dưới đây
#include
Nếu bạn đã mở chương trình từ tệp zip được tải xuống ở trên thì theo mặc định, tệp tiêu đề sẽ có trong thư mục tệp tiêu đề của tệp dự án của bạn. Nếu không, bạn phải thêm tệp tiêu đề theo cách thủ công bên trong dự án của mình, khi đã thêm tệp dự án của bạn sẽ trông giống như bên dưới
Bên trong tệp chính, chúng ta phải khởi tạo PIC làm Master cho giao tiếp SPI và sau đó bên trong vòng lặp while vô hạn, chúng ta sẽ ghi ba giá trị hex ngẫu nhiên vào xe buýt SPI để kiểm tra xem chúng ta có nhận được giống nhau trong quá trình mô phỏng hay không.
void main () { SPI_Initialize_Master (); while (1) { SPI_Write (0X0A); __delay_ms (100); SPI_Write (0X0F); __delay_ms (100); SPI_Write (0X15); __delay_ms (100); } }
Lưu ý rằng các giá trị ngẫu nhiên được sử dụng trong chương trình là 0A, 0F và 15 và chúng là các giá trị hex nên chúng ta sẽ thấy như vậy trong quá trình mô phỏng. Vậy là mã đã xong, đây chỉ là một mẫu nhưng chúng ta có thể sử dụng cùng một phương pháp luận để giao tiếp với MCU khác hoặc với mô-đun cảm biến khác hoạt động trên giao thức SPI.
Mô phỏng PIC với trình gỡ lỗi SPI:
Bây giờ chương trình của chúng tôi đã sẵn sàng, chúng tôi có thể biên dịch nó và sau đó tiến hành mô phỏng. Proteus có một tính năng tiện dụng hay được gọi là trình gỡ lỗi SPI , có thể được sử dụng để giám sát dữ liệu qua bus SPI. Vì vậy, chúng tôi sử dụng tương tự và xây dựng một mạch như hình dưới đây.
Vì chỉ có một thiết bị SPI trong mô phỏng nên chúng tôi không sử dụng chân SS và khi không sử dụng nó nên được nối đất như hình trên. Chỉ cần tải tệp hex vào bộ vi điều khiển PIC16F877A và nhấp vào nút phát để mô phỏng chương trình của chúng tôi. Khi mô phỏng bắt đầu, bạn sẽ nhận được một cửa sổ bật lên hiển thị dữ liệu trong bus SPI như hình dưới đây
Hãy xem xét kỹ hơn dữ liệu đến và kiểm tra xem nó có giống với dữ liệu mà chúng tôi đã viết trong chương trình của mình hay không.
Dữ liệu được nhận theo đúng thứ tự mà chúng tôi đã viết trong chương trình của mình và dữ liệu tương tự được đánh dấu cho bạn. Bạn cũng có thể thử mô phỏng một chương trình để giao tiếp với hai vi điều khiển PIC bằng giao thức SPI. Bạn phải lập trình một PIC làm chủ và một PIC làm nô lệ. Tất cả các tệp tiêu đề bắt buộc cho mục đích này đã được cung cấp trong tệp tiêu đề.
Đây chỉ là một cái nhìn thoáng qua về những gì SPI có thể làm, nó cũng có thể đọc và ghi dữ liệu vào nhiều thiết bị. Chúng tôi sẽ trình bày nhiều hơn về SPI trong các hướng dẫn sắp tới của chúng tôi bằng cách kết nối các mô-đun khác nhau hoạt động với giao thức SPI.
Hy vọng bạn đã hiểu dự án và học được điều gì đó hữu ích từ nó. Nếu bạn có bất kỳ nghi ngờ nào, hãy đăng chúng trong phần bình luận bên dưới hoặc sử dụng diễn đàn để được trợ giúp kỹ thuật.
Hoàn thành Mã chính đã được cung cấp bên dưới; bạn có thể tải xuống tệp tiêu đề với tất cả mã từ đây