SPI trên STM32 sẽ không hoạt động nếu không có điện trở pullup và thậm chí sau đó hoạt động kém


8

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.

Điện trở kéo lên 10 kΩ và đồng hồ 250 kHz

Điện trở kéo lên 330 and và 250 kHz làm cho dạng sóng đẹp hơn rất nhiều

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;

Thiết lập của bạn là gì? Làm thế nào là dây của bạn được kết nối? Bạn đang sử dụng một bảng tùy chỉnh hoặc bảng bánh mì?
Tarick Welling

Tôi đang sử dụng một chiếc bánh mì. 74hc595 được cấp nguồn từ 3,3V của bảng thuốc màu xanh (chính xác là: revspace.nl/File:Bluepill.jpg ). Các dây duy nhất đi từ và đến thanh ghi thay đổi là MOSI, SCK và SS. Tôi khẳng định hệ thống dây điện là chính xác, tôi đã kiểm tra nó nhiều lần (và một lần nữa trước khi trả lời bạn).
jjpprr

Câu trả lời:


12

Bạn nên đặt lại giá trị của các chân bạn đang thay đổi trước khi thiết lập các bit.

Giá trị đặt lại của GPIOA_CRL là 0x4444 4444. Vì vậy, mỗi pin được khởi tạo với 0b0100, nếu bạn thực hiện | = 0b0011, bạn kết thúc với 0b0111 là đầu ra cống mở. Tương tự với 0b1011 trở thành 0b1111 và đó là một chức năng thay thế mở cống.

Vì vậy, bạn cần phải làm một cái gì đó như thế này:

// Reset pin configuration
GPIOA->CRL &= ~(0b1111 << 4 * 4);  // Reset Pin A4
GPIOA->CRL &= ~(0b1111 << 5 * 4);  // Reset Pin A5
GPIOA->CRL &= ~(0b1111 << 7 * 4);  // Reset Pin A7
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

Đây chính là nó!! Cảm ơn bạn rất nhiều, tôi biết nó sẽ là một cái gì đó rất đơn giản. Đáng lẽ nên đọc dòng đầu tiên trên GPIOA_CRL của biểu dữ liệu, tôi chỉ giả sử giá trị đặt lại là tất cả các số không. Bây giờ nó hoạt động một sự quyến rũ.
jjpprr

@jjpprr cũng phải mất một thời gian tôi mới nhận ra :-) Vui vì tôi có thể giúp. Nếu bạn định sử dụng I²C trên F103, hãy sẵn sàng cho một chuyến đi khó khăn, tôi nhớ nó thật kinh khủng.
Arsenal

: O sẽ tính đến điều đó, sau khi bật USART và chạy, đến lượt I2C. Cảm ơn cho những người đứng đầu lên.
jjpprr

Điều nổi bật nhất là nơi mà các ngắt tôi đang nhận mà không có bất kỳ nguồn ngắt nào làm hỏng máy trạng thái của tôi. Cuối cùng, tôi đã tìm một cách tiếp cận hoàn toàn không sử dụng các ngắt I²C (nhưng ngắt DMA cho kết thúc truyền) và chỉ thăm dò các bit I²C để bắt đầu và xử lý, nhưng ứng dụng của tôi phải đợi I²C kết thúc , vì vậy dù sao tôi cũng không giành được thời gian với các ngắt.
Arsenal

Đây có phải chỉ với F103 hoặc các chip stm32 khác? Bởi vì kế hoạch của tôi là sử dụng nó chỉ để có được các IC stm32 nhưng sau đó chuyển sang F091 cho các dự án nhỏ và F446 cho những thứ đòi hỏi khắt khe hơn.
jjpprr
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.