Оглавление
DM634
Тайваньский чип с 16-ю 16-битными ШИМ-выходами, можно соединять в цепочки. Младшая 12-битная модель известна по отечественному проекту . В свое время, выбирая между DM63x и хорошо известным TLC5940, остановился на DM по нескольким причинам: 1) TLC на Алиэкспрессе точно поддельный, а этот – нет; 2) у DM автономный ШИМ со своим генератором частоты; 3) его можно было недорого купить в Москве, а не ждать посылки с Али. Ну и, конечно, было интересно самому научиться управлять чипом, а не использовать готовую библиотеку. Чипы сейчас в основном представлены в корпусе SSOP24, их несложно припаять на переходник.
Поскольку производитель тайваньский, к чипу написан на китайском английском, а значит, будет весело. Сперва смотрим на распиновку (Pin Connection), чтобы понять, к какой ноге что подключать, и описание пинов (Pin Description). 16 выводов:
Sink / Open-drain output – сток; источник втекающего тока; выход, в активном состоянии подключенный к земле, – светодиоды к драйверу подключаются катодами. Электрически это, конечно, никакой не «открытый сток» (open drain), но в даташитах такое обозначение для выводов в режиме стока встречается часто.
Между пином REXT и землей устанавливается референсный резистор, контролирующий внутреннее сопротивление выходов, см. график на стр. 9 даташита. В DM634 этим сопротивлением можно также управлять программно, устанавливая общую яркость (global brightness); в этой статье вдаваться в подробности не буду, просто поставлю сюда резистор на 2.2 – 3 кОм.
Чтобы понять, как управлять чипом, посмотрим на описание интерфейса устройства:
Ага, вот он, китайский английский во всей красе. Перевести это проблематично, понять при желании можно, но есть другой путь – взглянуть, как описывается подключение в даташите к функционально близкому TLC5940:
Latch – задвижка/защелка/фиксатор.Rising edge – передний фронт импульсаMSB first – старшим (крайним левым) битом вперед.to clock data – передавать данные последовательно (побитно).
Слово latch часто встречается в документации к чипам и переводится разнообразно, поэтому для понимания позволю себе
LED-драйвер – по сути сдвиговый регистр. «Сдвиг» (shift) в названии – побитное перемещение данных внутри устройства: каждый новый засунутый внутрь бит пихает всю цепочку перед собой вперед. Поскольку во время сдвига никто не хочет наблюдать хаотичное мигание светодиодов, процесс происходит в буферных регистрах, отделенных от рабочих заслонкой (latch) – это своего рода предбанник, где биты выстраиваются в нужную последовательность. Когда все готово, заслонка открывается, и биты отправляются работать, заменяя предыдущую партию. Слово latch в документации к микросхемам почти всегда подразумевает такую заслонку, в каких бы сочетаниях оно ни использовалось.
Итак, передача данных в DM634 осуществляется так: выставляем вход DAI в значение старшего бита дальнего светодиода, дергаем DCK вверх-вниз; выставляем вход DAI в значение следующего бита, дергаем DCK; и так далее, пока все биты не будут переданы (clocked in), после чего дергаем LAT. Это можно сделать вручную (bit-bang), но лучше воспользоваться специально под это заточенным интерфейсом SPI, благо он представлен на нашем STM32 в двух экземплярах.
Preface
STM8 is a cheap 8-bit microcontroller aimed towards low-cost mass-market devices. Initially I came across this part while searching for a simple microcontroller as a replacement for AVRs. Despite having various ARM Cortex-M0 devices available on the market for quite attractive prices, AVRs have one advantage — simplicity. Utilizing an ARM Cortex core to switch some lights on and off seems like an overkill. Some applications just don’t require that amount of flexibility and performance.
The main goal of this article is to demonstrate that ‘bare metal’ programming is not a difficult task and to give you an overview of STM8’s architecture and peripherals. Even though writing peripheral drivers from scratch might seem like reinventing the wheel, in many cases it is easier and faster to implement the functionality that you need for a specific task, instead of relying on vendor-supplied libraries that try to do everything at once (and fail).
Структура документации
В принципе, всего кроме этого раздела можно было и не писать. Документация у ST довольно неплохая. Главное знать, что и где искать. (Примеры будут для контроллера, который валяется у меня прямо сейчас на столе — stm8l152c4)
В отличии от Atmel’a, дядьки из ST поступили умнее, и разбили документацию на несколько частей. В даташите они приводят только отличие конкретного контроллера от всей остальной линейки. В даташите нужно искать электрические параметры, размер памяти, список периферии.
Немного ниже есть reference manual – это документация на всю линейку. Тут описывается переферия и регистры. Вообщем то, что нужно нормальному сишнику для программирования.
Если полистать ниже, то можно наткнуться на Errata sheet. Ошибок много, но серьезных практически нет.
Если ты – сумасшедший ассемблерщик (С), и этого тебе не хватило, то, в разделе Programming Manual, можно найти документ STM8 CPU programming manual. Это — описание самого ядра, набора инструкций, их таймингов, итп.
Включаем тактирование
За тактирование отвечают часики, они же Clock. И мы уже могли заметить аббревиатуру RCC. Ищем ее в документации: это Reset and Clock Control (Управление сбросом и тактированием).
Как выше было сказано, к счастью, самое сложное из темы тактирования за нас сделали люди из STM, за что им большое спасибо (еще раз дам ссылку на , чтобы было понятно, насколько это заморочено). Нам нужны всего лишь регистры, отвечающие за включение тактирования периферии (Peripheral Clock Enable Registers). Для начала найдем базовый адрес RCC, он в самом начале «Карты памяти»:
И в них, соответственно, биты, включающие тактирование SPI2, IOPB (I/O Port B) и альтернативных функций (AFIO).
Финальный код можно найти .
Если есть возможность и желание потестить, то подключаем DM634 так: DAI к PB15, DCK к PB13, LAT к PB14. Питаем драйвер от 5 вольт, не забываем объединить земли.
ШИМ на STM8
Когда я только планировал эту статью, я решил для примера попробовать освоить какой-нибудь функционал незнакомого мне чипа с помощью только даташита, чтобы не получался сапожник без сапог. STM8 на эту роль подходил идеально: во-первых, у меня была пара китайских плат с STM8S103, а во-вторых, он не слишком популярен, а потому соблазн почитить и найти решение в интернете упирается в отсутствие этих самых решений.
К чипу также есть и , в первом распиновка и адреса регистров, во втором – все остальное. Программируется STM8 на C в страшненькой IDE .
Тактирование и ввод-вывод
По умолчанию STM8 работает на частоте 2 МГц, это надо сразу исправить.
Находим адрес регистра в даташите, описание в refman и видим, что регистр надо очистить:
Поскольку мы собираемся запускать ШИМ и подключать светодиоды, смотрим распиновку:
Чип маленький, многие функции подвешены на одни и те же пины. То, что в квадратных скобках – «альтернативный функционал», он переключается «байтами опций» (option bytes) – что-то вроде фьюзов Атмеги. Менять их значения можно программно, но не нужно, т.к. активируется новый функционал только после перезагрузки. Проще воспользоваться ST Visual Programmer (качается вместе с Visual Develop), умеющим менять эти байты. В распиновке видно, что выводы CH1 и CH2 первого таймера спрятаны в квадратные скобки; надо в STVP проставить биты AFR1 и AFR0, причем второй также перенесет вывод CH1 второго таймера с PD4 на PC5.
Таким образом, управлять светодиодами будут 6 пинов: PC6, PC7 и PC3 для первого таймера, PC5, PD3 и PA3 для второго.
Настройка самих пинов ввода-вывода на STM8 проще и логичнее, чем на STM32:
- знакомый по Atmega регистр направления данных DDR (Data Direction Register): 1 = вывод;
- первый контрольный регистр CR1 при выводе задает режим «тяни-толкай» (1) или открытый сток (0); поскольку я подключаю светодиоды к чипу катодами, оставляю тут нули;
- второй контрольный регистр CR2 при выводе задает скорость тактирования: 1 = 10 МГц
It’s all just memory..
Before we begin, let’s take a simple example of accessing port register on ATmega and see what’s going on under the hood:
12345678 |
PORTB = (1 << PB2);(* (volatile uint8_t *) ((0x05) + 0x20)) = (1 << 2);* (volatile uint8_t *) 0x25 = 0x04; |
Typecasting integer to a pointer is a valid operation in C. If you don’t quite understand what is going on with pointer arithmetics then here’s another example for you:
123 |
uint8_t a = 0xDE; uint8_t *ptr = &a; *ptr = 0xAD; |
The only difference is that in the first example we know exactly which address in memory we are going to use. It’s important that you understand what’s going on here, since we’re going to use this mechanism for accessing hardware registers later on.
Библиотека
ST сделала такую штуку, которая называется STM8x Firmware library. Это – суть фрэймворк для микроконтроллеров.
Давайте, к примеру, запустим АЦП
1#include «stm8a_lib.h»
2
3void main(void)
4{
5 ADC_DeInit();
6 enableInterrupts();
7
8 /* Init ADC peripheral */
9 ADC_Init(ADC_CONVERSIONMODE_CONTINUOUS, ADC_CHANNEL_9,
10 ADC_PRESSEL_FCPU_D2, ADC_EXTTRIG_TIM, DISABLE,
11 ADC_ALIGN_RIGHT, ADC_SCHMITTTRIG_CHANNEL9, DISABLE);
12
13 /* Enable EOC interrupt */
14 ADC_ITConfig(ENABLE);
15
16 /*Start Conversion */
17 ADC_StartConversion();
18
19 while(1) { /* wait for interrupts */ }
20}
Красиво, не правда ли? Конечно, скорость работы с использованием такого “фрэймворка” будет ниже, чем без, но, как завещал Кнут – “premature optimization is the root of all evil”. Если будет совсем медленно, функции библиотеки всегда можно подменить своими.
Такая библиотека позволяет не только поднять скорость разработки, но и облегчает миграцию между процессорами.
Документация на библиотеку, хоть и doxygen’овская, но довольно хороша!
Настройка порта GPIO
Итак, с регистрами разобрались, настало время практики. Все примеры в этой статье для микроконтроллера STM32F103C8. В моем распоряжении есть вот такая отладочная плата:
На ней установлен кварцевый резонатор на 8 МГц и светодиод на порту PB12. Вот с помощью этого светодиода мы и устроим Hello, World!
Задача ясна: настраиваем PB12 на выход в режиме push-pull и с помощью регистра ODR дергаем 12-й пин порта GPIOB туда-сюда! Но мы забыли об одной маленько детали: RCC. Дело в том, что по-умолчанию после сброса микроконтроллера все периферийные модули отключены от источника тактового сигнала, в том числе и GPIO. А подать тактирование можно с помощью регистров RCC. В 3-ей части я про это говорил. Для начала нужно определить, к какой шине у нас подключен GPIOB. Открываем даташит на микроконтроллер, ищем вот эту таблицу:
Рис. 8. Таблица шин и периферийных устройств
GPIOB у нас подключен к шине APB2. Идем в Reference manual, открываем раздел про RCC, переходим к пункту 7.3.7 APB2 peripheral clock enable register (RCC_APB2ENR). С помощью этого регистра можно подать тактовый сигнал на устройства шины APB2:
Рис. 9. Регистр RCC_APB2ENR
В регистре RCC_APB2ENR много флагов для разной периферии, в том числе и для нашего GPIOB, флаг называется IOPBEN. Перед началом инициализации PB12 нам надо установить этот бит в единицу.
Поехали программировать! За основу возьмем проект из 2-й части: https://github.com/DiMoonElec/stm32f103c8_empty_project. Создадим функцию инициализации порта:
void PortInit(void) { }
GPIOB
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //Включаем тактирование порта GPIOB
PB12CRH:
GPIOB->CRH &= ~(GPIO_CRH_MODE12 | GPIO_CRH_CNF12); //для начала все сбрасываем в ноль //MODE: выход с максимальной частотой 2 МГц //CNF: режим push-pull GPIOB->CRH |= (0x02 << GPIO_CRH_MODE12_Pos) | (0x00 << GPIO_CRH_CNF12_Pos);
void PortInit(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //Включаем тактирование порта GPIOB GPIOB->CRH &= ~(GPIO_CRH_MODE12 | GPIO_CRH_CNF12); //для начала все сбрасываем в ноль //MODE: выход с максимальной частотой 2 МГц //CNF: режим push-pull GPIOB->CRH |= (0x02 << GPIO_CRH_MODE12_Pos) | (0x00 << GPIO_CRH_CNF12_Pos); }
ODRPB12
void PortSetHi(void) { GPIOB->ODR |= (1<<12); }
void PortSetLow(void) { GPIOB->ODR &= ~(1<<12); }
GPIOB->ODR |= (1<<12)STM32
void PortSetHi(void) { GPIOB->BSRR = (1<<12); } void PortSetLow(void) { GPIOB->BRR = (1<<12); }
(1<<12)0x1000BSRRBRRрис. 5, 6
Ни и простой main() для проверки:
void main() { int i; PortInit(); for(;;) { PortSetHi(); for(i=0; i<0x40000; i++) ; PortSetLow(); for(i=0; i<0x40000; i++) ; } }
BP12«Hello, World!»
Давайте теперь настроим какой-нибудь вывод порта, например PB15, на вход с подтяжкой к питанию. При подключении PB15 к минусу, у нас будет зажигаться светодиод. Задача ясна, преступаем к реализации. В PortInit() добавим пару строк:
/// Настраиваем PB15 на вход с подтяжкой к питанию /// GPIOB->CRH &= ~(GPIO_CRH_MODE15 | GPIO_CRH_CNF15); //MODE: вход, оставляем в нуле //CNF: вход с pull-up / pull-down GPIOB->CRH |= (0x00 << GPIO_CRH_MODE15_Pos) | (0x02 << GPIO_CRH_CNF15_Pos); GPIOB->ODR |= (1<<15); //Включаем подтяжку вверх
PB12MODE/CNFODRODRCNF=10Input with pull-up / pull-downODRReference manual
Рис. 10. Таблица конфигурации порта
Функция PortInit() приобретает такой вид:
void PortInit(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //Включаем тактирование порта GPIOB /// Настраиваем PB12 на выход /// GPIOB->CRH &= ~(GPIO_CRH_MODE12 | GPIO_CRH_CNF12); //для начала все сбрасываем в ноль //MODE: выход с максимальной частотой 2 МГц //CNF: режим push-pull GPIOB->CRH |= (0x02 << GPIO_CRH_MODE12_Pos) | (0x00 << GPIO_CRH_CNF12_Pos); /// Настраиваем PB15 на вход с подтяжкой к питанию /// GPIOB->CRH &= ~(GPIO_CRH_MODE15 | GPIO_CRH_CNF15); //MODE: вход, оставляем в нуле //CNF: вход с pull-up / pull-down GPIOB->CRH |= (0x00 << GPIO_CRH_MODE15_Pos) | (0x02 << GPIO_CRH_CNF15_Pos); GPIOB->ODR |= (1<<15); //Включаем подтяжку вверх }
PB15IDR
int ReadPort(void) { if(GPIOB->IDR & (1<<15)) return 1; return 0; }
IDR
В этом случае main() будет выглядеть вот так:
void main() { PortInit(); for(;;) { if(ReadPort()) PortSetHi(); else PortSetLow(); } }
stm32f103c8PB12PB15PP12PB15PB15ReadPort()PB12
На этом все, продолжение следует! Продолжение.
Setting up toolchain
The biggest downside is that STM8 processors are not supported by GCC. There are 3 commercial compilers available for these processors: Raisonance, Cosmic and IAR. Some of these compilers have free versions with code size limit, but none of them are available for linux. Luckily, SDCC supports STM8 and that’s what we’re going to use. SDCC is being actively developed, so I suggest trying the latest snapshot build instead of the stable version. To program the microcontroller we’ll be using stm8flash. The first step is to download all the necessary tools:
- sdcc
- stm8flash
Extract SDCC under ~/local/sdcc. Now extract stm8flash, build it with and copy stm8flash binary to ~/local/sdcc/bin. I prefer to keep flasher with compiler for convenience. Next, add the following line to your .bashrc file (replacing username with your user name):
1 |
export PATH=$PATH:/home/username/local/sdcc |
If everything was done properly, you should be able to run . The last remaining thing is to write udev rule for ST-Link programmer. Create a file :
123 |
# ST-Link v1/v2ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="0666"ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="0666" |
Finally, run as root. Now we’re all set and ready to start.
Регистры CR и CFGR
Открываем Reference manual на микроконтроллер STM32F103x8 и переходим к разделу 7: Low-, medium-, high- and XL-density reset and clock control (RCC). RCC имеет довольно много регистров, целых 10 штук. Однако, для настройки источника тактирования и делителей шин нам понадобится только 2 из них.
Clock control register (RCC_CR)
Рис. 1. Биты регистра CR
Описание основных битов регистра:
PLLRDY — флаг готовности PLL. Устанавливается аппаратно и сигнализирует о том, что PLL заблокирован.
PLLON — Включить PLL. Устанавливается и сбрасывается программно. При переходе в режим Stop или Standby сбрасывается аппаратно. Этот бит не может быть сброшен, если PLL используется как источник системного тактирования.
CSSON — включить систему CSS
HSEBYP — Если вместо кварцевого резонатора HSE мы хотим использовать внешний прямоугольный тактовый сигнал, то этот бит нужно установить в 1
HSERDY — Флаг готовности генератора HSE. Аппаратно устанавливается в 1 после успешного запуска и стабилизации частоты HSE-генератора
HSEON — Запустить HSE генератор. Устанавливается и сбрасывается программно. При переходе в режим Stop или Standby сбрасывается аппаратно и HSE генератор останавливается. Этот бит не может быть сброшен, если HSE используется как источник системного тактирования.
HSIRDY — то же самое, что и HSERDY, только для встроенного RC-генератора HSI
HSION — то же самое, что и HSEON, только для встроенного RC-генератора HSI
Clock configuration register (RCC_CFGR)
Рис. 2. Биты регистра CFGR
Описание основных битов регистра:
MCO — подача тактового сигнала на MCO-пин микроконтроллера.
- 0xx: Функция отключена
- 100: Выбран System clock (SYSCLK)
- 101: Выбран сигнал с HSI
- 110: Выбран сигнал с HSE
- 111: Выбран сигнал с PLL, который поделен на 2
PLLMUL — коэффициент умножения PLL. Эти биты могут быть записаны программно только при отключенном PLL
- 0000: Входную частота PLL умножить на 2
- 0001: —//— на 3
- 0010: —//— на 4
- 0011: —//— на 5
- 0100: —//— на 6
- 0101: —//— на 7
- 0110: —//— на 8
- 0111: —//— на 9
- 1000: —//— на 10
- 1001: —//— на 11
- 1010: —//— на 12
- 1011: —//— на 13
- 1100: —//— на 14
- 1101: —//— на 15
- 1110: —//— на 16
- 1111: —//— на 16
Два последних значения соответствуют одинаковому коэффициенту умножения.
PLLXTPRE — Делитель частоты с HSE генератора перед подачей на PLL. Этот бит не может быть изменен, если PLL запущен. При установке в 1 частота HSE будет поделена на 2, если 0, то делитель отключен.
PLLSRC — Источник входной частоты PLL. Не может быть изменен, если PLL запущен.
- 0: частота HSI генератора поделенная на 2
- 1: частота HSE генератора. Делитель может быть выбран PLLXTPRE битом.
PPRE2 — Делитель шины APB2 prescaler
- 0xx: HCLK без деления
- 100: HCLK / 2
- 101: HCLK / 4
- 110: HCLK / 8
- 111: HCLK / 16
PPRE1 — Делитель шины APB1 prescaler. Частота шины APB1 не должна превышать 36 МГц.
- 0xx: HCLK без деления
- 100: HCLK / 2
- 101: HCLK / 4
- 110: HCLK / 8
- 111: HCLK / 16
HPRE — AHB prescaler
- 0xxx: SYSCLK без деления
- 1000: SYSCLK / 2
- 1001: SYSCLK / 4
- 1010: SYSCLK / 8
- 1011: SYSCLK / 16
- 1100: SYSCLK / 64
- 1101: SYSCLK / 128
- 1110: SYSCLK / 256
- 1111: SYSCLK / 512
SWS — Состояние переключателя тактирования системы. Устанавливается аппаратно и указывает на текущий источник тактирования.
- 00: HSI генератор используется как источник тактирования системы
- 01: HSE генератор используется как источник тактирования системы
- 10: PLL используется как источник тактирования системы
SW — Переключатель источника тактирования системы. Изменяется программно для выбора источника SYSCLK. Устанавливается аппаратно для принудительного переключения на HSI генератор переходе в режим Stop или Standby или в случае срыва генерации HSE, который используется в качестве источника SYSCLK (только если активна система CSS)
- 00: HSI выбран в качестве источника системного тактирования
- 01: HSE выбран в качестве источника системного тактирования
- 10: PLL выбран в качестве источника системного тактирования
First program
These are the two most important documents: datasheet and reference manual. We’ll use the datasheet for the pinout and register map. Everything else is present in the reference manual: peripheral operation, register description, etc. Let’s begin by opening the GPIO section of the reference manual and taking a closer look at PORTD registers.
These registers are pretty much self-explanatory but just in case, here’s a brief overview: is the direction register, which configures a pin as either an input or an output. After we configured we can use for writing or for reading pin state. Control registers and are used for configuring internal pull-ups, output speed and selecting between push-pull or pseudo open-drain.
First, let’s define a macro that we’ll use later on for register definitions. Base address for all the hardware registers is 0x5000 so we can hardcode that into our macro.
1 |
#define _SFR_(mem_addr) (*(volatile uint8_t *)(0x5000 + (mem_addr))) |
Now let’s try blinking an LED. For this task we need to define , and registers for PORTD. We also need a delay function.
1234567891011121314151617181920212223242526272829 |
#include <stdint.h>#define F_CPU 2000000UL#define _SFR_(mem_addr) (*(volatile uint8_t *)(0x5000 + (mem_addr)))#define PD_ODR _SFR_(0x0F)#define PD_DDR _SFR_(0x11)#define PD_CR1 _SFR_(0x12)#define LED_PIN 4 static inline void delay_ms(uint16_t ms) { uint32_t i; for (i = ; i < ((F_CPU / 18000UL) * ms); i++) __asm__("nop");} void main() { PD_DDR |= (1 << LED_PIN); PD_CR1 |= (1 << LED_PIN); while (1) { PD_ODR ^= (1 << LED_PIN); delay_ms(250); }} |
Save this in main.c and compile by running the following command:
1 |
sdcc -lstm8 -mstm8 --out-fmt-ihx --std-sdcc11 main.c |
Now attach st-link and flash the microcontroller.
1 |
stm8flash -c stlinkv2 -p stm8s003f3 -w main.ihx |
Congratulations! We’ve just written our first program from scratch.
Note: some of the STM8 pins are labeled with in the datasheet. These pins are ‘true’ open-drain and can only pull to ground. You should be extra careful when working with open-drain pins, since there are no protection diodes. I managed to accidentally blow PB5 by using it as a normal GPIO, which took me hours to figure out when my I2C code wasn’t working. One way of checking whether the pin is dead or not is by setting the multimeter in diode mode and measuring the voltage drop between the pin and ground — it should be roughly 0.7V in one direction.
Что еще?
Здесь мы не рассмотрели еще некоторые блоки системы тактирования, о которых хочется упомянуть.
Clock security system (CSS) — переводится примерно как «система безопасности тактирования». Если, при использовании генератора HSE в качестве источника тактового сигнала для SYSCLK или PLL, произойдет срыв генерации HSE, то CSS автоматически переключит всю систему на работу от встроенного RC-генератора HSI. Таким образом, если что-то случится с кварцем, система не зависнет намертво в неопределенном состоянии, а сможет выполнить какие-то действия, например, перевести объект управления в безопасное состояние (закрыть все вентили, отключить силовые установки, и т.д.)
Модуль часов реального времени RTC может тактироваться от встроенного LSI генератора на 40 КГц, от HSE через делитель на 128, либо от LSE с внешним кварцем на 32768 Гц. Источник тактовых импульсов выбирается с помощью RTCSEL.
Модуль USB получает тактовый сигнал от PLL, причем при частоте на выходе PLL равной 72 МГц есть возможность активировать USB Prescaler с коэффициентом деления 1.5 для получения необходимой частоты 48 МГц.
Microcontroller clock output (MCO) — вывод микроконтроллера, на который можно вывести частоту от одного из источников сигнала: SYSCLK, HSE, HSI либо сигнал с выхода PLL, поделенный пополам. Нужный источник выбирается с помощью битов MCO.
Pin number mappings
The Arduino environment uses its own pin numbering scheme independent from
the physical CPU pin numbers. Many Arduino sketches and libraries contain
hard-coded assumptions about the number of pins with special functions.
Ideally, all these numbers would be the same and all programs could be
compiled without changes.
Here I discuss some possible pin mapping
schemes and check how close we could get to the ideal mapping.
Unfortunatly, it turns out that a perfect mapping is not possible.
In the end I chose a simple geometric numbering for the square UFQFPN20
package starting with port pin PA1 and counting up from 0. This results in
this mapping:
sduino pin | STM8S103 CPU port pin |
---|---|
0-2 | PA1-PA3 (PA1 and PA2 only weak output drivers) |
3-4 | PB5-PB4 (reverse order) |
5-9 | PC3-PC7 |
10-15 | PD1-PD6 |
- serial: 14,15
- SPI: 2,7,8,9
- I2C: 3,4 (true open drain. can’t drive a high signal without an external
pull-up resistor) - Analog: 6,11,12,14,15
- PWM: 2,5,6,12 plus either only 13 or 7-9 but not 13 (via alternate mapping)
pros of this approach:
- Easy and logical for use on a breadboard
- Very clear and logical port pin ordering
- TX and RX would be the rarely used analog pin numbers A3/A4 at
the end of the analog pin number list - At least the analog pins are in data sheet order
cons of this approach:
- Analog pins are still scattered around
- All functions use totally different pin numbers than Arduino
I am still not really happy with this mapping. Instead of simplifing things
it only adds another layer of abstraction and confusion. To avoid this I
added definitions for the regular CPU pin names like and . In the
end, this notation seems to be a lot easier to me. I am open for suggestions
for a better pin number mapping.
The chosen pin mapping for the STM8S103 (possible alternate function in
paratheses):
Phys. STM8 pin | Name | Functions | Geometrical mapping | special funcion |
---|---|---|---|---|
1 | PD4 | UART_CLK/T2-1/beep | 13 | PWM |
2 | PD5 | TX/Ain5 | 14 | Analog A3 |
3 | PD6 | RX/Ain6 | 15 | Analog A4 |
5 | PA1 | (OscIn, no HS) | ||
6 | PA2 | (OscIn, no HS) | 1 | |
10 | PA3 | SS/T2-3 | 2 | PWM |
11 | PB5 | SDA LED | 3 | |
12 | PB4 | SCL | 4 | |
13 | PC3 | T1-3/ | 5 | PWM, (n~) |
14 | PC4 | T1-4/Ain2/ | 6 | PWM, Analog A0, (n~) |
15 | PC5 | SCK/ | 7 | (~) |
16 | PC6 | MOSI/ | 8 | (~) |
17 | PC7 | MISO/ | 9 | (~) |
18 | PD1 | (SWIM) | 10 | |
19 | PD2 | Ain3/ | 11 | Analog A1, (~~) |
20 | PD3 | Ain4/T2-2 | 12 | PWM, Analog A2 |
Putting it all together
We have enough building blocks — now it’s time to put them together into some ‘real-world’ application. For this demo I picked up MMA8452 3-axis I2C accelerometer and a standard HD44780 1602 LCD, which is extremely popular among electronics enthusiasts for some reason.
The demo application will calculate inclination angle based on accelerometer readings and output it to the LCD. Calculating inclination angle will require some trigonometry and floating point arithmetic, which will consume a good amount of resources. Despite the floating point operations being quite slow, STM8 managed this task decently.
You might have noticed the lack of contrast adjustment potentiometer. The LCD module that I’m using is rated for 5V, however my setup uses 3.3V supply. I couldn’t be bothered with a separate supply for the display, so I cheated: the LCD is initialized in 1-line mode, which results in 1/8 duty cycle, and pin is tied to ground.
Programming Manual
Programming Manual не является документом первой необходимости в самом начале знакомства с STM-ми, однако является очень важным при углубленном изучении этих микроконтроллеров. Он содержит информацию о процессорном ядре, системе команд и периферии ядра. Причем это не та же самая периферия, которая описана в Reference manual-е. В нее входят:
- System timer — системный таймер
- Nested vectored interrupt controller — контроллер приоритетных прерываний
- System control block
- Memory protection unit
Как только мы начнем знакомится с прерываниями в STM32, нам понадобится раздел 4.3 Nested vectored interrupt controller (NVIC). Ну и системный таймер является очень прикольной вещью, который будет полезен в каких-нибудь RTOS или для создания программных таймеров.
Плюсы и минусы
Естественно, плюсы и минусы я оцениваю по применимости в моих проектах, для вас они могут отличаться в ту или иную сторону. Я буду сравнивать с AVR, потому, как на них многие уже скушали небольшую собачку.
Плюсы:
- Цена. Не смотря на мало распространенность, stm8 стоит по три копейки за ведро.
- Еще одна цена. Отладочные платы и отладчики стоят копейки. Можно забыть про всю ту ораву самопальных программаторов, что расплодились для AVR’ов. Также, можно забыть про программаторы без отладчиков – за минимальные деньги все включено.
- У stm8 в отличии от AVR нет фьюзов. И это меня очень радует. Теперь вся программа действительно содержится в одном hex файле. Ну согласитесь, фьюзы в AVR– чистейшее зло!
- Есть очень дешевые контроллеры с 12-битными АЦП и ЦАПами, и это – очень хорошо!
- Классный отладочный интерфейс. Задумка об отладке по одному проводу у AVR была хороша, но чтобы ее включить, приходилось подключать еще три. В итоге, JTAG был не намного хуже пресловутого debugWire. ST довела идею до логического завершения. Отладка по двум проводам. Супер!
- Работает от пяти вольт. Не знаю, можно ли это назвать достоинством в нынешнем мире, но олдфагам это точно понравится.
- Встроенный bootloader. Умеет загружать программы по uart, spi, can, i2c.
- На халяву дается библиотека драйверов периферии.
Недостатки:
- Нет контроллеров в маловыводных корпусах (типа so8).
- Нет контроллеров с USB. ST предлагает пересаживаться на ее кортексы, если нужен USB.
- Не слишком пока распространены. Соответственно, и доставать сложно, и цены выше, чем могли бы быть.
Источники питания
STM32W108 содержит три системы источников питания. Всегда включенный высоковольтный источник питания обеспечивает работу GPIO и функционирование критических блоков микросхемы. Остальные блоки микросхемы питаются от низковольтных стабилизаторов. Низковольтные источники питания можно отключить при переходе в спящий режим, что дополнительно уменьшает энергопотребление. Внутренние стабилизаторы обеспечивают получение напряжений питания 1,25 В и 1,8 В из нерегулируемого напряжения питания микросхемы. Выход стабилизатора напряжения 1,8 В имеет внешний фильтр и может использоваться внешними аналоговыми блоками, RAM и flash-памятью. Выход стабилизатора напряжения 1,25 В имеет внешний фильтр и используется для питания ядра микропроцессора.
Режимы пониженного энергопотребления
STM32W108 имеет сверхнизкое энергопотребление в режиме глубокого сна с возможностью выбора способа тактирования. Таймер выхода из состояния бездействия можно тактировать или от внешнего кварцевого резонатора на частоту 32,768 кГц, или от сигнала частотой 1 кГц, полученного делением частоты 10 кГц от внутреннего RC-генератора. Для режима с наименьшим энергопотреблением все тактовые генераторы можно выключить, т.к. микросхема будет пробуждаться только внешними событиями с выводов GPIO. STM32W108 обладает быстрым временем пробуждения (типичное значение — 100 мкс) из состояния глубокого сна до момента выполнения первой инструкции ARM Cortex-M3.
Средства разработки и отладки
Для создания приложений на базе STM32W108 можно использовать широкий набор сред разработки и отладки, а также операционных систем реального времени (OS и RTOS), предназначенных для работы с ARM-микроконтроллерами, и предлагаемых многими ведущими производителями программного и аппаратного обеспечения. Для создания прикладных программ для STM32W108 можно использовать интегрированную среду разработки Keil RealView Microcontroller Development Kit (MDK) совместно с семейством USB-JTAG адаптеров Keil ULINK или IAR Embedded Workbench for ARM совместно с адаптером IAR J-Trace for Cortex-M3.
Отличительной особенностью STM32W108 является наличие аппаратной поддержки модуля трассировки пакетов, который обеспечивает многоуровневую отладку на уровне пакетов. Этот блок является необходимым компонентом для интегрированной среды разработки InSight Desktop компании Ember и при использовании специального адаптера InSight компании Ember обеспечивает возможность расширенной сетевой отладки.