Обзор клона меги328 -LGT8F328P

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Купил поизучать що це таке вот такую платку а-ля Nano от небезызвестного китайского завода WAVGAT

На самом МК маркировка как и на картинке - WAVGAT AVGA328P, а фактически там стоит МК LGT8F328P от компании LogicGreen, об этом говорит хотя бы аддон, который продавец  рекомендует установить. Кстати продавец честно пишет, что это нано-совместимая плата.   В принципе об этом МК уже неоднократно писали, но информация неполная, а местами даже недостоверная. Так что решил что будет лучше собрать всё в одном месте. Подобные ардуины кстати делают так-же и другие производители, так что в целом всё будут справедливо и для других вариаций, типа промини WemosXI и прочих.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

И так, принципиальные отличия от меги 328:
-поддерживаются тактовые частоты до 32МГц как от внутреннего PLL-синтезатора, так и от внешнего кварца или кварцевого генератора.

-питание 1.8-5.5 вольт, причём 1.8 вольт поддерживается даже на самой высокой частоте.

-у этого МК нет фьюзов, любые параметры, аналогичные тем, что настраиваются в меге328 фьюзами можно настроить или изменить прямо из программы.
-Что-бы МК поддерживал ардуино на стандартной частоте 16Мгц регистр управления системными клоками настраивается в бутлоадере.
-Поэтому не смотря на то, что там залит стандартный оптибутовский бутлоадер -с другими ардуиновскими лоадерами он не совместим, так как адаптирован под данный МК. Если залить обычный бутлоадер от меги, то пологаю МК может и запуститься, но на какой-то дефолтовой частоте.
- На конкретно моей плате ещё стоят 2 кварца на 12МГц (для CH340 и для МК). Причём для МК он по умолчанию не используется, т.к. бутлоадер настраивает системные клоки на внутренний генератор 32МГц с делителем 2, т.е. так получаются заветные 16МГц.
Из первых разочарований -внутренний генератор не смотря на то, что довольно точный (заявлена 1% точность) - но по сути всё равно паршивый, у него жуткий джиттер. Включаю вывод тактовой на ногу 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
}

Совершенно другое дело, сигнал с той же ноги:

-ещё  WatchDog тут умеет тактироваться как от своего, так и от системного rc-осциллятора. Т.е. должен быть гораздо точнее во втором случае.

- Таймеры. В сравнении с мегой328 добавился 16-битный таймер3. Обладает всеми возможностями 1-го, но имеет доп. регистры. Аппаратных ног у третьего таймера как и у остальных таймеров (в 32х выводном МК) тоже две-  OCR3A/B , которые доступны на арду-пинах TXd и D2.  Соответссно всего на плате имеется 8 ног с PWM.  Таймеры 0 , 1  могут тактироваться от внутреннего PLL синтезатора 64МГц. Соответственно умеют шиммить на гораздо более высоких частотах чем мега328. Так же 0 , 1 и 3  таймеры умеют делать дид-тайм, и у них есть возможность отключать свои выходы по всяким событиям (срабатывание компаратора, внешнее прерывание, переполнение от другого таймера).

- ЦАП имеется в количестве 1 штука, 8-битный.  Может брать референс от Vcc или от внутренних источников.   Вывел пилу для визуальной оценки:

#include "lgtx8p.h"
 void setup() {
DACON= 1<<DACEN | 1<<DAOE ; // dac-on, включить пин
static uint8_t n=0;
cli();
while(1){  DAL0=n++;  } 
}
 
void loop() {}

Сперва что-то не пошло, выдавало кривую пилу. Со второго захода вроде нормально стало.

Но есть нюанс,- у этого ЦАПа выход с каким-то большим внутренним сопротивлением, попробовал подключил киломный резюк -сигнал схлопнулся почти что в ноль. Так что без  ОУ этот ЦАП не стоит использовать. Судя по этому, а так же по высокой скорости работы и по картинке в даташите -цап чисто резисторный :)

-Компаратор (2 штуки) тут гораздо более продвинутый. Есть возможность использовать DAC как один из входов. Или любое из калиброванных внутренних референсных напряжений (а их тут 3 - 1.024V, 2.048V и 4.096V)   А главное, чего не было в меге -тут есть гистерезис! 

-АЦП -12 битный, есть возможность дифф.включения входов и  усиления входного сигнала в 8/16/32 раз. Доступны любые референсы, в том числе от ЦАПа.   АЦП этот бегло протестировал, не очень впечатляет. Возможно это недостаток платы , на которой припаян МК, но 12-битного разрешения мне не удалось выжать даже при идеальном источнике сигнала и референса, 10 бит пожалуй  будет, но с программным усреднением: при референсе 2,048V удалось добиться гуляние результата оцифровки измерения напряжения батарейки   +/-  1mV

-Порты здесь  рассчитаны в основном на 30мА нагрузки. Но есть некоторые у которых ток по умолчанию лишь 12 мА, но через регистр HDR (high-current push-pull) можно включить буффер, и  максимальная нагрузка на них возрастает до 80мА. Но таких портов немного, (PE5) (PE4) (PD2)  (PD1) (PD6)  (PD5)       

-Есть ещё интересные регистры мультиплексирования - с помощью них можно перекинуть некоторые сигналы таймеров или сериала на альтернативные ноги. Есть даже возможность переназначить ногу AREF как порт PE6 , и даже ресет в порт  PC6 .

Пример задействования ног  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; }
}

Как видно полный цикл ногодрыга получится  из 4х тактов МК (инверсия ноги, jamp, инверсия ноги, jamp) Поэтому на выходе меандр с частотой 8 МГц.  (32/4)

-Дополнил распиновку модуля теми сигналами, что не были указаны. Так же исправил несколько ошибок на исходной картинке.

