Прежде всего стоит отметить, что в практической работе совершенно не использовалась библиотека Standard Peripheral driver Library (SPL), чтобы избежать излишней абстракции и исключить процедуру поиска, установки, настройки - сейчас бы это только мешало и запутывало. При компиляции проекта использовались лишь определения периферии из заголовочных файлов компилятора Cosmic (CXSTM8). Посмотрим в заголовочный файл iostm8s103.h в котором описаны регистры периферии. Вот интересный фрагмент, описывающий порт PB. Управление всеми линиями этого порта умещается в пять восьмибитных регистров (однако на МС STM8S103F3T6 выведено лишь две линии порта PB, это PB4 и PB5)
ODR - output digital register - данные для вывода на порт. 8 бит - 8 линий.
IDR - input digital register - данные со входов. Только для чтения.
DDR - data direction register - определяет, как будет работать конкретная линия: на ввод или на вывод.
CR1, CR2 - дополнительная конфигурация линий порта, как то подтяжка входов, тип выходов, скорость переключения и разрешение прерываний линии.
/* Отрывок кода из заголовочного файла IOSTM8S103.H */
/* Port B */
volatile char PB_ODR @0x5005; /* Data Output Latch reg */
volatile char PB_IDR @0x5006; /* Input Pin Value reg */
volatile char PB_DDR @0x5007; /* Data Direction */
volatile char PB_CR1 @0x5008; /* Control register 1 */
volatile char PB_CR2 @0x5009; /* Control register 2 */
Поскольку процессор построен по архитектуре фон Неймана, то адресное пространство у программы, у данных, у регистров одно и то же. Для обновления значений регистров мы всего лишь записываем новое значение по конкретному адресу. Точно так же читаем, если нужно.
/* Листинг из практической работы Hello, LED */
#include <iostm8s103.h>
int delay(unsigned int it) {
while(it--);
}
int main(void) {
PB_DDR = 0b00100000;
// PB5 - output
while(1) {
PB_ODR = 0xFF; // all PB high
delay(50000); // pause
PB_ODR = 0x00; // all PB low
delay(10000); // pause
}
}
Первое, что сделала программа в практической работе - это записала в регистр PB_DDR (по адресу 0x5007) значение 0b00100000. Это число в двоичном формате, где 5-ый бит соответствует 5-ой линии порта, и она установлена в 1 (выходной), а остальные линии 0 (входной).
Затем программа уходит в бесконечный цикл. В нем мы уже обращаемся к регистру PB_ODR и пишем в него 0xFF (в двоичном коде это все единицы). Логическая единица выставляется только на линии PB5 (но не на остальных, так как они настроены как вход). После паузы во все линии порта пишется 0, затем снова пауза и все повторяется по-новой.
Регистры PB_CR1, PB_CR2 мы не трогали. Хотя вот как они работают (жирным шрифтом значения по-умолчанию):
Регистр Control |
Линия входная |
Линия выходная |
CR1 |
PULL-UP (подтяжка входа) |
Топология выхода: |
CR2 |
Прерывание при изменении уровня входа |
Скорость переключения: |
Pull-up резистор обычно подсоединяется между линией порта и Vdd, его еще называют резистор подтяжки. На всех линиях (кроме NRST) можно подключать и отключать эти подтяжки программно.
Топологию лучше всего показать наглядно. На схеме.
Скорость будет рассмотрена позже, при разборе системы тактирования.