STM32F103C8T6 Максимальная выходная скорость ввода-вывода

Согласно техническому описанию STM32F103C8T6, его контакты GPIO имеют аппаратное ограничение скорости 50 МГц. Мне нужно добиться скорости выше 10 МГц, но даже с ассемблерными кодами я получаю только 7,99 МГц.

Он работает на максимальной рекомендованной частоте 72 МГц (8 МГц Crystal + PLL).

Может ли кто-нибудь направить меня? Пожалуйста, проверьте следующий цикл языка ассемблера, который я использую для переключения контактов GPIO.

 asm(".equ GPIOB_ODR, 0x4001080C");
 asm("ldr r6, = GPIOB_ODR");

 asm("loop:");
 asm("mov r1, #0xFFFFFFFF");
 asm("strh r1, [r6]");
 asm("mov r1, #0x00000000");
 asm("strh r1, [r6]");
 asm("b loop");
Вы должны использовать таймер.
Даже если каждая из этих инструкций занимает один цикл, вы получите только 12 МГц. Чего вы пытаетесь добиться этим? Вы просто хотите создать прямоугольную волну? Если это так, вам нужно использовать ШИМ. Используя этот метод, ваш процессор будет просто генератором прямоугольных импульсов!
Не могли бы вы объяснить причину вышеуказанного поведения? Если приведенный выше код выполняется на частоте 72 МГц, выходная частота GPIO должна быть намного выше, верно?
Я не пытаюсь генерировать прямоугольную волну... Мне нужно управлять светодиодными дисплеями на более высоких частотах. Поэтому я просто тестировал максимальную скорость gpio.
Представьте, если бы каждая инструкция занимала один цикл (чего они не будут делать). Это 13,9 нс на инструкцию. Шесть инструкций займут 83,3 нс, что даст вам 12 МГц. Теперь посмотрите, сколько циклов на самом деле занимает каждая из этих инструкций, и посчитайте.
Так что теперь у меня есть еще одно сомнение, в даташите написано, что максимальная скорость GPIO составляет 50 МГц, . Как я могу этого добиться?
Первый вопрос, что именно вы хотите сделать с этим GPIO?
Вы не можете добиться этого, используя GPIO и переключая его в программном обеспечении. Кроме того, я думаю, это связано с тем, как быстро переключается контакт и, следовательно, насколько сильно это влияет на ЭМС.

Ответы (2)

У вас есть несколько лучших вариантов управления контактами GPIO:

  • Таймеры. В этой части у вас есть семь таймеров, большинство из которых можно настроить для установки/сброса/переключения контактов при определенных событиях (таких как сравнение совпадений и переполнение).

  • прямой доступ к памяти. Настройте передачу DMA в регистр установки/сброса битов GPIO, и вы сможете переключать биты на скорости шины. Или вы можете подключить его к таймеру, чтобы установить биты с любой скоростью, которую вы хотите.

  • Творческое использование других периферийных устройств. USART и SPI/I2S кажутся особенно вероятными кандидатами.

Ваш метод:

:loop
MOV R1, #0xFFFFFFFF  ; 1 cycle
STRH R1, [R6]        ; 2 cycles
MOV R1, #0x00000000  ; 1 cycle
STRH R1, [R6]        ; 2 cycles
b loop               ; 3 cycles

Самое быстрое ядро ​​может записывать регистры:

MOV R3, #0xFFFFFFFF
MOV R4, #0x00000000
:loop
STRH R3, [R6]
STRH R4, [R6]
b loop

Примечание. GPIO — это APB2, поэтому шина 36 МГц. Вы никогда не можете превышать 36 МГц.

Однако таймер может генерировать вывод на sysclk/2. (часто 72/2 МГц)

Чтобы получить 10 МГц на выходе, вам нужно будет тактировать ядро ​​с частотой, кратной 10, с помощью PLL, поскольку вы не можете разделить тактовую частоту на 7,2 на таймерах.

Максимальное число в таблице данных Fmax(IO)out50 МГц является аппаратным ограничением. Аппаратное обеспечение GPIO не может достичь достаточно быстрого наклона, чтобы подняться выше.
Можно настроить скорость нарастания выходов, например, не нужно будет мигать светодиодом с крутизной 10 нс. Но надо бы для высокой скорости внешнюю память.

Большое спасибо за предложение. С этим я могу достичь 11,9 МГц. У меня есть одно сомнение. В таблице данных я видел, что максимальная выходная частота контактов GPIO составляет 50 МГц. Если это недостижимо, то в чем его польза?
@LigoGeorge Фактическое аппаратное обеспечение привода ограничено 50 МГц. (я добавил это, чтобы ответить)