-Документация  оригинальный даташит на МК на китайском, есть так же его переведённая на инглиш гуглом версия, но там убились все картинки и сбился формат строк. Наш коллега Green  нашёл  русскоязычный даташит LGT8F328P datasheet  за что спасибо ему и большое спасибо автору перевода.  Даташит сам по себе не очень хороший, в нём например не все регистры описаны, которые есть в сводной таблице. Внимание, в даташите есть мелкие ошибки! Примеры приводить не буду, что б не раздувать пост. 

Так же переведён на русский даташит на более старую модель МК  LGT8F328D, в нём максимальная частота 20МГц, нет третьего таймера, но зато вроде как есть два ЦАПа. Предположительно он ставился в платы MassDuino и WEMOS XI. Определить какой у вас МК пологаю можно запрограммировав 3й таймер. Его можно запустить даже без аддона, я указал для таймера прямые адреса без дефайнов)

//Тест на наличие таймера3 -при 16МГц тактовой светодиод Тх замигает с частотой примерно 5Герц
void setup() {
*(uint8_t*)0x33 =0x2 ;//  DDRF=1<<DDF1
*(uint8_t*)0x99 =0x5; // OCR3AH=0x5;
*(uint8_t*)0x98 =0xDC; // OCR3AL=0xDC;
*(uint8_t*)0x90 =0x40; // TCCR3A=1<<COM3A0;
*(uint8_t*)0x91 =0xD;  // TCCR3B=1<<WGM32 | 1<<CS30 |1<<CS32;
}
void loop(){}

-Аддон (пакет поддержки мк) для Arduino IDE лучше брать не тот, который со страницы продавца, а родной, от производителя контроллера. С ним меньше проблем.

-прошивка производится либо через бутлоадер , либо специальным  программатором через serial wire debug (SWD) interface по двум проводам. К счастью добрые люди уже написали скетч для ардуины, которая превращается в SWD программатор.  Дополнение: к сожалению этот скетч только для МК LGT8F328D , c *P он не работает.

Напоследок табличка, где сравнивается скорость выполнения  в тактах некоторых ассемблерных команд в обычном AVR и в LGT8

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

Пока всё. Просьба не нажимать кнопку "цитировать", т.к. у меня пропадёт возможность что-то добавлять в этот пост.

 

semaawp
semaawp аватар
Offline
Зарегистрирован: 29.05.2017

Интересный камень, спасибо за информацию. Пойду добывать сведения про него

slider
Offline
Зарегистрирован: 17.06.2014

здоровские исследования.

порадовало -АЦП -12 битный, есть возможность усилить входной сигнал в 8/16/32 раз. (для измерений на шунтах само-то . и измерений с высокоомным входом , хотя для микропотребления, чтоб не заморачиваться с ключём для делителя , годно работал делитель 10МОм+1МОм || кондер керамика 0.1мкф 50в)

делителя нет у atmega328p .  хотя на меге2560 есть x200  http://arduino.ru/forum/apparatnye-voprosy/koeffitsient-usileniya-u-analogovogo-vkhoda .  и тиньках  x20  ( x200 )

так что там про 32МГц ? , очень интересно.  Какую частоту выдает ногодрыг? можно выдавить 32МГц (длину импульса 31нс, и сколько там будет период)?

как это было на atmega328 , длина импульса 62 нс , период=250мс => частота 4мгц ,:

1
2
3
4
5
6
7
8
9
10
11
12
13
void setup()
{
DDRB = B10000000; // устанавливаем 13 пин как OUTPUT
}
void loop()
{
// создаем свой бесконечный цикл
 while (1)
{
  PORTB = B10000000; // устанавливаем состояние pin13 как HIGH
  PORTB = B00000000; // устанавливаем состояние pin13 как LOW
}
}

взято здесь  http://robotosha.ru/arduino/digitalwrite-optimizing-arduino.html

 

// по идее можно было еще больше выдавить частоту чем 4мгц применив

RJMP/RCALL  Relative jump/call          2/3             1
// создаем свой бесконечный цикл
M1:
  PORTB = B10000000; // устанавливаем состояние pin13 как HIGH
  PORTB = B00000000; // устанавливаем состояние pin13 как LOW
goto M1;

 

 

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Спасибки, очень интересно.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

slider, завтра проверю ногодрыг  на 32МГц, на ассемблере,  со счётом тактов, всё как пологается :)

slider
Offline
Зарегистрирован: 17.06.2014

------- 32 MГц  WAVGAT328  в  2.66 раза  оказался быстрее чем Atmega328p  !!!  ------

dimaxв принципе то вроде все сходится без написания на ассемблере.

1такт - лог.1

1такт - лог.0

1такт - переход rjmp в цикле на начало (у атмеги328 было значит 2 такта)

и того 32нс * 3 = 96.  

1000/96= 10.4  вот и получалось на выходе 10.5МГц     (на atmega328p было 4МГц 1такт+1такт+2такта переход)

Из фотки видать что лог.1=лог.0=rjmp= ~31нс , а это и есть 1 такт при 32МГц !!!

пулучается все верно , забираем у проца по 3 такта по кругу и получаем грубо частоту 32МГц/3  .

 

// фотки осциллограф sds1102cml не сохранят картинки на флэшку, а только файлы настроек *.set  ,в инете у когото чудесным образом получилось. я не знаю как заставить его сохранять.

slider
Offline
Зарегистрирован: 17.06.2014

dimax ,, переключи щуп осцила на делитель 10 , и тогда пила будет пила отличная !  (собственно осцилы портят и цифровые сигналы на 1 , поэтому иногда имеет смысл переключать на щупе на 10)

при вкл. на 32МГц

#include "lgtx8p.h"
 void setup() {
CLKPR = 1<<PMCE;//разрешить изменение
CLKPR = B00000000;

DACON= 1<<DACEN | 1<<DAOE ; // dac-on, включить пин
static uint8_t n=0;
cli();
while(1){  DAL0=n++;  } 
}
 
void loop() {}

частота повышается с 6.9КГц до 13.8КГц

