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

Микроконтроллеры STM8. Порты ввода-вывода.
Здравствуйте,Сегодня мы с вами разберемся, как устроены порты ввода-вывода у STM8S.
Количество линий ввода-вывода, естественно, различно у разных моделей контролеров, и колеблется от 16 (в двадцатиногом корпусе) до 68 для микроконтроллеров в корпусе LQFP-80. При этом линии портов не одинаковы и имеют различную нагрузочную способность. Уточню на всякий случай, что порты у STM8 восьмибитные, каждую ножку порта можно настроить индивидуально.
Для примера возьмем даташит на микроконтроллер, установленный в плату STM8S Discovery — STM8S105C6, если кто забыл. К слову, принцип построения документации у ST схож с подходом TI – есть один reference manual на все семейство, где описаны все возможные периферийные устройства, и отдельные короткие даташитики на каждый кристалл с описанием распиновки, содержанием периферии и электрическими характеристиками. В данном случае мы имеем даташит на все семейство STM8S105xx. Идем на страницу номер 9 и смотрим в таблицу:

Очевидно, что у нашего микроконтроллера 48 ножки, из которых в качестве линий ввода-вывода мы можем использовать 38, а из этих тридцати восьми ног шестнадцать имеют имею повышенную нагрузочную способность.
Кроме этого, ножки процессора отличаются по некоторым другим параметрам. Как пример, разберемся, какие параметры у ножки, на которую подключен светодиод на плате Dicsovery. В этом документе на странице 14 смотрим на схему модуля, и видим, что светодиод подключен к ножке PD0 с номером 41. Теперь открываем предыдущий даташит на собственно контроллер и для начала смотрим таблицу 5 на странице 21. Это легенда для таблицы номер 6, которая начинается на странице 25. Находим в ней строку, которая соответствует сорок первой ножке.

И теперь расшифровуем:
— эта ножка – после сброса находится в плавающем состоянии (в столбце floating подчеркнутый крест);
— эта ножка имеет повышенную нагрузочную способность (в столбце High Sink обозначение HS);
— для этой ножки можно выбрать максимальную скорость переключения в 2 или 10 МГц, по умолчанию 2МГц (в столбце Speed обозначение O3);
— кроме своей основной функции эта ножка способна выполнять функции второго канала для Таймера3, остановом для Таймера1, или выводить наружу тактовый сигнал микроконтроллера (столбцы Default alternate functions и Alternate functions after remap).
Основная работа с портами ввода-вывода ведется через пять регистров на каждый порт. Рассмотрим подробнее каждый из них:
Регистр Px_ODR — Port x output data register. Регистр вывода данных, аналог регистра PORTx у AVR. Если пин порта сконфигурирован на выход, то запись в соответствующий бит регистра Px_ODR ведет к соответственному изменению электрического состояния ножки порта.
Регистр Px_IDR — Port x pin input register. Регистр чтения данных, аналог регистра PINx у AVR.
Регистр Px_DDR — Port x data direction register. Регистр направления данных, аналог регистра DDRx у AVR. При записи единицы в какой-либо из битов регистра соответствующий вывод порта конфигурируется как выход. При записи ноля ножка порта конфигурируется на ввод.
Регистр Px_CR1 — Port x control register 1. Регистр управления портом. Аналога такого регистра у AVR нет. В этом регистре конфигурируются электрические свойства ножек порта. Если ножка сконфигурирована в режим ввода, то запись единицы в соответствующий бит регистра Px_CR1 включит встроенную подтяжку к питанию. В другом случае вход плавающий.
Если ножка сконфигурирована в режим вывода, то запись ноля в соответствующий бит регистра Px_CR1 переведет вывод в режим псевдооткрытого коллектора. В другом случае вывод ведет себя как push-pull. Подробнее про типы входов и выходов и с чем их едят доступно написано здесь.
Регистр Px_CR2 — Port x control register 2. Еще один регистр управления портом. Если ножка сконфигурирована на ввод, то соответствующие биты разрешают (единица) или запрещают (ноль) генерацию внешнего прерывания. Для ножки, настроенной на вывод, эти биты выбирают максимальную скорость переключения. Ноль ограничивает скорость до 2 МГц, единица – до 10 МГц.
Для нашего удобства все это сведено фирмой ST в одну табличку (ее уже приводили в этом блоге, но я повторюсь):

Теперь перейдем к практике. Я припаял на макетной области еще один светодиод и подтяжку для него и подключил его к питанию и ножке PD7. R ножке PB0 я подключил кнопку, которая подтянута к земле и коммутирует питание на ножку при нажатии.

Как можно увидеть на фото, у меня есть плата клавиатуры на четыре кнопки, мы же будем использовать одну. Все компоненты схемы соединены при помощи разъемов.

Чтобы узнать, на каком разъеме что находится смотрим таблицы распиновки на странице 11 в документации на плату Discovery. Например, ножка PB0 размещена на колодке CN 3 под номером 10. На фото — подключения на колодки:

Напишем простейшую программу, которая постоянно анализирует состояние кнопки. Если кнопка отпущена – постоянно горит один светодиод, если кнопка нажата – он гаснет и загорается другой.
#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;
}
}
}
И коротенькое видео от Капитана Очевидность о том, как работает эта программа. Заранее извиняюсь за плохое качество видео.
На сегодня все, а в следующей статье мы рассмотрим таймеры.

