Я пытался заставить SPI1 на STM32F103C8 ( Blue Pill Board) работать правильно в течение некоторого времени. Поскольку я только начинаю изучать ARM, я просто пытаюсь сместить данные в регистр сдвига 74HC595 и зафиксировать их, чтобы загорелся байт светодиодов. Я не читаю никаких данных, поэтому у меня есть только линии MOSI, SCK и SS.
Сначала я ничего не получал, но, читая некоторые онлайн-примеры, я мог решить эти первые проблемы, чтобы начать общение (мне нужно было правильно установить контакты GPIOA и установить программное обеспечение SS).
Основная проблема сейчас заключается в том, что, если я не включаю подтягивающие резисторы на всех линиях (MOSI, SCK и SS), микроконтроллер ничего не выводит ни на одну линию (проверяется с помощью области). Кроме того, после добавления подтягивающих резисторов время нарастания импульсов очень медленное, поэтому я не могу использовать слишком высокую частоту (с подтягивающими резисторами 10 кОм я ограничен до 250 кГц SCK, и переключение до 330 Ом (около 4 МГц). Я работаю над макетом, но даже тогда с AVR и запутанной проводкой я мог получить SPI на 4 МГц, работающий без проблем без каких-либо добавленных резисторов, и формы сигнала были более чистыми.
Вот две картинки (извините за плачевное состояние экрана моего прицела), передающих байт 0b01110010 с тактовой частотой 250 кГц. Верхний след - SCK, а нижний - MOSI. Первое изображение с подтягивающими резисторами 10 кОм, а второе с подтягивающими резисторами 330 Ом, которые делают сигналы намного приятнее (но они не нужны).
Буду признателен за помощь, чтобы выяснить, что происходит.
Соответствующие части моего кода:
#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;
Ответы:
Вы должны сбросить значение выводов, которые вы меняете, прежде чем устанавливать биты.
Значение сброса GPIOA_CRL составляет 0x4444 4444. Таким образом, каждый вывод инициализируется с 0b0100, если вы делаете | = 0b0011, вы получаете 0b0111, который является выходом с открытым стоком. То же самое с 0b1011 становится 0b1111, и это альтернативная функция открытого стока.
Так что вам нужно сделать что-то вроде этого:
источник