пила тож норм. , также малехо также подрыгивается из-за плавания частоты внутреннего гена.

renoshnik
Онлайн
Зарегистрирован: 11.04.2013

Пробовали работать с ЕЕPROM - у меня библиотека глючит. Пишет, что она для архитектуры АВР .

slider
Offline
Зарегистрирован: 17.06.2014

renoshnik норм,  ничего не глючит (IDE 1.8.5) , запускаю из

C:\Users\.......\Documents\Arduino\WAWGAT\E2PROM\examples  (в мои доки скинул примеры и либу с гитхаба  https://drive.google.com/open?id=10gwrG9uTDwaEO-7EudsmBkfgdcyrcABI эта ссылка у продавца на али)

// полагаю что может ваше IDE из-за более близких к началу списка подтягивает оригинальную либу EEPROM.h . попробуйте закинуть либу в либы что в моих документах.  и мож в моих документах в скетчи закинуть.

//// и заметил разве что как-то в 0 адрес ничего не пишется , всегда там читается 0 , а в другие адреса и пишется всякое и читается верно. А потом в сетап поставил холостой  value = EEPROM.read(address);  и все норм читается из 0 адреса.

/*
 * EEPROM Read
 *
 * Reads the value of each byte of the EEPROM and prints it 
 * to the computer.
 * This example code is in the public domain.
 */

#include <EEPROM.h>

// start reading from the first byte (address 0) of the EEPROM
int address = 0;
byte value;

void setup()
{
  // initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
    
  }
 // delay(1000); // на всяк случай
   value = EEPROM.read(address); // холостой
}

void loop()
{
  // read a byte from the current address of the EEPROM
  value = EEPROM.read(address);
  
  Serial.print(address);
  Serial.print("\t");
  Serial.print(value, DEC);
  Serial.println();
  
  // advance to the next address of the EEPROM
  address = address + 1;
  
  // there are only 512 bytes of EEPROM, from 0 to 511, so if we're
  // on address 512, wrap around to address 0
  if (address == 512)
    address = 0;
    
  delay(50);
}

 

Green
Offline
Зарегистрирован: 01.10.2015

Уже где-то писал:
【重要说明】:  
LGT8FX8D 最高运行频率为20MHz,  因此当选择内部32MHz RC作为主时钟源时,一定要
保证CLKPR设置为正确的分频配置(最低2分频)。

dimax пишет:

-к сожалению оригинальный даташит на МК на китайском, есть так же его переведённая гуглом версия,

Есть на русском. Красивый, с цветными картинками). Уже не помню где брал.
 

renoshnik
Онлайн
Зарегистрирован: 11.04.2013

Про бутлоадер  https://www.drive2.ru/b/508852882896847017/

Игрался с АЦП  https://www.drive2.ru/b/506709110100590734/

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Green, LGT8FX8D -это немножко другой МК, более старая модель. У них не очень значительные отличия, но одно из них как раз максимальная частота. По моему ещё математические 16-битные регистры и таймер3 тоже есть только в *P модели, и ещё из броского по даташитам - ЦАПов в *D было 2 штуки, а в *P оставили один. PS: думаю многие будут благодарны, если найдёте  даташит на русском, пусть даже более старой модели, всё равно пригодиться :)

slider, щуп на /10 переключал, при этом горб выпячивался в другом месте, я в реальности около часа пытал этот ЦАП, всё  что можно перепробывал, до конца надеялся, что можно что-то сделать, но увы.  Как вариант -может это просто бракованный мк, всякое бывает, тем более у таких левых производителей :)

Green
Offline
Зарегистрирован: 01.10.2015
alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012

 

Война клонов?  Или китайцы выпустили один клон и тиражируют его

в разных вариантах. Давно купил MD-328D, но руки до него так и недошли.

Сейчас глянул доки, блок-схемы один в один. Только названия ядра разные и

некоторые другие отличия. У моего, например, АЦП 10/12/16 бит.

Сейчас глянул на их сайт, они новый клон запилили MD-3248P. И сделали на нём плату.

http://www.inhaos.com/product_info.php?products_id=168

Но ИМПЕРИЯ наносит ответный удар. http://www.microchip.com/promo/atmegaavr-family

Да, EEPROM у них нет. “ (simulate E2PROM) “ В флеше область выделяют.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Logik, сейчас проверил ссылка на продавца работает.. кликнул -открылась.

alex_r61, подозреваю, что Inhaos  как и WAVGAT крупный покупатель у ложик грина, и для них МК маркируют по-другому. За 16 бит АЦП там выдают оверсемплинг 12ти бит.

Logik
Offline
Зарегистрирован: 05.08.2014

dimax пишет:

Logik, сейчас проверил ссылка на продавца работает.. кликнул -открылась.

То известная багофича сайта. Вставте через кнопку "Вставить/редактировать ссылку". Хотя себе я уже нашел его https://ru.aliexpress.com/item/WAVGAT-Nano-Mini-USB-Nano-3-0/32868170637.html Закажу пожалуй.

А он чё, реально в коробочке приезжает? Там жеж одна коробочка этих денег стит ;) В половине случаев она за корпус прибора сойдет.

malser
Offline
Зарегистрирован: 12.09.2018
DIMAX 
Пытаюсь залить бутлоадер в платку WAWGAT. Взял скетч по вашей ссылке, скомпилировал и залил на Ардуино нано3. Подключил Wavgat. Нажимаю кнопку залить загрузчик - выдает следующее. Вы не пробовали заливать?
C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/bin/avrdude -CC:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM5 -b19200 -Uflash:w:C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\LGT\avr/bootloaders/lgt8fx8p/optiboot_lgt8f328p.hex:i 

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM5
         Using Programmer              : arduino
         Overriding Baud Rate          : 19200
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x15
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x15
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x02

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x10
         Hardware Version: 4744608
         Firmware Version: 0.4611299
         Topcard         : STK502
         Vtarget         : 1.8 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: stk500_initialize(): (b) protocol error, expect=0x10, resp=0x01
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x10

