Найти тему
Разумный мир

Микроконтроллеры для начинающих. Часть 47. Порты ввода-вывода STM8

Оглавление

В предыдущей статье "Микроконтроллеры для начинающих. Часть 46. Порты ввода-вывода PIC" мы познакомились с некоторыми подробностями реализации портов ввода-вывода микроконтроллеров PIC. Главной сложностью тогда было многообразие вариантов.

Сегодня мы поговорим о гораздо более логичной организации портов в микроконтроллерах STM8. При этом их функциональность достаточно высока. Но, как мы вскоре увидим, у этих микроконтроллеров гораздо больше общего, чем может показаться на первый взгляд.

Сегодня я тоже буду опираться на статью "Микроконтроллеры для начинающих. Часть 45. Порты ввода-вывода". Если вы ее еще не прочитали, то советую это сделать прямо сейчас.

В дальнейшем я буду использовать условные обозначения REG.bitx. Здесь REG это имя одного из регистров порта, а bitx обозначает один из разрядов, если номер не важен. Например, ODR.bitx будет обозначать один из битов регистра ODR (не важно, какой). Если же речь будет идти о конкретном бите, то это будет выглядеть так, ODR.bit3 - бит 3 регистра ODR.
Эти условные обозначения опираются на статью "Микроконтроллеры для начинающих. Часть 34. Мост к Си. Описываем регистры аппаратуры" и статью "Микроконтроллеры для начинающих. Часть 33. Мост к Си. Работа с битами"
Если потребуется дополнительно уточнить, о каком порте идет речь, то в начале обозначения будет добавляться имя порта. Например, PORTB.ODR.bit5 - бит регистра ODR порта B.

Реализация портов ввода-вывода STM8

В отличии от PIC, в STM8 порты реализованы одинаково (почти) во всей линейке.

Реализация портов ввода-вывода STM8. Из документации
Реализация портов ввода-вывода STM8. Из документации

Не правда ли, очень похоже на то, как устроено в PIC (с регистрами LAT)? Не верите? Давайте абстрагируемся от названий регистров и альтернативных функций (их опять не будем пока рассматривать).

В данном случае, показан более детально выходной буферный каскад. Для PIC он был показан в виде функционального блока. Но здесь, в целом, нет отличий, что я показывал в 45 статье цикла. Там же, я привел таблицу соответствия имен регистров.

Регистр ODR это регистр-защелка выходных данных, который доступен и для чтения. Это аналог регистра LAT в PIC. И точно так же, записанные в него данные не обязательно появятся на выводах микроконтроллера. При чтении ODR возвращаются именно записанные в него данные, а не фактическое состояние выводов.

Режим работы"вход"/"выход", или направление передачи данных, выбирается регистром DDR. Это аналог регистра TRIS в PIC. Но в данном случае режим "выход" задается единичным состоянием соответствующего бита, а не нулевым, как в PIC.

Регистр IDR позволяет считывать фактическое состояние выводов микроконтроллера. Это почти аналог регистра PORT в PIC (при наличии регистра LAT). Почти, так как в регистр IDR невозможна запись.

А вот все настройки разрядов порта, кроме направления передачи, задаются парой регистров, CR1 и CR2. В отличии от того винегрета, который присутствует в PIC. Но для PIC это во многом объясняется требованиями совместимости с ранними моделями, а STM8 все таки относительно молодые микроконтроллеры.

Настройки портов ввода-вывода

Два регистра управления дают 4 варианта настроек для каждого разряда. Но поскольку тут принимает участие и регистр DDR, то вариантов становится 8. 4 для входа и 4 для выхода.

Настройки для режима "вход"

Когда разряд порта работает как цифровой вход (DDR.bitx=0), регистр CR1 управляет подключением подтягивающих резисторов (к положительному выводу источника питания). Если CR1.bitx=0, то подтягивающий резистор отключен (плавающий вход). Если CR1.bitx=1, то подтягивающий резистор подключен.

Регистр CR2 управляет обработкой прерываний для соответствующего разряда порта. Мы пока не изучали прерывания, поэтому я не буду подробно описывать все связанное с генерацией и обработкой прерываний для разрядов порта, это еще впереди. Фактически, каждый вывод порта может использоваться как вход внешнего прерывания работающий по фронту или по уровню. И это настраивается специальными регистрами.

Сегодня будет достаточным сказать, что CR2.bitx=0 запрещает формирование запросов прерывания для соответствующего разряда порта. А CR2.bitx=1 разрешает использование соответствующего разряда как входа внешних прерываний.

Настройки для режима "выход"

Когда разряд порта работает как цифровой выход (DDR.bitx=1), регистр CR1 управляет переключением между двухтактным выходом и выходом с открытым стоком (псевдо-открытый сток). Разумеется, такое переключение невозможно для выводов в который двухтактный выход не реализован в принципе (истинный открытый сток).

CR1.bitx=0 переключает выход в режим открытого стока, а CR1.bitx=1 в двухтактный режим.

Регистр CR2 управляет скоростью нарастания напряжения (быстродействием вывода). CR2.bitx=0 ограничивает быстродействие вывода разряда порта, а CR2.bitx=1 разрешает работу на максимальной частоте.