- +4
- 14 марта 2011, 23:02
- kalvenolt
В целом познавательно и доступно, но есть одно замечание:
Просто остальной материял, повторюсь, изложен очень доступно, а тут приходится гадать.
И теперь расшифровуем:Не очевидно какой пункт из чего получили. Возможно при открытии даташита и его изучении станет интуитивно понятно, но не мешало бы тут описать поподробнее, уж коли затронули этот момент.
— эта ножка – после сброса находится в плавающем состоянии;
— эта ножка имеет повышенную нагрузочную способность;
— для этой ножки можно выбрать максимальную скорость переключения в 2 или 10 МГц (по умолчанию 2МГц);
— кроме своей основной функции эта ножка способна выполнять функции второго канала для Таймера3, остановом для Таймера1, или выводить наружу тактовый сигнал микроконтроллера.
Просто остальной материял, повторюсь, изложен очень доступно, а тут приходится гадать.
Доброго времени суток, господа хорошие. Честно признаться, я не понял смысл пинов с «повышенной нагрузочной способностью». Это как? обычные пины могут выдавать/принимать 20 мА, а те — побольше? А побольше — это сколько? Как не искал — не нашел.
обычные линии ввода-вывода при питании 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
линии с повышенной нагрузкой при питании 3.3 вольта 10 мА
смотрите раздел
10.3.6 I/O port pin characteristics
www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00200092.pdf
Вопрос еще такой, в файле stm8s_gpio.h дано пояснение для
4-го бита в порту конфигурации GPIO:
В чем смысл установки этого бита с т.з. схемотехники?
переводит пин в высокоимпедансное состояние (дабы другим не мешать)?
Т.е. имеет смысл только только при конфигурации пина порта на вывод?
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 */
В чем смысл установки этого бита с т.з. схемотехники?
переводит пин в высокоимпедансное состояние (дабы другим не мешать)?
Т.е. имеет смысл только только при конфигурации пина порта на вывод?
*Я припаял на макетной области еще один светодиод и подтяжку для него и подключил его к питанию и ножке PD7*… в этом случае диод светится, когда на порт контроллер дает 0… так? а почему не присоединить его к контроллеру и через подтяжку к земле? Тогда светится будет при единице на порт...?
Здравствуйте!
Помогите пожалуйста… У меня на код
Вываливаются ошибки:
Понимаю, что переменные не объявлены в .h файле. Пробовал подключать и iostm8.h, но у в моем iostm8.h их тоже нет
Помогите пожалуйста… У меня на код
/*
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 их тоже нет
А если писать так:
То все компилируется, но мне не понятно, как управлять разными ногами. Допустим я хочу изменить эти биты на PD2. Как это сделать?
#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. Как это сделать?
2 sanek776 — хидеры идут к каждому С-компилятору, так что скорее всего что-то делаете не так…
ЗЫ. неплохо бы указать, какой компилятор используете, а то получается «гадание на кофейной гуще»
ЗЫ. неплохо бы указать, какой компилятор используете, а то получается «гадание на кофейной гуще»
- ChipKiller
- 15 февраля 2012, 14:49
- ↑
- ↓
… просто нужно явно включить хидер в прожект — #include <iostm8s105.h> в *.с файле не достаточно
- ChipKiller
- 15 февраля 2012, 18:00
- ↑
- ↓
делается это ровно так, как и добавление файла к прожекту — через окно «Workspase»
- ChipKiller
- 15 февраля 2012, 18:56
- ↑
- ↓
файл находится в папке stvd\inklude\ и называется stm8s105c6.h
#include <iostm8s105.h> // register definesпочему iostm8s105.h — загадка…
- ChipKiller
- 15 февраля 2012, 20:02
- ↑
- ↓
Естьл проблема… Обнаружилось, что вывод, подключенный к каналу PWM таймера, работает как push-pull вне зависимости от состояния Px_CR1. Кто-нибудь знает, это можно как-то обойти (получив open-drain PWM) или нет?
Yeah, я завел ШИМ, я не дурак. Утешили. xDDD
Что с внешними компонентами можно, это понятно. Я думал, что за счет такой прикольной фишки, как работа порта в режиме открытого коллектора удастся сократить количество рассыпухи на плате… Но нет.
Да, я перепроверил. В обычном режиме все ОК, открытый коллетор. Включаю ШИМ-таймер, не меняя настройки Px_CR1 — автоматом включается push-pull. Значит, и правда так задумано разработчиками ST.
Что с внешними компонентами можно, это понятно. Я думал, что за счет такой прикольной фишки, как работа порта в режиме открытого коллектора удастся сократить количество рассыпухи на плате… Но нет.
Да, я перепроверил. В обычном режиме все ОК, открытый коллетор. Включаю ШИМ-таймер, не меняя настройки Px_CR1 — автоматом включается push-pull. Значит, и правда так задумано разработчиками ST.
Не компилировал это и не знаю, но нет ли где в коде макроса OPT?
- teplofizik
- 26 октября 2012, 23:44
- ↑
- ↓
Если заинклюдить в такой последовательности, то получаем 360 варнингов, но подобнй ошибки как на скрине нет и всё работает.
#include «iostm8.h»
#define STM8S105
#include <stm8s.h>
#include «iostm8.h»
#define STM8S105
#include <stm8s.h>
А так ли необходимо два хедера от разных разработчиков для одного и того же?
Как минимум пример отвратительного кода.
Как минимум пример отвратительного кода.
Комментарии (45)
RSS свернуть / развернуть