avrdude done.  Thank you.

 

Logik
Offline
Зарегистрирован: 05.08.2014

В даташите с цветными картинками

[Важно] Максимальная рабочая частота LGT8FX8D составляет 20 МГц.
Поэтому, когда в качестве основного источника синхронизации выбран внутренний
32-мегагерцовый RC, необходимо убедиться, что CLKPR настроен на правильную
конфигурацию частотного разделения (минимум 2-х частотное деление).

Получается 32МГц официально нет?

slider
Offline
Зарегистрирован: 17.06.2014

Logik, читайте внимательней ,dimax выше писал что LGT8FX8D это немного другой по возможностям  чем LGT8F328P (AVGA328P) .
И в даташите  написали что 20мгц предел это только для LGT8FX8D, на LGT8F328P это ограничение не распространяется.

 

renoshnik
Онлайн
Зарегистрирован: 11.04.2013

malser пишет:

DIMAX 
Пытаюсь залить бутлоадер в платку WAWGAT. Взял скетч по вашей ссылке, скомпилировал и залил на Ардуино нано3. Подключил Wavgat. Нажимаю кнопку залить загрузчик - выдает следующее. Вы не пробовали заливать?
C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/bin/avrdude -CC:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM5 -b19200 -Uflash:w:C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\LGT\avr/bootloaders/lgt8fx8p/optiboot_lgt8f328p.hex:i 

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\malserr\Downloads\arduino-1.8.6-windows\arduino-1.8.6\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM5
         Using Programmer              : arduino
         Overriding Baud Rate          : 19200
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x15
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x15
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x02

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x10
         Hardware Version: 4744608
         Firmware Version: 0.4611299
         Topcard         : STK502
         Vtarget         : 1.8 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: stk500_initialize(): (b) protocol error, expect=0x10, resp=0x01
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x10

avrdude done.  Thank you.

 

 

пост №15 про бутлоадер...

AleksandrGHJ
Offline
Зарегистрирован: 06.09.2018

Уважаемые Dimax и Logic, следуя вашим рекомендациям создам новую ветку с более подробным описанием. Вот только проведу дополнительные пробы, чтоб лишний раз не отвлекать по мелочам. Вдруг проблемы тут вовсе нет. Единственный вопросик: может раз уж у вас в руках имеются подобные девайсы может гляните у себя как ведет себя аналоговый вход?

Скеч предельно прост:

void setup() {
 Serial.begin(9600);
}
 
void loop() {
 Serial.println(analogRead(A1));
 delay(200);
}

Схему подключения можно также предельно упростить:

пробрасывать перемычкой на А1 напругу с пинов 5В; 3,3В и GND. У меня выдает в мониторе соответственно 2340, 4061, 0. хотя по логике вещей должно быть 4096, 2703 и 0.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Обновил первый пост:

- добавил осцилограмму с ноги D8 при тактировании от внешнего генератора + команды переключения
- c ЦАПа снял нормальную  осцилограмму другим щупом, поменял картинку.
- пример и осцилограмма ногодрыга на тактовой 32МГц -> 8МГц
-ссылки на руские даташиты
-тест на наличие таймера3
 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

AleksandrGHJ, загрузил ваш скетч, подключил переменник 10 кОм -у меня всё линейно регулируется. Отдельно от 3.3 вольта показывает  3100 попугаев, от  5 вольт - 3968 попугаев. Тут наверное вам стоит обратить внимание на то, что это _нано_, у неё питание идёт через диод. В результате на Vcc приходит (на моей плате) 4,65в. И 3,3 у меня тоже не соответствует -реально 3,63. Если всё это пересчитать -то именно так и должно быть.

А 4095 в максимуме тут  быть не обязано, т.к. функция analogRead в этом аддоне навороченная, и делает калибровку смещения АЦП (страница 251 русского даташита), так что в моём случае АЦП откалибровалось с потолком 3968. В вашем -4061. Можете проверить чтение без арудиновских причуд моим скетчем, там будет  0..4095. Сигнал подавать на вход A0:

void setup() {
Serial.begin(9600);
ADCSRA|=1<<ADEN | 1<<ADPS2 |1<<ADPS1 |1<<ADPS0; // clk/128
ADCSRB=0; DIDR0=1<<0;
ADMUX=1<<REFS0; // ADC0 , AREF=Vcc
}

void loop() {
ADCSRA|=1<<ADSC;
while (bit_is_set(ADCSRA, ADSC));
uint16_t aread = ADC;
Serial.println(aread);
delay(100);

}

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

dimax, Какова максимально возможная скорость работы АЦП, можете измерить? Какой минимальный делитель тянет АЦП, пусть с потерей разрядности..

alex_r61
alex_r61 аватар
Offline
Зарегистрирован: 20.06.2012

 Какая максимальная частота у SPI. Ждёмс конкретных результатов работы с LCD TFT.

malser
Offline
Зарегистрирован: 12.09.2018

renoshnik пишет:

 

 

пост №15 про бутлоадер...

[/quote]

Не помогло

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM6 -b19200 -e -Ulock:w:0x3f:m -Uefuse:w:0x07:m -Uhfuse:w:0xff:m -Ulfuse:w:0xff:m 

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM6
         Using Programmer              : arduino
         Overriding Baud Rate          : 19200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: erasing chip
avrdude: reading input file "0x3f"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3f:
avrdude: load data lock data from input file 0x3f:
avrdude: input file 0x3f contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of lock verified
avrdude: reading input file "0x07"
avrdude: writing efuse (1 bytes):

