Микроконтроллеры STM8. Порты ввода-вывода.

Микроконтроллеры STM8. Порты ввода-вывода.

Здравствуйте,
Сегодня мы с вами разберемся, как устроены порты ввода-вывода у STM8S.
Количество линий ввода-вывода, естественно, различно у разных моделей контролеров, и колеблется от 16 (в двадцатиногом корпусе) до 68 для микроконтроллеров в корпусе LQFP-80. При этом линии портов не одинаковы и имеют различную нагрузочную способность. Уточню на всякий случай, что порты у STM8 восьмибитные, каждую ножку порта можно настроить индивидуально.
Для примера возьмем даташит на микроконтроллер, установленный в плату STM8S Discovery — STM8S105C6, если кто забыл. К слову, принцип построения документации у ST схож с подходом TI – есть один reference manual на все семейство, где описаны все возможные периферийные устройства, и отдельные короткие даташитики на каждый кристалл с описанием распиновки, содержанием периферии и электрическими характеристиками. В данном случае мы имеем даташит на все семейство STM8S105xx. Идем на страницу номер 9 и смотрим в таблицу:
Pin1
Очевидно, что у нашего микроконтроллера 48 ножки, из которых в качестве линий ввода-вывода мы можем использовать 38, а из этих тридцати восьми ног шестнадцать имеют имею повышенную нагрузочную способность.
Кроме этого, ножки процессора отличаются по некоторым другим параметрам. Как пример, разберемся, какие параметры у ножки, на которую подключен светодиод на плате Dicsovery. В этом документе на странице 14 смотрим на схему модуля, и видим, что светодиод подключен к ножке PD0 с номером 41. Теперь открываем предыдущий даташит на собственно контроллер и для начала смотрим таблицу 5 на странице 21. Это легенда для таблицы номер 6, которая начинается на странице 25. Находим в ней строку, которая соответствует сорок первой ножке.
Pin2
И теперь расшифровуем:
— эта ножка – после сброса находится в плавающем состоянии (в столбце floating подчеркнутый крест);
— эта ножка имеет повышенную нагрузочную способность (в столбце High Sink обозначение HS);
— для этой ножки можно выбрать максимальную скорость переключения в 2 или 10 МГц, по умолчанию 2МГц (в столбце Speed обозначение O3);
— кроме своей основной функции эта ножка способна выполнять функции второго канала для Таймера3, остановом для Таймера1, или выводить наружу тактовый сигнал микроконтроллера (столбцы Default alternate functions и Alternate functions after remap).
Основная работа с портами ввода-вывода ведется через пять регистров на каждый порт. Рассмотрим подробнее каждый из них:
Регистр Px_ODRPort x output data register. Регистр вывода данных, аналог регистра PORTx у AVR. Если пин порта сконфигурирован на выход, то запись в соответствующий бит регистра Px_ODR ведет к соответственному изменению электрического состояния ножки порта.
Регистр Px_IDRPort x pin input register. Регистр чтения данных, аналог регистра PINx у AVR.
Регистр Px_DDRPort x data direction register. Регистр направления данных, аналог регистра DDRx у AVR. При записи единицы в какой-либо из битов регистра соответствующий вывод порта конфигурируется как выход. При записи ноля ножка порта конфигурируется на ввод.
Регистр Px_CR1Port x control register 1. Регистр управления портом. Аналога такого регистра у AVR нет. В этом регистре конфигурируются электрические свойства ножек порта. Если ножка сконфигурирована в режим ввода, то запись единицы в соответствующий бит регистра Px_CR1 включит встроенную подтяжку к питанию. В другом случае вход плавающий.
Если ножка сконфигурирована в режим вывода, то запись ноля в соответствующий бит регистра Px_CR1 переведет вывод в режим псевдооткрытого коллектора. В другом случае вывод ведет себя как push-pull. Подробнее про типы входов и выходов и с чем их едят доступно написано здесь.
Регистр Px_CR2Port x control register 2. Еще один регистр управления портом. Если ножка сконфигурирована на ввод, то соответствующие биты разрешают (единица) или запрещают (ноль) генерацию внешнего прерывания. Для ножки, настроенной на вывод, эти биты выбирают максимальную скорость переключения. Ноль ограничивает скорость до 2 МГц, единица – до 10 МГц.
Для нашего удобства все это сведено фирмой ST в одну табличку (ее уже приводили в этом блоге, но я повторюсь):
Pin3
Теперь перейдем к практике. Я припаял на макетной области еще один светодиод и подтяжку для него и подключил его к питанию и ножке PD7. R ножке PB0 я подключил кнопку, которая подтянута к земле и коммутирует питание на ножку при нажатии.
Board1
Как можно увидеть на фото, у меня есть плата клавиатуры на четыре кнопки, мы же будем использовать одну. Все компоненты схемы соединены при помощи разъемов.
Board2
Чтобы узнать, на каком разъеме что находится смотрим таблицы распиновки на странице 11 в документации на плату Discovery. Например, ножка PB0 размещена на колодке CN 3 под номером 10. На фото — подключения на колодки:
Board3
Напишем простейшую программу, которая постоянно анализирует состояние кнопки. Если кнопка отпущена – постоянно горит один светодиод, если кнопка нажата – он гаснет и загорается другой.

