
GPIO Extender-F: руководство по Forth
Руководство GPIO Extender-F на Mecrisp-Stellaris: подключение, распиновка, оперативная и флеш-память, GPIO, АЦП, ШИМ и таймеры.
GPIO Extender-F — мини-контроллер на STM32F042 с интерактивным Mecrisp-Stellaris Forth. Команды и определения вводятся через USB CDC и выполняются сразу: программу можно отладить в оперативной памяти, а готовую версию сохранить во флеш-памяти.
Характеристики
| Параметр | Значение |
|---|---|
| Микроконтроллер | STM32F042, ARM Cortex-M0 |
| Тактовая частота | 48 МГц |
| Интерфейс | USB CDC, виртуальный COM-порт |
| Питание | USB 5 В |
| Управляемые выводы | 10 GPIO |
| АЦП (ADC) | 8 выводов |
| ШИМ (PWM) | 4 канала TIM2 |
| Флеш-память | 32 КБ, пользовательскому коду доступно около 7 КБ |
| Габариты | 54 × 15 × 10 мм |
Первый запуск
- Подключите контроллер к USB.
- Откройте появившийся порт в PuTTY, TeraTerm, Minicom,
screenилиpyserial-miniterm. - Нажмите Enter. В терминале должно появиться приглашение Forth и
ok.. - Проверьте интерпретатор выражением
2 3 + .: результат должен быть5.
В Forth операнды сначала помещаются в стек, а операция снимает их со стека и
возвращает результат. Слова разделяются пробелами; новое слово определяется
между : и ;.
2 3 + . \ сложение и вывод результата
: double 2 * ; \ новое слово
5 double . \ результат: 10
Распиновка
| Контакт | Алиас | STM32 | Функции |
|---|---|---|---|
| 1 | IO1 | PA4 | GPIO, АЦП |
| 2 | IO2 | PA2 | GPIO, ШИМ TIM2 CH3, АЦП |
| 3 | IO3 | PA0 | GPIO, ШИМ TIM2 CH1, АЦП |
| 4 | IO4 | PA7 | GPIO, АЦП |
| 5 | IO5 | PA6 | GPIO, АЦП |
| 6 | IO6 | PA3 | GPIO, ШИМ TIM2 CH4, АЦП |
| 7 | IO7 | PA1 | GPIO, ШИМ TIM2 CH2, АЦП |
| 8 | IO8 | PA13 | GPIO |
| 9 | IO9 | PB1 | GPIO, АЦП |
| 10 | IO10 | PA14 | GPIO |
| — | LED1 | PF0 | встроенный светодиод |
| — | LED2 | PF1 | встроенный светодиод |
GPIO работают с логическими уровнями 3,3 В. Не подключайте двигатель, лампу, соленоид или катушку реле непосредственно к выводу.
Оперативная и флеш-память
Во время разработки компилируйте слова в оперативную память: их можно быстро менять, а после перезагрузки они исчезнут. Когда программа проверена, переключитесь на флеш-память и повторно отправьте окончательный исходный текст. Переключение режима само по себе не переносит уже скомпилированные слова.
compiletoram \ новые слова будут находиться в оперативной памяти
compiletoflash \ новые слова будут записываться во флеш-память
eraseflash \ удалить пользовательский код из флеш-памяти
Сохраните исходный текст на компьютере до eraseflash. Для точки возврата
можно создать cornerstone во флеш-памяти:
compiletoflash
: basic_image
begin here dup flash-pagesize 1- and while 0 h, repeat
does> begin dup dup flash-pagesize 1- and while 2+ repeat
cr eraseflashfrom ;
Вызов basic_image удалит определения, созданные после этой точки.
GPIO
OMODE-PP IO3 io-mode! \ двухтактный выход
IMODE-HIGH IO7 io-mode! \ вход с подтяжкой вверх
IMODE-LOW IO2 io-mode! \ вход с подтяжкой вниз
IMODE-ADC IO6 io-mode! \ аналоговый вход
1 IO3 io! \ высокий уровень
0 IO3 io! \ низкий уровень
IO3 iox! \ инвертировать выход
IO7 io@ . \ прочитать вход
Пример ожидания кнопки между IO7 и GND:
: wait-button
IMODE-HIGH IO7 io-mode!
begin IO7 io@ 0= until
." Кнопка нажата!" ;
АЦП (ADC)
Если adc-init, adc-deinit, adc-once и adc отсутствуют в списке words,
сначала выполните приведённые ниже определения:
: adc-calib ( -- )
31 bit ADC-CR bis!
begin 31 bit ADC-CR bit@ 0= until ;
: adc-once ( -- u )
2 bit ADC-CR bis!
begin 2 bit ADC-ISR bit@ until
ADC-DR @ ;
: adc-init ( -- )
9 bit $40021018 bis! \ включить тактирование ADC
adc-calib
1 ADC-CR !
adc-once drop ;
: adc-deinit ( -- )
1 bit ADC-CR bis!
9 bit $40021018 bic! ;
: adc ( pin -- u )
io# bit ADC-CHSELR !
adc-once drop adc-once ;
После этого переведите вывод в аналоговый режим и включите АЦП. Необработанное
значение лежит в диапазоне 0…4095; adc-mv возвращает милливольты.
adc-init
IMODE-ADC IO3 io-mode!
IO3 adc . \ сырое значение
IO3 adc-mv . \ милливольты
adc-temp . \ температура кристалла
adc-deinit
Пример отдельного слова:
: check-voltage
IMODE-ADC IO1 io-mode!
adc-init
." Напряжение на IO1: " IO1 adc-mv . ." мВ" cr
adc-deinit ;
ШИМ (PWM)
ШИМ доступна на IO3/PA0, IO7/PA1, IO2/PA2 и IO6/PA3. Если слов
pwm-init и pwm нет в words, выполните приведённые ниже определения:
: timer-base ( n -- addr )
drop $40000000 ;
: timer-enabit ( n -- bit addr )
drop 0 bit RCC RCC_APB1ENR_OFFSET + ;
: timer-init ( u n -- )
dup timer-enabit bis!
timer-base >r
dup 16 rshift TIM.PSC r@ + !
$FFFF and TIM.ARR r@ + !
8 bit TIM.DIER r@ + bis!
%010 4 lshift TIM.CR2 r@ + !
0 bit TIM.CR1 r@ + bis!
r> drop ;
: timer-deinit ( n -- )
timer-enabit bic! ;
: p2tim ( pin -- n ) drop 2 ;
: p2cmp ( pin -- n ) $3 and ;
: pin-af2 ( pin -- )
dup PA0 = if
GPIO-BASE GPIO.AFRL + dup @
$FFFFFFF0 and 2 or swap !
else dup PA1 = if
GPIO-BASE GPIO.AFRL + dup @
$FFFFF0FF and 2 4 lshift or swap !
else dup PA2 = if
GPIO-BASE GPIO.AFRL + dup @
$FFFF0FFF and 2 8 lshift or swap !
else dup PA3 = if
GPIO-BASE GPIO.AFRL + dup @
$FFF0FFFF and 2 12 lshift or swap !
then then then then drop ;
: pwm-init ( hz pin -- )
>r
OMODE-AF-PP r@ io-mode!
r@ pin-af2
48000000 swap /
dup 65536 > if
dup 65536 / 1+
dup 1- >r
/ 1-
r> swap
else
0 swap 1-
then
swap 16 lshift or
r@ p2tim timer-init
r@ p2cmp dup 2 < if
2 * 8 * $68 swap lshift
r@ p2tim timer-base TIM.CCMR1 + bis!
else
2 - 2 * 8 * $68 swap lshift
r@ p2tim timer-base TIM.CCMR2 + bis!
then
r@ p2cmp 4 * bit r> p2tim timer-base TIM.CCER + bis! ;
: pwm ( u pin -- )
>r
r@ p2tim timer-base TIM.ARR + @
1+ swap 10000 */
r@ p2cmp cells
r> p2tim timer-base $34 + + ! ;
Частота pwm-init задаётся в герцах, заполнение pwm — числом от 0 до
10000.
1000 IO3 pwm-init \ частота 1000 Гц
5000 IO3 pwm \ заполнение 50 %
: led-fade
1000 IO3 pwm-init
10 0 do
i 1000 * IO3 pwm
500 ms-delay
loop
0 IO3 pwm ;
Все четыре ШИМ-вывода используют TIM2. При одновременной работе нескольких каналов задавайте одну и ту же частоту:
: multi-pwm-test
1000 IO3 pwm-init
1000 IO7 pwm-init
1000 IO2 pwm-init
1000 IO6 pwm-init
2500 IO3 pwm
5000 IO7 pwm
7500 IO2 pwm
9000 IO6 pwm ;
Системный и сторожевой таймеры
systick-init
ms_tick_cnt @ .
: measure-time
systick-init
ms_tick_cnt @
1000 0 do loop
ms_tick_cnt @ swap -
." Время выполнения: " . ." мс" ;
IWDG должен обновляться чаще заданного тайм-аута:
1000 iwdg-init-timeout
iwdg-refresh
: safe-loop
1000 iwdg-init-timeout
begin
." Работаю... " cr
500 ms-delay
iwdg-refresh
again ;
После запуска IWDG остановить его программно нельзя; сначала проверяйте цикл в оперативной памяти и держите исходник сохранённым на компьютере.
Пользовательские настройки во флеш-памяти
Последняя страница флеш-памяти зарезервирована под настройки по адресу
0x08007c00. Не размещайте там пользовательский код, если планируете хранить
настройки. Запись во флеш-память имеет ограниченный ресурс, поэтому не
выполняйте её в каждом проходе цикла.
$08007c00 constant SETTINGS_PAGE
: settings-write ( value addr -- )
SETTINGS_PAGE +
2dup h@ = if
2drop
else
$08000000 - hflash!
then ;
: settings-read ( addr -- value )
SETTINGS_PAGE + h@ ;
: settings-erase ( -- )
SETTINGS_PAGE $08000000 - flashpageerase ;
Пример сохранения двух значений:
0 constant CFG_PWM_FREQ
2 constant CFG_ADC_THRESH
: save-config ( pwm-freq adc-thresh -- )
settings-erase
CFG_ADC_THRESH settings-write
CFG_PWM_FREQ settings-write ;
: load-config
CFG_PWM_FREQ settings-read
CFG_ADC_THRESH settings-read ;
Готовые примеры
Мигание встроенным светодиодом:
: blink
10 0 do
1 LED1 io!
500 ms-delay
0 LED1 io!
500 ms-delay
loop ;
Управление стандартным сервоприводом с ШИМ 50 Гц:
: servo-init
50 IO3 pwm-init ;
: servo-set ( angle -- )
180 min 0 max
500 * 180 /
500 +
IO3 pwm ;
: servo-test
servo-init
0 servo-set 1000 ms-delay
90 servo-set 1000 ms-delay
180 servo-set 1000 ms-delay
90 servo-set ;
Здесь углу 0…180° соответствует импульс 1…2 мс: при частоте 50 Гц это
5…10 % периода, или 500…1000 в шкале команды pwm. Не расширяйте диапазон
без проверки документации конкретного сервопривода.
Перед подключением сервопривода используйте отдельный источник питания, рассчитанный на его пусковой ток, и объедините GND источника с GND контроллера.
Пороговый сигнал по АЦП:
: threshold-alert
IMODE-ADC IO4 io-mode!
OMODE-PP IO7 io-mode!
adc-init
begin
IO4 adc-mv dup . ." мВ "
2000 > if
." ТРЕВОГА!" cr 1 IO7 io!
else
cr 0 IO7 io!
then
500 ms-delay
key? until
adc-deinit ;
Идентификаторы микроконтроллера и объём флеш-памяти:
: show-device-info
." Chip ID: " chipid drop drop drop .
." Hardware ID: " hwid .
." Flash size: " flash-kb . ." KB" ;
Ограничения
- При автономной работе обеспечьте стабильное питание 5 В. При пропадании USB или переходе компьютера в спящий режим USB-периферия может быть приостановлена.
- ШИМ доступна только на четырёх выводах TIM2, перечисленных выше.
- Перед записью во флеш-память полностью проверьте программу в оперативной памяти и сохраните исходник на компьютере.
- Слова могут различаться между версиями прошивки. Если команда из примера не
определена, проверьте список слов командой
wordsи обратитесь в поддержку, указав версию устройства.