Writing |  ***failed;  
################################################## | 100% 0.06s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0x07:
avrdude: load data efuse data from input file 0x07:
avrdude: input file 0x07 contains 1 bytes
avrdude: reading on-chip efuse data:

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM6 -b19200 -Uflash:w:D:\Документы\Arduino\hardware\WAV\avr/bootloaders/lgt8fx8e\optiboot_lgt8f328d.hex:i -Ulock:w:0x3f:m 
Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: WARNING: invalid value for unused bits in fuse "efuse", should be set to 1 according to datasheet
This behaviour is deprecated and will result in an error in future version
You probably want to use 0xff instead of 0x07 (double check with your datasheet first).
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0xff"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xff:
avrdude: load data hfuse data from input file 0xff:
avrdude: input file 0xff contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xff"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xff:
avrdude: load data lfuse data from input file 0xff:
avrdude: input file 0xff contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude done.  Thank you.


avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM6
         Using Programmer              : arduino
         Overriding Baud Rate          : 19200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "D:\Документы\Arduino\hardware\WAV\avr/bootloaders/lgt8fx8e\optiboot_lgt8f328d.hex"
avrdude: writing flash (30720 bytes):

Writing | ################################################## | 100% 0.56s

avrdude: 30720 bytes of flash written
avrdude: verifying flash memory against D:\Документы\Arduino\hardware\WAV\avr/bootloaders/lgt8fx8e\optiboot_lgt8f328d.hex:
avrdude: load data flash data from input file D:\Документы\Arduino\hardware\WAV\avr/bootloaders/lgt8fx8e\optiboot_lgt8f328d.hex:
avrdude: input file D:\Документы\Arduino\hardware\WAV\avr/bootloaders/lgt8fx8e\optiboot_lgt8f328d.hex contains 30720 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.08s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
Ошибка при записи загрузчика.
         0xff != 0x0c
avrdude: verification error; content mismatch

avrdude done.  Thank you.

 

malser
Offline
Зарегистрирован: 12.09.2018

Кто-то загружал бутлоадер в эту плату?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Arhat109-2 пишет:

dimax, Какова максимально возможная скорость работы АЦП, можете измерить? Какой минимальный делитель тянет АЦП, пусть с потерей разрядности..

Даташит говорит, что больше 3МГц разрешение будет падать.  Проверил минимум -делитель на 2 держит однако, т.е. 8 МГц тактовую. Ну и 15 тактов на преобразование. 0,125µS * 15 = 1,875 µS. Не помню уж сколько у простой меги было. Для проверки завернул сигнал-треугольник  с выхода  ЦАПа через ОУ на вход АЦП, картинку рисует приемлемую.

Но с дефолтовым делителем более ровно рисует.

#include "lgtx8p.h"
uint8_t n;
void setup() {
Serial.begin(2000000);
DACON= 1<<DACEN | 1<<DAOE; // dac-on, включить пин
ADCSRA=1<<ADEN ; // clk/2
ADCSRB=0; ADCSRC=0;
ADMUX=1<<REFS0; // ADC0 , AREF=avcc
DIDR0=1<<0;
}

void loop() {
static bool dir=1;
DAL0= dir? n++ : n-- ;
if (n==255|| n==0) dir=!dir;
ADCSRA|=1<<ADSC;
while (bit_is_set(ADCSRA, ADSC));
uint16_t aread = ADC;
Serial.println(aread);
delay(5);

}

alex_r61 пишет:

 Какая максимальная частота у SPI. Ждёмс конкретных результатов работы с LCD TFT.

Если вопрос ко мне, то у меня не было планов подключать LCD..

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

А как он по совместимости с Atmega328 на уровне регистров? Хотябы обратной?
 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

sav13, я каждый регистр не сверял :)  думаю обратно совместимы, хотя какие-то нюансы скорее всего есть.  

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Уже нефигово. А с 32Мгц тактовой делитель на 2 - держит? (16Мгц частота Ацп)? У него 15 тактов преобразование? Впрочем, если 12 бит, то должно быть так, пасибки.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Arhat109-2, на 32х МГц тоже завелось, но картинка уж совсем непривлекательна..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ну .. непривлекательность картинки для меня - явление условное. А вот делитель 2 с 32метров .. это очень даже круто - практическая скорость оцифровки за мегагерц. :) На 8Мгц блока АЦП у Меги она ещё больше "непривлекательна", промежду прочим и ещё и не каждая мега такое может (328-я к примеру нет) .. там ваще рабочих макс. 6 разрядов и это при низкоомном выходе (как у Вас с ОУ) и правильной разводке ножек АЦП.. а в типовых платат так и ваще 5 бит. :)

P.S. на этом уже вполне можно лепить следящую систему за десятком целей.. :)

.. очень интересная машинка. Правда помнится микрочип тоже грозился выпустить обновление линеек, не знаю как там у них с этим - пошли или нет, не следил.

AleksandrGHJ
Offline
Зарегистрирован: 06.09.2018
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Всякие полезняшки:

Аналог "секретного вольтметра" для lgt8f328p  Измеряется напряжение на шине Vcc. Теория метода та-же самая, что и для меги 328. Ставится референс =AVCC, вход АЦП мультиплексором переключается на внутреннее, заведомо известное опорное напряжение (в данном случае 2,048 V). Затем через опорное вычисляется какое же было референсное. Ну тут я ещё усреднение добавил.

#include "lgtx8p.h"
void setup() {
Serial.begin(9600);
}

void loop() {
Serial.print(" Vbg,mV=");
Serial.println(Vbg());
delay(300);

}



uint16_t Vbg(){
ADCSRB=0;
ADCSRC=0;
ADCSRA=1<<ADEN | 1<<ADPS2 |1<<ADPS1 |1<<ADPS0; // adc enable , clk/128
ADMUX=1<<REFS0 | 1<<3 | 1<<2 | 1<<0; //ref=avcc, input= ivref 
ADCSRD=1<<BGEN | 1<<IVSEL0; //ivref=2048
VCAL=VCAL2;//load 2048 calibrate byte
uint32_t bgaread=0;
//собрать 256 семплов для усреднения
for (int n=0x0; n<=0xff; n++ ) {
  ADCSRA |= (1<<ADSC);   
    while (bit_is_set(ADCSRA,ADSC));
      bgaread += ADC;
        }
bgaread>>=8; 
bgaread= ((uint32_t)2048<<12) / bgaread;
return (uint16_t)bgaread;

  
  }

