#c #stm32 #microcontroller
#c #stm32 #микроконтроллер
Вопрос:
У кого-нибудь есть идеи, почему код не работает?
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
GPIOB->MODER amp;= ~(0x3u << 6u);
GPIOB->MODER |= (0x1u << 6u);
for (int i = 0; i < 1000; i ) {
GPIOB->ODR |= (0x1u << 0x3u);
}
Я использую плату STM (STM32L432KC), которая имеет встроенный светодиод, который называется выводом PB3 (порт 26), но после мигания ничего не происходит. На самом деле должен светиться светодиод. Правильно ли я использую регистр?
Комментарии:
1. вы не мигаете светодиодом с этим кодом, и у вас все равно нет задержки. в зависимости от конструкции вашей платы вам может потребоваться сделать вывод низким, чтобы включить светодиод. вы можете использовать регистр bsrr, а можете просто использовать GPIOB-> BSRR = 1<<3, а затем попробовать 1 << (3 16). и для мигания используйте эти два регистра с задержкой между ними
2. предполагая, что все магические числа, структура и определения верны в соответствии с руководством, тогда вы выполняете шаги, необходимые для правильной настройки порта, и это необходимый минимум.
3. Спасибо, но почему я должен выполнять вторую смену 1 << (3 16)?
4. один устанавливает бит 3, другой устанавливает бит 19, если вы посмотрите на регистр bsrr, вы увидите, что один бит делает этот вывод высоким, а другой — низким. один из двух высоких или низких значений включит светодиод, а другой выключит. итак, я полагаю, что вы хотите мигать, как в вашем вопросе заголовка, тогда вам нужно включаться и выключаться со скоростью человека.
5. если ваш код не включает светодиод, то, как уже упоминалось, попробуйте сделать вывод низким и посмотреть, загорится ли при этом светодиод. Вы смотрели на схему? Что это показывает?
Ответ №1:
Вы устанавливаете бит, ODR
но никогда не очищаете его, поэтому он не будет мигать, вам потребуется задержка между переходами включения / выключения, чтобы можно было видеть, как он мигает.
Рекомендуется записывать в BSRR
регистр вместо ODR
too, где это возможно, это позволяет избежать циклов чтения-изменения-записи.
Если этот код является вашим целым main()
, то вы можете заменить for (int i = 0; i < 1000; i )
его на a while(1)
, обычно вы не хотите возвращаться из main
встроенного контекста.
Комментарии:
1. Большое вам спасибо! но светодиод все еще не мигает. На самом деле он даже не светится. Правильно ли я использую адреса регистров? Светодиод соответствует указанному PB3. Может быть, светодиод только поврежден?
2. Это коммерчески доступная плата, что это за плата?
3. Это STM32 от ST NUCLEO-плата разработки Nucleo L432KC. На схеме PB3 показан как зеленый светодиод.
Ответ №2:
Эта последовательность неверна (я не проверял, используете ли вы правильный регистр RCC)
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
GPIOB->MODER amp;= ~(0x3u << 6u);
Когда вы включаете периферийные часы, вам нужно прочитать значение или добавить некоторую задержку для распространения изменений по шине. Обычно я использую для этого инструкцию barrier .
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
__DMB();
GPIOB->MODER amp;= ~(0x3u << 6u);
Если вы не добавите эту задержку (или обратное чтение), первая операция завершится неудачно, поскольку она будет выполняться на не синхронизированном GPIO periperal.
Комментарии:
1. Спасибо, имеет смысл! Я добавил эту строку, но все равно ничего не происходит (я уже проверил PIN-код).
2. Я обнаружил проблему, из-за которой программа выполняется только один раз (я нажимаю на эту проблему в другом потоке, потому что проблема с заголовком решена).
3. Никогда не было такой проблемы ни с одной из этих частей, это код на C, много задержек. Технически возможно с некоторыми конструкциями, но не с STM32s.
4. согласно этому документу, этот код записан в C…so больше двух часов, готово, не нужно ничего читать.
5. @old_timer это хорошо известная проблема с использованием STM32s. Я удивлен, что вы об этом не слышали. Если вы обращаетесь к периферийному устройству до установки синхронизации, следующие обращения к регистрам также могут быть неправильными. Например, STM в драйвере низкого уровня выполняет обратную считку