#include "iostm8.h"      // подключение заголовочного файла с объявлениями регистров, масок и битов

int main( void )         // Основная программа
{
 
  PD_DDR_bit.DDR0 = 1;   // Ножка PD0 конфигурируется на вывод
  PD_CR1_bit.C10 = 1;   // Выход типа Push-pull
  PD_CR2_bit.C20 = 1;   // Скорость переключения - до 10 МГц.
  
  PD_DDR_bit.DDR7 = 1;   // Ножка PD7 конфигурируется на вывод
  PD_CR1_bit.C17 = 1;   // Выход типа Push-pull
  PD_CR2_bit.C27 = 1;   // Скорость переключения - до 10 МГц.
  
  PB_DDR_bit.DDR0 = 0;   // Ножка PB0 конфигурируется на ввод
  PB_CR1_bit.C10 = 0;   // Выход плавающий - у меня установлен подтягивающий резистор
  PB_CR2_bit.C20 = 0;   // Прерывание отключено
  
  
  while(1)              // Бесконечный цикл
  {
        if (PB_IDR_bit.IDR0 == 1) // Проверяем состояние кнопки
        {
          PD_ODR_bit.ODR0 = 1;    // Зажигаем нужные светодиоды
          PD_ODR_bit.ODR7 = 0;    // в зависимости от состояния кнопки
        } else 
        {
          PD_ODR_bit.ODR0 = 0;
          PD_ODR_bit.ODR7 = 1;
        }
  }

}


И коротенькое видео от Капитана Очевидность о том, как работает эта программа. Заранее извиняюсь за плохое качество видео.

На сегодня все, а в следующей статье мы рассмотрим таймеры.

Комментарии (45)

RSS свернуть / развернуть
Все хорошо, плюсик тебе. Ток это, нафиг такой здоровый аляповатый логотип ST лепить в каждый пост. Да еще загружать его каждый раз заново :)
0
Нам ST в отличии от Masteram за рекламу плюшек не дает :)
0
Нравится мне он)
И статью видно сразу)
Но раз начальство просит — уберу.
0
В целом познавательно и доступно, но есть одно замечание:
И теперь расшифровуем:
— эта ножка – после сброса находится в плавающем состоянии;
— эта ножка имеет повышенную нагрузочную способность;
— для этой ножки можно выбрать максимальную скорость переключения в 2 или 10 МГц (по умолчанию 2МГц);
— кроме своей основной функции эта ножка способна выполнять функции второго канала для Таймера3, остановом для Таймера1, или выводить наружу тактовый сигнал микроконтроллера.
Не очевидно какой пункт из чего получили. Возможно при открытии даташита и его изучении станет интуитивно понятно, но не мешало бы тут описать поподробнее, уж коли затронули этот момент.
Просто остальной материял, повторюсь, изложен очень доступно, а тут приходится гадать.
0
Добавил. Просто не хотелось заполнять статью скриншотами из даташита.
0
Доброго времени суток, господа хорошие. Честно признаться, я не понял смысл пинов с «повышенной нагрузочной способностью». Это как? обычные пины могут выдавать/принимать 20 мА, а те — побольше? А побольше — это сколько? Как не искал — не нашел.
0
обычные линии ввода-вывода при питании 3.3 вольта 4 мА
линии с повышенной нагрузкой при питании 3.3 вольта 10 мА
смотрите раздел
10.3.6 I/O port pin characteristics
www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00200092.pdf
0
Вопрос еще такой, в файле stm8s_gpio.h дано пояснение для
4-го бита в порту конфигурации GPIO:


 /* 
  Bits definitions: 
  - Bit 7: 0 = INPUT mode 
           1 = OUTPUT mode 
  - Bit 6: 0 = FLOAT (input) or OPEN-DRAIN (output) 
           1 = PULL-UP (input) or PUSH-PULL (output) 
  - Bit 5: 0 = No external interrupt (input) or No slope control (output) 
           1 = External interrupt (input) or Slow control enabled (output) 
  - Bit 4: 0 = Low level (output) 
           1 = High level (output push-pull) or HI-Z (output open-drain) 
  */ 
  GPIO_MODE_IN_FL_NO_IT      = (u8)0b00000000, /*! Input floating, no external interrupt */ 
  GPIO_MODE_IN_PU_NO_IT      = (u8)0b01000000, /*! Input pull-up, no external interrupt */ 
  GPIO_MODE_IN_FL_IT         = (u8)0b00100000, /*! Input floating, external interrupt */ 
  GPIO_MODE_IN_PU_IT         = (u8)0b01100000, /*! Input pull-up, external interrupt */ 
  GPIO_MODE_OUT_OD_LOW_FAST  = (u8)0b10000000, /*! Output open-drain, low level, no slope control */ 
  GPIO_MODE_OUT_PP_LOW_FAST  = (u8)0b11000000, /*! Output push-pull, low level, no slope control */ 
  GPIO_MODE_OUT_OD_LOW_SLOW  = (u8)0b10100000, /*! Output open-drain, low level, slow slope */ 
  GPIO_MODE_OUT_PP_LOW_SLOW  = (u8)0b11100000, /*! Output push-pull, low level, slow slope */ 
  GPIO_MODE_OUT_OD_HIZ_FAST  = (u8)0b10010000, /*! Output open-drain, high-impedance level, no slope control */ 
  GPIO_MODE_OUT_PP_HIGH_FAST = (u8)0b11010000, /*! Output push-pull, high level, no slope control */ 
  GPIO_MODE_OUT_OD_HIZ_SLOW  = (u8)0b10110000, /*! Output open-drain, high-impedance level, slow slope */ 
  GPIO_MODE_OUT_PP_HIGH_SLOW = (u8)0b11110000  /*! Output push-pull, high level, slow slope */ 