Следующий скетч  поочерёдно выводит внутренние референсные напряжения на вывод AVREF. Можно проконтролировать их точным вольтметром, и например учесть в расчётах. Или подкрутить заводские калибровочные константы VCAL*

#include "lgtx8p.h"
void setup() {
Serial.begin(57600);
ADCSRA|=1<<ADEN | 1<<ADPS2 |1<<ADPS1 |1<<ADPS0; // clk/128
ADCSRB=0;
ADMUX=0xd;     // ivref
ADCSRC=1<<0;
DIDR1=1<<PE6D;
}

void loop() {
Serial.println("Set AREF pin -> 4,096v");
ADCSRD=1<<BGEN | 1<<IVSEL1;
VCAL=VCAL3;
mydelay();
Serial.println("Set AREF pin -> 2,048v");
ADCSRD=1<<BGEN | 1<<IVSEL0;
VCAL=VCAL2;
mydelay();
Serial.println("Set AREF pin -> 1,024v");
ADCSRD=1<<BGEN;
VCAL=VCAL1;
mydelay();
}

void mydelay(){
for (byte n=0; n<=5; n++ ) {Serial.print("."); delay(1000); }
 Serial.println();
}

 

slider
Offline
Зарегистрирован: 17.06.2014

dimax ,     чутка не по теме, но как тож развитие atmega328, не посматривал ли такие контроллеры  ATxmega32D4  ?https://ru.aliexpress.com/item/-/32843431511.html
 по деньгам рядом с atmega328p(b)-au   , зато тож всяких возможностей гораздо прибавилось.  ATXMEGA32A4  еще покруче , но и подороже https://ru.aliexpress.com/item/10pcs-ATXMELA32A4-AU-ATXMEGA32A4-QFP-sold-together-new/32800983407.html  . мож потом кто и поддержку в IDE придумает.  

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

slider, не, семейством xMega вообще не интересовался. Психологически я уже перешёл на stm32, и другие МК меня не интересуют. Данный МК, которому посвящена тема исключение, заинтересовало что у любимой "тёплой, ламповой" меги328 появился братик со сверхспособностями, и его захотелось изучить :)

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

У xMega несколько странноватый способ прошивки, поэтому она не получила большого развития, ну и цена тоже "не айс". Хотя, когда ковырял даташит, была мысля что можно запилить обыкновенный USB-UART программатор, но так и не удалось найти камни по вменяемым ценам на тот момент.

slider
Offline
Зарегистрирован: 17.06.2014

Очень ясно. Вопрос закрыт.

А есть на памяти какой скетч тестовый арифметический ?, попробую от внешних активных кварцев погонять wavgat328 , интересно до какой частоты он стабильно может работать , 40 , 50мгц ? (Скетч , что сбои давал при разгоне)
Конечно такие опыты от лукавого , если надо быстрее - бери проц другой . но все таки хотелось бы проверить запас у него по частоте.

Logik
Offline
Зарегистрирован: 05.08.2014

Наверно БПФ посчитать подойдет. И познавательно будет.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Ещё в копилку полезняшек, этот МК обладает глобальным уникальным идентификационным номером. (GUID) Можно в чём-то это использовать, например привязать программу к этому номеру, и на другом МК она уже не заработает. Скетчик , считывающий GUID сначала заприметил на китайском сайте, но ещё при первом взгляде зародились сомнения, что правильно он работать не сможет. И точно, проверил -выдаёт только часть номера, думаю знающие люди сразу поймут почему. А незнающим хорошая задачка на самостоятельный разбор причины ;) Предлагаю другой вариант чтения GUID, без всяких байтовых сдвигов.


void setup() {
Serial.begin(9600);
uint32_t guid= *(uint32_t*)&GUID0 ;
Serial.println(guid,HEX); 
}

void loop() {}

 

slider
Offline
Зарегистрирован: 17.06.2014

dimax , гениально. китайцы до этого не додумались :)
хорошая плюшка.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Есть ещё в этом МК такая любопытная штука, как цифровой вычислительный ускоритель (uDSC).  Позволяет производить массу различный операций с целочисленными 16-битными числами  (кроме вычислений с плавующей точкой). Ускорение достигается за счёт того, что этот модуль любую операцию выполняет всего за 1 такт МК, правда тут возникают накладные расходы времени что-бы загрузить и выгрузить данные. Но загрузка и выгрузка каждого 16-разрядного слова тоже занимает 1 такт.  Выгружается кстати в 32-битный регистр (за 2 такта), так же есть ещё 16-битный регистр переполнения. Так что в теории можно производить операции с числами до 40 бит. Жалко что входные регистры не 32-битные, а то можно было бы посоревноваться с 72х мегагерцовым stm32 . Из-за специфики доступа к этому модулю компилятор понятия не имеет что он существует, поэтому что бы задействовать все эти способности нужно написать свою  функцию. Опять же из-за особенностей доступа к портам ускорителя напрямую  языком СИ невозможно к ним обратится. Я написал простую функцию на ассемблере, они принимает 3 операнда - первые два -это числа для ариф. операции, и третий операнд - код арифметической операции (подробности смотреть в русском даташите, страница36 )

void setup(){
Serial.begin(115200);
Serial.println ("Start..");
uint16_t a=16173, b=7522;
uint32_t data  = uDSC(a,b, 0x44);
Serial.print("a= "); Serial.print(a);
Serial.print("  b= "); Serial.println(b);
Serial.print("a * b = "); Serial.println (data); 
}
uint32_t uDSC(uint16_t dx, uint16_t dy, uint8_t opcode){
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: : [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (opcode)
) ; }

void loop(){}

 

