На правах заметки.
Intro
В народе этот чип называют “клоном” Atmega328P или “антикризисным Arduino” (ну не сам чип, а те платки, которые доступны на AliExpress).
Даташит смотреть в разделе “Полезные ссылки и документация”.
Клоном оно не является. Это самобытная разработка, которая в некотором отношение по пинам (в некоторых режимах) совместима ATmega328P. При этом, если, к примеру, плату с Али зашить обычным примером я миганием светодиода, собранным для BSP Arduino Nano, то диод будет мигать неадекватно. Т.е. для этого контроллера нужно свой пакет BSP, как, к примеру, для совсем “левых” контроллеров, типа ESP32.
Т.е. из схожего:
- система комманд и ассемблер, тулчейн
- корпус и совместимость пинов, при этом, LGT8F328 может заменить 328 мегу, то обратная замена не всегда возможна (далее).
Основные особенности LGT8F328P:
- Питание от 1.8-5.5В для всех частот
- Максимальная частота на внутренней RC цепочке и внешнем кварце до 32Mhz
- Нет фьюзов, как следствие, все настройки периферии нужно делать в стартовом коде, аналогично “взрослым” контроллерам. Отсюда и необходимость в отдельном “ядре” (BSP - Board Support Package из “взрослой” терминологии) для Arduino IDE.
- Особенности BSP для Arduino IDE, что прошивается только на 57кбод.
- Дополнительный третий 16 битный таймер. И все таймеры существенно проапргейжены в плане максимальных частот PWM и числа ног с PWM.
- Появился ЦАП
- АЦП тут уже 12 битный, а не 10 битный. Хотя, по отзывам, реальная точность осталась в районе 10 бит
- Нет EEPROM. Но он может программно эмулироваться на внутреннем флеше. Т.е. - больше EEPROM - меньше на код.
Хорошее ревью с примерами кода: Обзор клона меги328 -LGT8F328P
В общем, контроллер новый, самобытный. Для домашнего использования очень интересен, но для промышленного использования я бы поостерёгся использовать.
Для домашнего использования хорош и тем, что можно купить на Али версю платы Нано за ~115 рублей с бесплатной доставкой против 250 рублей за аналогичный Nano v3. Плюс платы с односторонним расположением элементов, что позволяет монтировать на плату в виде модуля.
Официальный тулинг
Статья: LGT8F328P Arduino совместимая плата. Программирование на чистом Си
Ну а инструмент называется: LGTSDK Builder
- Сайт (китайский язык)
- Скачать:
http://www.lgtic.com/upload/tools/lgtsdk_builder/LGTSDK_Builder_latest.rar
- Скачивания смотреть на странице: http://www.prodesign.com.cn/download/ или http://www.prodesign.com.cn/lgt8f328p/
Поддержка в Arduino IDE
Теперь про интеграцию в Arduino IDE. Как я писал выше - нужен свой BSP. Как минимум настройки для PLL и EEPROM при старте.
Я нашёл более-менее работающих два:
- https://github.com/dbuezas/LGT8fx
- https://github.com/nulllaborg/arduino_nulllab (альтернативный репозиторий: https://gitee.com/nulllab/nulllab_arduino)
Рекомендую ознакомиться так же со ссылками на страницах обоих BSP. Можно найти полезного.
LGT8fx
Рекомендую именно его на момент 2024.11.26 (актуальная версия: 2.0.7), до этого рекомендовал Nulllab
Ставим через Board Manager в Arduino IDE. В File → Preference, Settings tab добавляем:
https://raw.githubusercontent.com/dbuezas/lgt8fx/master/package_lgt8fx_index.json
На момент первоначального составления заметки была актуальна версия 1.0.5 (оригинальный BSP LGT8fx выглядел заброшенным.) и была доступна неофициальная 1.0.6 (ака v1.0.7 pre release), которая:
- Работает с платами с внешним 16Mhz кварцем
- Реализуют классический Arduino интерфейс для работы с EEPROM.
Естественно ставить её нужно было вручную. Сейчас же (2023.06.23) актуальная версия - 2.0.6, уже содержит вышеупомянутые доработки.
Для установки в Board Manager вводим:
gt8fx
И ставим “LGT8fx Boards”
В Tools → Board → LGT8fx Board выбираем единственную (2023.06.25) борду: LGT8F328. Собственно на ней и собраны популярные “клоны” Ardunio Nano и Arduino Pro Mini.
После этого выбираем в Tools → Variants выбираем:
- 328P-LQFP32 - для большинства клонов в форм-факторе Arduino Pro Mini и Arduino Nano Ну или посчитайте ножки :)
Из настроек полезные, по сути, только частота работы и что используется: внутренний клок или внешний кварц.
Внешний кварц понятен, есть три варианта (Tools → Clock Source):
- External 12Mhz
- External 16Mhz
- External 32Mhz
Внутренний клок всегда один (там же, Tools → Clock Source):
- Internal 32Mhz
А вот нужную частоту работы уже догоняем делителями (Tools → Clock Divider): 1, 2, 4, 8, 16, 32
Я не разбирался, работают ли делители, при выборе внешнего кварца, но для внутреннего клока они точно работают.
Следующие настройки, скорее всего, никогда не придётся менять:
- Upload Speed: 57600, при другой у меня ничего не прошивалось, но зависит от прошитого FSBL (aka просто загрузчик, позволяющий обновляться по UART).
- SERIAL_RX_BUFFER_SIZE: 64, скорее всего сделано как какой-то WA. Не вникал.
Настроек для размера EEPROM нет, он есть всегда и его размер - 1 кБ. Если нужна гибкость в настройке - используйте Nulllab BSP,
Ну и стоит отдельно упомянуть, что этот BSP - это развитие “официального” оного: https://github.com/LGTMCU/Larduino_HSP. Можете и его попробовать. В некоторых источниках есть и на него ссылка.
Nulllab
В целом можно и его рекомендовать: широкий набор источников клока, делителей (косвенно, через указание конкретной частоты) и возможность настройки EEPROM. Но LGT8fx Boards очень оживился, а этот как был версией 1.0.3 на момент составления заметки (2022.12.04), так и остался на момент правки (2023.06.25).
Ставим через Board Manager в Arduino IDE. В File → Preference, Settings tab добавляем:
https://raw.githubusercontent.com/nulllaborg/arduino_nulllab/master/package_nulllab_boards_index.json
Nullab в Board Manager ищется по словам… nulllab :-) При выборе борды нужно выбрать:
- Tools → Board → Nulllab AVR Compatible Board → DIY Board
При этом станет доступен полный “тюниг” для всех борд:
- Tools → CPU Frequency: 16 Mhz
- Tools → Clock Source: External (16 Mhz)
- Tools → EEPROM size: от 0 до 8кБ с шагом x2
- Tools → Upload Speed: 57600 - это важно, иначе не будет шиться (см выше)
Как и LGT8fx Boards - это развитие “официального” BSP: https://github.com/LGTMCU/Larduino_HSP.
Покупка
Естественно - Aliexpress. Я брал:
- Nano + TypeC:
https://aliexpress.ru/item/1005004234919226.html, на момент составлении заметки - ~118руб
- в этой версии платы на RX/TX нет LED и они не мешают работе PWM на Timer3 / OC3A (используется D1, он же RX). Но ни в коем случае нельзя включать аппратный Serial при включенном PWM.
- Pro Mini:
https://aliexpress.ru/item/33003833124.html
- тут две версии под 3.3В и 5В, плюс отдельно сам контроллер
- цена на момент заметки: ~63 руб за 5В версию. 3.3В версия чуть дороже
- UNO: TBD пока сам ищу. Ниже варианты, не проверенные:
- https://aliexpress.ru/item/1005004833260461.html UNO R3 ~300руб плюс доставка примерно столько же.
- имхо, проще “оригинал” купить:
- https://aliexpress.ru/item/32556087234.html - 233+50 руб
- https://aliexpress.ru/item/32932088536.html - 207+55 руб
Полезные ссылки, обсуждения и документация
- Упомянутый выше: Обзор клона меги328 -LGT8F328P
-
LGT8F328p. Начало работы, особенности
- Даташиты (лежат на Я.Д могут протухнуть в любой момент, поэтому пишу и имена файлов, что бы потом поискать на машине времени)
- Даташит, серия P (RU) - LGT8FxxxP.pdf
- Даташит, серия D (RU) - LGT8FxxxD.pdf
- Даташит 1.0.4 (EN) - Databook
- Даташит 1.0.5 (EN) - Databook
- Характеристики и отличия
- Видео обзор: https://www.youtube.com/watch?v=Mk8YXS1tkhI
- Даташиты (лежат на Я.Д могут протухнуть в любой момент, поэтому пишу и имена файлов, что бы потом поискать на машине времени)
- На Amperka.ru:
https://amperka.ru/product/chip-lgt8f328p
- Даташит: https://storage.googleapis.com/media.amperka.com/products/chip-lgt8f328p/media/lgt8f328p-datasheet.pdf
- Рекомендует ставить оригинальный BSP, чего делать не нужно. Или использовать его для проектов вне среды Arduino.
- На странице BSP от dbuezas хорошая подборка документации:
-
https://hallroad.org/lgt8f328p-lqfp32-minievb-alternative-arduino-nano-v3.0-atmega328p.html
- тоже рекомендуют оригинальный BSP.
Табличка, где сравнивается скорость выполнения в тактах некоторых ассемблерных команд в обычном AVR и в LGT8 (по данным по ссылке 1):
Instruction Function Cycle of AVR Cycle of LGT8XM
ADIW Add immediate to word 2 1
SBIW Subtract immediate to word 2 1
MUL/S/SU 8bit multiply 2 1
FMUL/S/SU Fractional multiply 2 1
RJMP/RCALL Relative jump/call 2/3 1
IJMP/ICALL Indirect jump/call 2/3 2
RET/IRET Return 4 2
CPSE Compare, skip if equal 1/2/3 1/2
SBIS/SBRS Skip if set 1/2/3 1/2
SBIC/SBRC Skip if cleared 1/2/3 1/2
LD/LDD Load indirect 2 1
ST/STD Store indirect 2 1
LPM Load program memory 3 2
PUSH/POP Stack access 2 1
Другие MCU от LGT в платах Arduino и их сравнения:
Pinout
Schematic
LGT8F328P MiniEVB
Качество шакальное, но нашёл только тут скачивал через тут. Оба два ресурса - через VPN или Tor.
Code snippets
Определение в коде, что строимся для LGT8fx
- LGT8fx Boards BSP и Nulllab BSP, определены макросы:
- Все “P” (например - 328P) платы:
__LGT8FX8P__
__LGT8F__
- LQFP48:
__LGT8FX8P48__
- SSOP20:
__LGT8F_SSOP20__
- Прочее: смотреть в
ARDUINO_DIR/packages/BSP/hardware/avr/VERSION/variants/XXX/pins_arduino.h
- Все “P” (например - 328P) платы:
GUID
В каждом чипе прошит уникальный GUID (aka Serial Number). Может использоваться для расшифровки/кодирования чего-то
uint32_t guid = (uint32_t)&GUID0;
Вывод тактовой на ногу PB0
CLKPR = 1<<PMCE; //разрешить изменение
CLKPR = 1<<5 | 1<<0; //делитель =2 и вывод clk
Переключение тактирования на кварц
sysClock(EXT_OSC);
CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = 1<<5; // вывод clk
Тактирование от внешнего генератора 32MHz
#include "lgtx8p.h"
int main(){
PMCR=1<<PMCE; //разрешить выбор источника тактирования
PMCR= 1<<2 | 1<<5; //External high frequency crystal
PMX2= 1<<WCE;//разрешить изменения
PMX2= 1<<XIEN;//разрешить вход тактовой частоты от кварц. генератора
CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = 1<<5; //делитель =1 и вывод clk
}
ЦАП. Вывод пилы
#include "lgtx8p.h"
void setup() {
DACON= 1<<DACEN | 1<<DAOE ; // dac-on, включить пин
static uint8_t n=0;
cli();
while(1){ DAL0=n++; }
}
void loop() {}
Пример задействования ног SWC,SWD,ADC6,ADC7,AREF - их можно сделать выходами порта E
#include "lgtx8p.h"
void setup() {
PMX2= 1<<WCE;
PMX2= 1<<E6EN; //сделеть AREF ногой PE6
MCUSR&= ~(1<<7);
MCUSR|= 1<<7;// Освободить PE0,PE2 от SWD
//ноги SWC=PE0,ADC6=PE1,SWD=PE2, ADC7=PE3,AREF=PE6
DDRE= 1<<0 | 1<<1 | 1<<2 | 1<<3 | 1<<6 ;
Пример ногодрыга с переключением клоков на тактовую 32МГц
int main(){
CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = 0; //делитель =1
DDRB = 1<<4; // 12 пин OUTPUT
while (1){ PINB=0x10; }
}
Тест на наличие таймера3 -при 16МГц тактовой светодиод Тх замигает с частотой примерно 5Герц
int main() {
*(uint8_t*)0x33 =0x2 ;// DDRF=1<<DDF1
*(uint8_t*)0x90 =0x40; // TCCR3A=1<<COM3A0;
*(uint8_t*)0x91 =0xD; // TCCR3B=1<<WGM32 | 1<<CS30 |1<<CS32;
*(uint8_t*)0x99 =0x5; // OCR3AH=0x5;
*(uint8_t*)0x98 =0xDC; // OCR3AL=0xDC;
Можно перенести Rx и Tx (оба одновременно или только какой то один) на другие пины
PMX0= 1<<7;//разрешить ремаппинг
PMX0= (1<<RXD5) |( 1<<TXD6) ;
Нужно, так как на этой плате неправильно разведён USART. Обмен данными возможен только между мк и usb-мостом. Какой-либо внешний сериальный сигнал подать нет возможности, он просто не прожмёт линию, которую каждый чип и светодиоды тянут вверх. Но выход есть, на помощь приходят регистры port multiplexing (PMX). Так что подключить bluetooth/GPS не проблема.
Так же отремаппить можно и выход таймера OC3A, который сидит на пине Txd, и так же страдает от резистора ( #286):
PMX0= 1<<7;//разрешить ремаппинг
PMX1= (1<<C3AC);
Цитата от сниппета:
Ловить на PD6, причём в данном режиме переводить PD6 в OUTPUT категорически запрещено, иначе будет к.з т.к. сигнал OC3A будет выводится не на сам PD6, а на запараллеленый ему физически вход компаратора. В общем там всё запутанно :)
ШИМ / PWM
У меня на таймере Timer3 не получилось получить ШИМ на ноге D1 (TX). После экспериментов там появился сигнал, но уровня 1.5В. Смотреть, также, предыдущий пункт про ремаппинг.
Предыдущий пункт про ремаппинг всё так же смотреть: вдруг пригодиться. На платах MiniEVB (см схему выше) цепь TX (D1) не притягивается никуда ничем, а с конвертером разделена резистором, так что ей ничего не мешает работать полноценно как таймер. В моём коде оказалась ошибка: не записывалось значение в регистр OC3A
. При этом, нужно деактивировать порт PD и активировать выход на PF:
// Для OC3A (D1)
DDRD &= ~(1u << DDD1);
DDRF |= (1u << DDF1);
// Для OC3B (D2)
DDRD &= ~(1u << DDD2);
DDRF |= (1u << DDF2);
Правда при этом мы лишаемся TX USART. Его можно перенести на другую ногу (см пинаут и предыдущий пункт), но там тоже нужный ШИМ.
А вот тут есть идея как запустить на A0/PC0, но не проверена:
Для настройки PWM онлайн:
Или отличная статья с деталями: LGT8F328P таймеры (Arduino). Тут всё по полочкам, по режимам.
Стоит отметить про Timer0: он используется для Millis по переполнению. Делитель там 64 (но завязываться на это не стоит). Соответственно мне нужен был делитель 1, а значит время от millis стало в 64 раза быстрее. Костыльно для задержек решил проблему так:
constexpr long ms(long val)
{
return val * 64;
}
constexpr unsigned long long int operator""_ms(unsigned long long int val) {
return val * 64; // we use divider 1 vs default divider 64 for timer0
}
void loop() {
static long tm = millis();
if (millis() - tm > 15_ms) {
...
}
if (millis() - tm > ms(some_val)) {
...
}
}
В идеале же нужно прочитать делитель при старте и заменить 64 на прочитанное значение.