В чем смысл установки этого бита с т.з. схемотехники?

переводит пин в высокоимпедансное состояние (дабы другим не мешать)?
Т.е. имеет смысл только только при конфигурации пина порта на вывод?
0
*Я припаял на макетной области еще один светодиод и подтяжку для него и подключил его к питанию и ножке PD7*… в этом случае диод светится, когда на порт контроллер дает 0… так? а почему не присоединить его к контроллеру и через подтяжку к земле? Тогда светится будет при единице на порт...?
0
  • avatar
  • Onic
  • 07 февраля 2012, 13:36
Ответы на вопросы: да. Потому как фаза луны. да.
0
Потому как фаза луны.
Скорее привычка из тех времен, когда N-канальники в микрах были сильно лучше, чем P-канальники.
0
и ОК тоже :)
0
Ну и NPN были лучше, чем PNP.
В общем, кратко — большинство микросхем вниз тянуло лучше, а то и вовсе только вниз и тянуло. Отсюда и привычка :)
0
Здравствуйте!
Помогите пожалуйста… У меня на код
/*
	STM8S-DISCOVERY minimal blink for Cosmic C compiler		
	LED is connected to high sink pin PD0 (active low)
*/	
#include <iostm8s105.h> // register defines

typedef unsigned short uint16_t;
#define LED_BIT 0 
#define nop()                 {_asm("nop\n");}  /* No Operation */

void main()
{		
	uint16_t d = 0;	

	PD_DDR_bit.DDR0 = 1; // Set to output
	PD_CR1_bit.C10 |= 1; // Push-pull output

	
	for (;;)
	{	
		// dummy delay loop
		
		
		for (d = 0; d < 40000; d++) 
		{
			nop();
		}
		
		
		PD_ODR_bit.ODR0 ^= 1;
	}
}


Вываливаются ошибки:

----------- Project led - STM8 Cosmic - Configuration Debug -------------

Compiling main.c...
cxstm8 +debug -pxp -no -l +mods0 -pp -i"C:\Program Files (x86)\COSMIC\CXSTM8_32K\Hstm8"  -clDebug\ -coDebug\ main.c 
#error cpstm8 main.c:15(12+4) bad struct/union operand
#error cpstm8 main.c:16(12+3) bad struct/union operand
#error cpstm8 main.c:30(13+4) bad struct/union operand
#error cpstm8 main.c:16(1+10) PD_CR1_bit undefined
#error cpstm8 main.c:15(1+10) PD_DDR_bit undefined
#error cpstm8 main.c:30(2+10) PD_ODR_bit undefined
main.c:
 The command: "cxstm8 +debug -pxp -no -l +mods0 -pp -i"C:\Program Files (x86)\COSMIC\CXSTM8_32K\Hstm8"  -clDebug\ -coDebug\ main.c " has failed, the returned value is: 1
exit code=1.

led.elf - 8 error(s), 0 warning(s)


Понимаю, что переменные не объявлены в .h файле. Пробовал подключать и iostm8.h, но у в моем iostm8.h их тоже нет
0
А если писать так:
#include <iostm8s105.h> // register defines