Ну и естессно захотелось сравнить реально ли оно быстрее обычных вычислений? Проверка скорости дело не такое простое как может показаться на первый взгляд, компилятор может взять, и полностью изменить код.  Поэтому надо не давать ему такой возможности, но при этом сильно не мудря, что-бы посторонними операциями мк занимался минимальное время. Я решил умножать счётные регистры таймеров. 

/*тестирование скорости математическогго ускорителя LGT8F328P
данные для ариф. операций берутся от счётных регистров 3 и 2 таймера.
Счёт времени ведёт первый таймер. Программа выводит скорость подсчёта
функций, кол-во циклов в измерении  задано в дефайне cycles
*/
#define cycles 100 
#define tcnt2 (*(volatile uint16_t*)0xB1)
#define tcnt3 (*(volatile uint16_t*)0x94)
#include "lgtx8p.h"
uint16_t n; //
uint32_t data; //для результата ариф. операций

void setup(){
Serial.begin(115200);
Serial.println ("Start..");
TCCR2A=0;TCCR2B=1<<CS20; //запустить таймер
TCCR3A=0;TCCR3B=1<<CS30; //запустить таймер
TCKSR=0; TIMSK1=0; TCCR1A=0; TCCR1B=0; //обнулить лишнее
OCR1A=65535u; OCR1B=65535u;// чтоб удобнее читать регистр флагов

//Тестирование скорости операций DA=DA+(DX*DY) через uDSC
cli();
n=cycles;
TCNT1=0; TIFR1=TIFR1;
TCCR1B=1<<CS10;//подсчёт времени включён
while(n--) {
data  = uDSC(tcnt2,tcnt3); 
}
TCCR1B=0; sei();
Serial.print("Test uDSC  ");
if (TIFR1) {Serial.println("Timer overload");} 
  else Serial.print((float)TCNT1/16); Serial.println("  uS"); 

//Тестирование скорости операций DA=DA+(DX*DY) обычным способом 
data=0;
cli();
n=cycles;
TCNT1=0; TIFR1=TIFR1;
TCCR1B=1<<CS10;
while(n--) {
no_acsl(tcnt2, tcnt3);
}
TCCR1B=0;  sei();
Serial.print("Test Normal  ");
if (TIFR1) {Serial.println("Timer overload");} 
  else Serial.print((float)TCNT1/16); Serial.println("  uS"); 

}

void loop(){}

uint32_t no_acsl(uint16_t a, uint16_t b){
data+= (uint32_t)a * b;  
}

uint32_t uDSC(uint16_t dx, uint16_t dy){
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: : [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x47)
) ; }

Уж не знаю, оптимальный ли это код для тестирования. Я старался создать одинаковые условия. И обычный счёт и счёт через ускоритель вывел в отдельные функции, которые получали по два 16 бит операнда, а возвращали один 32 бит. Время считает таймер1, у микроса точность гораздо хуже. Результат такой, -на 100 циклах операции DA = DA + (DX*DY)  вывелось следущее:

Test uDSC  269.75  uS
Test Normal  451.00  uS

То есть с ускорителем в 1,5 раза быстрее. Ну если вычисление обычным способом убрать из отдельной функции и вставить в тело основной программы то результат сравнится. Но возможно, что все эти результаты полная фигня из-за того что я выбрал неудачно счётную задачу. Возможно в какой-то другой ситуации, где идёт какой-то входящий поток данных ускоритель даст в разы большую скорость. Интересно протестировать на FFT. Я за это пожалуй уже не возьмусь, и так времени целый день убил.

 

 

Logik
Offline
Зарегистрирован: 05.08.2014

Реальная круть! Прямо целый DSP! И то что на входе всего 16-бит нормально, даже правильно. Если не тяжело, прогоните тест еще например на 200 циклах, чтоб исключить потери времени на организацию цикла и т.д.

Хотя даже лучше просто продублировать строки 60-62. Типа так.

uint32_t uDSC(uint16_t dx, uint16_t dy){
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: : [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x47)
) ; }

 

Тогда увеличение времени на тех же 100 тактах  по сравнению с предыдущими Test uDSC  269.75  uS делим на 100 и получаем чистое время на DA = DA + (DX*DY) . Вывод результата из DA в время операции вносить не стоит. Назначение строк 58-59 (или 3-4 в этом сообщении) я не понял, может и их надо повторять?

ПС. посмотрел строк 58-59 вобще один раз нужы. Включают DCS просто.

Logik
Offline
Зарегистрирован: 05.08.2014

Чего пишут то! "При использовании команды LD / ST для доступа к SRAM от 0x2100 до 0x28FF, ядро автоматически включает 16-разрядную функцию LD / ST, чтобы включить прямой доступ между SRAM и uDSC." Получается вместо out можна LD / ST но с адресов 0x2100 до 0x28FF куда дублировано обычное ОЗУ.

А еще там сдвиги есть на N бит! Причем хочеш со знаком, хочеш без. И деление быстрое.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Logik,  500 циклов

Test uDSC  1344.75  uS
Test Normal  2251.00  uS
Т.е соотношение не меняется . Добавлять повторы в функцию особого смысла не, т.к.  уже её потактово просчитал. 2 такта уйдёт что б внести операнды в адресные регистры. Потом 7 команд по такту описанных в функции, и  1 такт выход из функции. Выходит полный цикл 10 тактов, похоже большая часть времени уходит непонятно на что..:-\   Что-бы повторить вычисление без изменения входных данных достаточно всёго двух тактов -загрузить код операции в временный регистр, и выгрузить его в порт (или одного, если код уже лежит в регистре). На данной операции конечно скорость будет сверхзвуковая )

PS: строки 58-59 просто включают ускоритель. Да! в принципе  можно убрать, включив его один раз в сетапе. Этот регистр 8-битный, и можно им управлять из Си.  Выходит любую операцию функция будет выполнять за 8 тактов. Найти бы этому полезное применение..

Logik
Offline
Зарегистрирован: 05.08.2014