Дополнительные настройки

Не смотря на то, что это относится к работе аналоговых модулей, я все таки кратко коснусь еще одного регистра. Точнее пары регистров, ADC_TDRH и ADC_TDRL.

Эти регистры управляют работой триггеров Шмитта между выводом микроконтроллера и входом регистра IDR. Дело в том, что триггер Шмитта может негативно влиять на точность работы аналогового модуля. По этой причине и предусмотрена возможность их отключения.

Но отключение триггера Шмитта приводит к тому, что для соответствующего разряда порта будет невозможно определить фактическое состояние вывода даже в том случае, если он не используется аналоговым модулем (используется как цифровой вход).

Регистры ADC_TDR определены не для портов ввода-вывода, а для аналоговых каналов. Например, для микроконтроллера STM8S103K3 в корпусе LQFP32 отключение триггера Шмитта для аналогового канала 2 (вывод 14 - PB2/AIN2/TIM1_CH3N) на самом деле отключит цифровой вход разряда 2 порта В.

Цикл чтение-модификация-запись

Для STM8 эта проблема не актуальна, так как пути чтения и записи данных для разрядов порта разделены. Точно так же, как для портов с регистрами LAT в PIC. Но в данном случае еще и регистр IDR не доступен для записи.

При этом, с точки зрения процессора, операции с битами по прежнему выполняются как чтение-модификация-запись. Только нам это уже никак не мешает.

"Темная" сторона логичности

У каждого плюса, как известно, есть свой минус. Так же и здесь.

Иногда в программах требуется частое переключение работы вывода порта между "вход" и "выход". Например, это использовалось в работе с емкостным датчиком методов переноса заряда в статье "Емкостные датчики. Измерения и обработка сигнала". И вот тут несоответствие настроек режимов может мешать.

Например, нам требуется выход в режиме "двухтактный, ограничение быстродействия". Для этого мы установим CR1.bitx=1 и CR2.bitx=0. Но если при этом нам потребуется и режим "подтяжка отключена, прерывания разрешены", то возникает проблема, так для это потребуется CR1.bitx=0 и CR2.bitx=1.

То есть, простое переключение DDR.bitx нам уже не подойдет. Нужно изменять биты сразу в трех регистрах. Причем это не всегда может быть простым. Например, в данном случае сброс бита в CR1 перед переключением в режим входа приводит к проблеме, если на выходе был установлен высокий уровень, а внешней подтяжки нет.

Поэтому иногда приходится прибегать и к объединению нескольких выводов, что бы обеспечить требуемые параметры переключения, и к использованию отключения триггеров Шмитта, и к хитрым программным решениям. Какого то единого способа нет, все определяется конкретной ситуацией.

Нужно отметить, что эта проблема не является особенностью именно STM8. Она свойственна многим микроконтроллерам со сложными настройками портов и большой их функциональностью. Но это иногда может очень сильно повлиять на выбор микроконтроллера для конкретной прикладной задачи.

Работа с большими втекающими/вытекающими токами

Для многих микроконтроллеров сегодня просто объявляется, что они могут обеспечить некоторое значение тока через выводы портов. Причем все выводы считаются в этом отношении равнозначными. Но в STM8 ситуация более сложная.

В этих микроконтроллерах выходы портов делятся на обычные и высокотоковые (high sink - HS). Причем даже отдельные выводы одного порта могут быть разными. Например, для уже ранее упоминавшегося STM8S103K3 разряды порта В 0, 1, 2 и 3 являются высокотоковыми, а остальные нет.

Вообще, этому вопросу в документации уделяется мало внимания. А это вызывает вопросы у тех, кто только начинает работать с этими микроконтроллерами. Давайте попробуем разобраться.

Во первых, для всех портов максимальный ток одного разряда может достигать 20 мА, как втекающий, так и вытекающий. То есть, по этому параметру разницы нет.

А вот по уровням напряжения на выходе разница уже есть. У высокотоковых выводов сопротивление каналов транзисторов выходного двухтактного буфера гораздо меньше. Что позволяет, при одинаковом токе через вывод обеспечивать меньшее падение напряжения на транзисторе. Вот и вся разница.

Начальное состояние после сброса (включения питания)

Здесь, в целом, нет отличия от других микроконтроллеров. После сброса разряды порта настроены как цифровые входы, без подтягивающих резисторов, а прерывания запрещены. Триггеры Шмитта разрешены.

Заключение

В STM8 порты кажутся более простыми в работе, чем в PIC. Но это несколько обманчивое впечатление.

Собственно работа с уже настроенным портом проста и в STM8, и в PIC (с LAT регистрами). Только имена регистров разные. А вот настройка в STM8 действительно проще, прежде всего из-за единообразия и логичности. Но за STM8 не тянется груз старых моделей.

Функциональность портов в STM8 практически полностью аналогична PIC современных семейств. Так что тут паритет. Но в STM8 производитель часто размещает в микроконтроллере много портов, но зато от каждого лишь несколько разрядов. Причем расположенных в середине байта. А это бывает неудобно с точки зрения программирования.

В следующий раз мы рассмотрим порты ввода-вывода AVR.

До новых встреч!