typedef unsigned short uint16_t;
#define LED_BIT 0 
#define nop()                 {_asm("nop\n");}  /* No Operation */

void main()
{		
	uint16_t d = 0;	

	PD_DDR = 1; // Set to output
	PD_CR1 |= 1; // Push-pull output

	
	for (;;)
	{	
		// dummy delay loop
		
		
		for (d = 0; d < 40000; d++) 
		{
			nop();
		}
		
		
		PD_ODR ^= 1;
	}
}

То все компилируется, но мне не понятно, как управлять разными ногами. Допустим я хочу изменить эти биты на PD2. Как это сделать?
0
PD_ODR ^= (1<<bitnum);

Но лучше найти определения структур или написать самому их. Удобнее всё же.
0
Понимаю, что лучше найти определения… только найти не могу их никак…
0
2 sanek776 — хидеры идут к каждому С-компилятору, так что скорее всего что-то делаете не так…
ЗЫ. неплохо бы указать, какой компилятор используете, а то получается «гадание на кофейной гуще»
0
использую STVD + Cosmic
0
… просто нужно явно включить хидер в прожект — #include <iostm8s105.h> в *.с файле не достаточно
0
эмм… странно… а где это делается, не подскажете?
0
делается это ровно так, как и добавление файла к прожекту — через окно «Workspase»
0
у меня этот файл и так в проекте был. но всякий случай еще раз добавил, но ноль реакции. Я заглядывал в сам .h файл, но там нет описаний этих битов
0
чудес не бывает — сам использую Cosmic и все ОК
0
А можете мне скинуть ваш .h файл. Чтобы уж точно знать, что это я порталу. Если не слоэно
0
файл находится в папке stvd\inklude\ и называется stm8s105c6.h
#include <iostm8s105.h> // register defines
почему iostm8s105.h — загадка…
0
Помогите пожалуйста!
Не понимаю в чем дело. Сегодня попытался прошить мк на discovery, но красный СД на st-link не загорелся и stm32 который там стоит начал безумно сильно греться и дебаггер выдал ошибку о том что устройство не отвечает
0
Естьл проблема… Обнаружилось, что вывод, подключенный к каналу PWM таймера, работает как push-pull вне зависимости от состояния Px_CR1. Кто-нибудь знает, это можно как-то обойти (получив open-drain PWM) или нет?
0
Диод шоттки на выход повесить… не??? )))
0
С диодом каждый дурак сможет. Я-то думал использовать эту прикольную фишечку STM8…
0
Сомневаюсь )))))
Дурак и МК спалит, и ШИМ не заведёт… ))))))))))))))
0
Yeah, я завел ШИМ, я не дурак. Утешили. xDDD

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

Да, я перепроверил. В обычном режиме все ОК, открытый коллетор. Включаю ШИМ-таймер, не меняя настройки Px_CR1 — автоматом включается push-pull. Значит, и правда так задумано разработчиками ST.
0
Диодом, как уже посоветовали. Некоторая переферия сама настраивает выводы для себя. Возможно таймер относится к числу такой переферии. Это долбанутый участок стм8, фиг найдешь кто настраивает и как, а кто нет.
0
Вот да, нигде не нашел. Ни в reference manual, ни в даташите на сам МК, ни в аппноуте по ШИМу.
0
Ошибка в iostm8.h:

Как это исправить?
0
И еще вопрос: как залить прошивку без отладки? пункт меню Project->Download всегда не активный.
0
Насчет Project->Download не знаю, но можно взять ST-шный прошиватор и запихнуть его в меню Tools.
0
Не компилировал это и не знаю, но нет ли где в коде макроса OPT?
0
Если заинклюдить в такой последовательности, то получаем 360 варнингов, но подобнй ошибки как на скрине нет и всё работает.
#include «iostm8.h»
#define STM8S105
#include <stm8s.h>
0
А так ли необходимо два хедера от разных разработчиков для одного и того же?
Как минимум пример отвратительного кода.
0
Как минимум пример из статьи без второго хедера не работает.
0
*без первого
0
Первый нужен из-за взятых из него структур данных PD_DDR_bit и иже с ним. В статье собственно по этомы и подключен iostm8.h.
А вот stm8s.h уже воткнули вы. Зачем?
Вы используйте либо базовую библиотеку IAR'а, либо STD PL. Мешать их не следует.
0
Так мне удобнее с портами работать через регистры, а не с помощью тех библиотечных функций. Раз не следует, тогда не буду.
0
Выше были сообщения о том что STDV+Cosmic не желают работать с битовыми операциями вроде:
PD_ODR_bit.ODR0 ^= 1;

Тоже с этим столкнулся. Файл stm8s105c6.h в проект добавлял, не помогло. Нет таких описаний в этом файле, только PD_ODR заработало, а биты никак…
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.