Продолжаем изучение STM32 с нуля! Пришло время убедиться в том, что наша программа работает так, как задумано, и в этом нам поможет отладка в Keil (в статье используется Keil 4). Запускаем проект из предыдущей статьи про GPIO, компилируем и жмем на значок в виде лупы на панели инструментов. Также можно использовать сочетание Ctrl + F5 или пункт меню – Debug - Start/Stop Debug Session.
Итак, мы оказались в режиме отладки. Тут можно посмотреть, какие значения записаны в регистры общего назначения, также есть окошко дизассемблера и куча других инструментов:
Мы же идем в меню, в Peripherals->General Purpose I/O и в появившемся подменю выбираем наш GPIOA, задействованный в этом проекте. Появляется специальное окно для работы с портом A:
Здесь мы видим, в каком режиме работают выводы порта, какие значения в регистрах ODR, IDR, CRL, CRH, LCKR. В общем, тут есть все, связанное с GPIOA.
Давайте наконец-то это все опробуем и получим уже долгожданный результат. Идем в меню и во вкладке Debug находим Run. Также можно нажать F5. Программа полетела выполняться. Сразу же видим, что в окне GPIOA изменились режимы работы выводов 0 и 1.
Конечно, это радует, но все же где мигание диода?
А для того, чтобы диод заморгал нам надо нажимать кнопку, которую у нас символизирует вывод PA1. То есть нам необходимо сэмулировать нажатие кнопки. Вспоминаем про входной регистр GPIOA_IDR, запускаем программу и "включаем" первый бит в строке Pins:
Замечаем, что при этом у нас выставляется нужный бит регистра IDR, что нам собственно и надо. А одновременно с нажатием кнопки (выставлением первого бита GPIOA_IDR) видим, что загорается диод (выставляется первый бит регистра GPIOA_ODR). Нажимаем кнопку – горит, отпускаем – гаснет:
Но только выставлением значений регистров механизм отладки в Keil’е не ограничивается. На панели инструментов находим значок Analysis Windows.
Нажимаем – появляется окошко логического анализатора. В нем мы можем посмотреть сигнал на любой ножке микроконтроллера. Полезнейшее средство отладки, осталось только все настроить. В нижней части окна Keil есть командная строка. Пишем в ней:
la porta&0x01
и жмем Enter... Возникает вопрос, а что же мы вообще такое сделали? А мы отдали команду логическому анализатору, чтобы он нам показал сигнал на выходе нулевого бита порта A. Если бы нам понадобился, например, седьмой бит того же порта, надо было бы написать
la porta&0x80
Почему 0x80? Так 0x80 при переводе в двоичную систему дает не что иное, как 0b10000000 – наш седьмой бит.
Двигаемся дальше, в окне логического анализатора жмем правой кнопкой мыши и в появившемся меню выбираем Bit. Мы же будем отслеживать только единички и нолики на выходе PA0. Итак, все настроено, запускаем программу и в окне GPIOA эмулируем нажатие кнопки (выставляем бит). И вот что мы видим в окне анализатора:
В соответствии с нажатием кнопки меняется уровень логического сигнала на выходе PA0, что равнозначно миганию диода 🙂 Вообще логический анализатор в Keil’е – очень удобное и во многих случаях полезное средство отладки программ.
Теперь, когда мы разобрались с этим, рассмотрим еще один способ, а именно использование языка сценариев отладчика. Операторы и синтаксис языка сценариев соответствует Си, правда есть некоторые отличия:
- В языке сценариев не поддерживаются структуры.
- Есть ограничения по работе с указателями и адресами.
- Прописные символы эквивалентны строчным.
- При помощи языка сценариев невозможно вызвать функции из отлаживаемой программы.
Язык сценариев позволяет реализовать взаимодействие внешних устройств с отлаживаемой программой. Что это значит, увидим на примере.
Вернемся к нашей программе. Светодиод загорается при нажатии кнопки - то есть при логической единице на входе PA1. Попробуем вместо нажатия кнопки выставлением бита регистра IDR сэмулировать периодический внешний сигнал, поданный все на тот же вход PA0. И для этого воспользуемся языком сценариев.
Итак, приступаем! Создаем новый файл в редакторе Keil’а и набираем следующий код:
/***************************************************************************************/ signal void start(void) { while(1) { PORTA |= 0x02; twatch(400); PORTA &= ~0x02; twatch(400); } } /***************************************************************************************/
В целом, это обычная функция, за исключением ключевого слово signal, которое необходимо для эмуляции входных сигналов. Организуем вечный цикл, в котором сначала подаем логическую единицу на вход PA1, затем реализуем временную задержку, затем ноль на вход и снова задержка. То есть на входе у нас будет периодический сигнал. Сохраняем этот файл с расширением .ini, в той же папке(!), где находятся файлы проекта. Теперь запускаем режим отладки и идем в командную строку. Необходимо подключить наш созданный файл:
Include gpio.ini
У меня файл назван gpio.ini. Просим логический анализатор показать интересующие нас выводы:
- la porta&0x01 (PA0)
- la porta&0x02 (PA1)
И теперь остается только вызвать функцию для генерации сигнала. Для этого просто пишем в командной строке название функции, у меня это - start(). Можно запускать программу (F5)
Видим на экране анализатора периодический сигнал на входе PA1, и в соответствии с ним то зажигается, то гаснет светодиод на выводе PA0. То есть все работает, как задумано )
P. S. Если возникли какие либо вопросы или что-нибудь отказалось работать должным образом, пишите о своей проблеме в комментарии, буду рад помочь!