Tôi đã cố gắng để SPI1 trên STM32F103C8 ( bảng Blue Pill ) hoạt động chính xác trong một thời gian. Khi tôi mới bắt đầu học ARM, tôi chỉ đơn giản là cố gắng chuyển dữ liệu sang thanh ghi thay đổi 74HC595 và chốt nó để làm sáng lên một byte đèn LED. Tôi không đọc lại bất kỳ dữ liệu nào, vì vậy tôi chỉ có các dòng MOSI, SCK và SS.
Lúc đầu, tôi không nhận được bất cứ điều gì, nhưng đọc một số ví dụ trực tuyến tôi có thể khắc phục những sự cố đầu tiên này để truyền thông diễn ra (tôi cần đặt chính xác các chân GPIOA và đặt SS phần mềm).
Vấn đề chính bây giờ là nếu tôi không bao gồm các điện trở kéo lên trên tất cả các dòng (MOSI, SCK và SS) thì vi điều khiển không xuất bất cứ thứ gì trên bất kỳ dòng nào (được kiểm tra với một phạm vi). Trên hết, sau khi thêm các điện trở kéo lên, thời gian tăng trên các xung rất chậm nên tôi không thể sử dụng tần số quá cao (với điện trở kéo lên 10 kΩ Tôi bị giới hạn ở khoảng 250 kHz SCK và chuyển đổi đến 330 Ω khoảng 4 MHz). Tôi đang làm việc trên một chiếc bánh mì, nhưng ngay cả khi đó với hệ thống dây điện và bộ điều khiển lộn xộn, tôi có thể có được SPI 4 MHz hoạt động mà không gặp vấn đề gì nếu không có thêm điện trở và dạng sóng sạch hơn.
Dưới đây là hai hình ảnh (xin lỗi cho trạng thái sâu thẳm của màn hình phạm vi của tôi) truyền byte 0b01110010 ở xung nhịp 250 kHz. Dấu vết trên cùng là SCK và dưới cùng là MOSI. Bức ảnh đầu tiên có điện trở kéo lên 10 kΩ và bức thứ hai có điện trở kéo 330 330 giúp dạng sóng đẹp hơn nhiều (nhưng không cần thiết).
Tôi đánh giá cao một số trợ giúp để tìm hiểu những gì đang xảy ra.
Các phần có liên quan trong mã của tôi là:
#define SS_LOW GPIOA->BSRR |= 1 << 4 + 16;
#define SS_HIGH GPIOA->BSRR |= 1 << 4;
// SPI GPIO configuration
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
GPIOA->CRL |= 0b0011 << 4 * 4; // Set pin A4 as PP out 50mHz for SS
GPIOA->CRL |= 0b1011 << 5 * 4; // Set pin A5 AltFunc PP out 50mHz for SCK
GPIOA->CRL |= 0b1011 << 7 * 4; // Set pin A7 AltFunc PP out 50mHz for MOSI
SS_HIGH;
// SPI1 configuration
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // Enable SPI1 clock
SPI1->CR1 |= SPI_CR1_SSM; // Software SS
SPI1->CR1 |= SPI_CR1_SSI;
SPI1->CR1 |= SPI_CR1_BR_0; // Set prescaler
SPI1->CR1 |= SPI_CR1_BR_1;
SPI1->CR1 |= SPI_CR1_BR_2;
SPI1->CR1 |= SPI_CR1_MSTR; // Master mode
SPI1->CR1 |= SPI_CR1_SPE; // Enable SPI
// Transmit byte
SS_LOW;
SPI1->DR = 0b01110010;
while(!(SPI1->SR & SPI_SR_TXE));
while(SPI1->SR & SPI_SR_BSY);
SS_HIGH;