//соотношение не меняется .

И не поменяется, не в нем дело. В эти времена входит много чего - переходы циклов, вызовы функций, извлечение из аккумулятора. Все это вобщем не связано с самим временем DA = DA + (DX*DY). Чтоб исключить эту чепуху надо сделать допустим 500 (или сколько угодно вобщем, но достаточно много) раз с однократным DA = DA + (DX*DY), а потом столькоже с двукратным и вычесть одно из другого чтоб чепуха, которая одинакова в обоих опытах сократилась. Так с точностю до такта можна определить. 

//Потом 7 команд по такту описанных в функции, и  1 такт выход из функции. 

Не факт что эти команды именно при работе с DCS остаются с такими же тактами а не ждут пока насчитают

Хотя и из Ваших цифр уже интересно получается. По первому опыту 269,75/100=2,7мксек По второму 1344,75/500=2,7мксек По разностям, здесь плохо что итератор в первом опыте байт а в втором 2 байта, но (1344,75-269,75)/(500-400)=2,7мксек. Вобщем везде одинаково. Вывод - время самой операции DA = DA + (DX*DY) существенно больше чем на организацию циклов и прочую чепуху и порядка 2,7мксек. Если нужно точней - методику я описал.

//похоже большая часть времени уходит непонятно на что..:-\

Ага, порядка 2,7мксек какраз на работу DCS по расчету математики. Ну немного меньше понятно, но не на много, на те самые тактов 10.

//На данной операции конечно скорость будет сверхзвуковая )

Все проверять нужно, это же китайцы! )))))

Logik
Offline
Зарегистрирован: 05.08.2014

Я вот чего подумал. Включение ускорителя может вызывать его инициализацию на сколькото тактов. И будет влиять сильно, т.к. все тормознется до завершения инита. Возможно.  Надо стр 58-59 в сетап нафиг убирать. 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Logik пишет:

Не факт что эти команды именно при работе с DCS остаются с такими же тактами а не ждут пока насчитают

Решил проверить, ниже скетч, выполняет измерение один раз, и только времени работы функции uDSC. Поместил включение таймера прямо перед вызовом ассемблерной вставки , а выключение таймера сразу после.

//Тестирование скорости операции DA= DX*DY  через uDSC
#define tcnt2 (*(volatile uint16_t*)0xB1)
#define tcnt3 (*(volatile uint16_t*)0x94)
#include "lgtx8p.h"
volatile uint32_t data; //для результата ариф. операций
void setup(){
Serial.begin(115200);
Serial.println ("Start..");
TCCR2A=0;TCCR2B=1<<CS20; //запустить таймер
TCCR3A=0;TCCR3B=1<<CS30; //запустить таймер
TCKSR=0; TIMSK1=0; TCCR1A=0; TCCR1B=0; //обнулить лишнее
OCR1A=65535u; OCR1B=65535u;// чтоб удобнее читать регистр флагов
}

void loop(){
cli();
TCNT1=0; TIFR1=TIFR1;
uint16_t dx = tcnt2;
uint16_t dy = tcnt3;
data  = uDSC(dx,dy); 
sei();
Serial.print("Test uDSC  ");
if (TIFR1) {Serial.println("Timer overload");} 
else Serial.print(TCNT1); Serial.println("  tic mk "); 
Serial.print("dx="); Serial.print(dx);
Serial.print(" dy="); Serial.print(dy);
Serial.print(  "dx x dy ="); Serial.println (data); 
Serial.println("..");  
Serial.println("..");  
delay(5000);  
  
  }


volatile uint32_t uDSC(uint16_t dx, uint16_t dy){
TCCR1B=1; //пошёл счёт времени!
asm volatile(  
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
: 
: [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x44)
:"r18"
) ; 
TCCR1B=0; //стоп таймер 
}

И получаю:

Test uDSC  10  tic mk
dx=22017 dy=33589dx x dy =739529013

 

Решил ещё один тест провести, вписал включение таймера в начало ассемблерного кода, выключение в конец.

asm volatile(  
"ldi r19,0x01;"       "\n\t" 
"sts 0x81,r19;"       "\n\t" // TCCR1B=1<<CS10
"ldi r18, 0x80;"     "\n\t" // byte  for DSUEN
"out 0x00, r18;"     "\n\t" // DCSR= 1<<DSUEN
"out 0x10, %[dsdx];" "\n\t" // DSDX = dx 
"out 0x11, %[dsdy];" "\n\t" // DSDY = dy 
"out 0x01, %[opc];"  "\n\t" // DSIR= operation code
"in r22, 0x38;"      "\n\t" // DSAL return 
"in r24, 0x39;"      "\n\t" // DSAH return
"sts 0x81,__zero_reg__;"  "\n\t" // TCCR1B=0
: "=r" (data)
: [dsdx] "r" (dx), [dsdy] "r" (dy), [opc] "r" (0x44)
) ; 

Start..
Test uDSC  9  tic mk
dx=18689 dy=40 dx x dy =12648448
 

Добавлено: переписал результаты этих тестов в этом посте, т.к. сам допустил небольшую ошибочку. В общем все накрутки идут когда программа уже выходит из функции.

Logik
Offline
Зарегистрирован: 05.08.2014

//dx=18689 dy=40 dx x dy =12648448

вощето 18689*40=747560. Заметил что уВас множитель заканчивается на 0 а результат - нет. ))

А зачем перешли с операции DA = DA + (DX*DY), код 0х47 на DA = DX*DY, код 0х44? Они могут различатся длительностю.

Не морочтесь с этими таймерами. Когда вносится в код много изменений всегда ошибки влезут. Возмите код из #28 второй Ваш скетч, убедитесь что выдаст как ранее Test uDSC  269.75  uS, это для самопроверки, поменяйте функцию на приведеную в #29 и все, новое время все сразу покажет, т.к. в код добавлена только одна операция, то и время добавится только на неё (с учетом разумеется повтора 100 раз).