Обзор клона меги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Герц
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; 
}

 

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

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

Напоследок табличка, где сравнивается скорость выполнения  в тактах некоторых ассемблерных команд в обычном 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

 

Добавлено 25.07.2019

На этой плате неправильно разведён USART, специально срисовал схему для наглядности:


 

Как видно обмен данными возможен только между мк и usb-мостом. Какой-либо внешний сериальный сигнал подать нет возможности, он просто не прожмёт линию, которую каждый чип и светодиоды тянут вверх. Но выход есть, на помощь приходят регистры port multiplexing (PMX). Можно перенести Rx и Tx (оба одновременно или только какой то один ) на другие пины:

PMX0= 1<<7;//разрешить ремаппинг
PMX0= (1<<RXD5) |( 1<<TXD6) ; 

Так что подключить bluetooth/GPS не проблема.  Так же отремаппить можно и выход таймера OC3A, который сидит на пине Txd, и так же страдает от резистора.

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

Green
Offline
Зарегистрирован: 01.10.2015
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
Offline
Зарегистрирован: 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
Offline
Зарегистрирован: 20.06.2012

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

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 раз).

 

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

Logik, ну проверил:

Start..
Test uDSC  288.50  uS
Test Normal  451.00  uS

uDSC вырос на 18,75 мкС, тобишь на 0,1875мкС на один круг круг, что равняется 3м тактам, что точно соответствует 3-м добавленным командам. :) Стало быть ещё раз подтвердилось, что функция работает быстро, получается что основной вычислительный ресурс уходит  куда-то ещё.  60мкС на 100 кругов функции , а оставшиеся  200мкС  на подтягивание  в функцию двух 16-битных данных? Очень не правдоподобно :-/

while(n--) {
data  = uDSC(tcnt2,tcnt3);
}

 

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

ОК. Вот и вопрс решен. )) 

Одна DA = DA + (DX*DY)  - 0,1875мксек, что очень класно.

//равняется 3м тактам

А частота что 16МГц? тогда период 1/16МГц=0,0625мксек. Я думал 32МГц.  Кстати про точност 0,0625*3=0,1875 - просто идеально )))

//получается что основной вычислительный ресурс уходит  куда-то ещё.

Ага. Уходит. Ну и хрен с ним. Ответ на волновавший вопрос о скорости DSC получили. Найти пропажу - оно конечно тоже любопытно по своему. Там нужно код в ассемблере рассматривать. Думаю все найдется.

ПС. А что с нумерацией сообщений творится?! Невозможно ж рабтать в таких условиях ;)

 

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

Запостил предыдущее - терь нормально с нумерацией. Глюк.

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

Прикинул БПФ 16бит 128 точек, 128*7=896 бабочек, по две операции типа DA = DA + (DX*DY),  336мксек. С пересылками и адресацией в пару мсек должно влазить.

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

Что еще нарыл в поиске цельных портов для подключения 8/16 бит дисплеев , и благодаря интересу dimaxа:

Из-за того что мы имеем урезанную версию чипа в 32выводном корпусе вместо 48выводного , у чипа всего 2 порта цельных B и D.

8бит  PortB  01234567   (6,7 биты забрать можно у кварца , один фиг он медленный 12Мгц)

7бит  PortC  0123456     (6 бит забираем у ресета. Благо никаких фьюзов не надо, все перенастраивается в скетче)

8бит  PortD  01234567  

7бит  PortE  0123456   ( 4,5 биты забыли вывести, но можно подпаять) 

и того 30 GPIO          + VCC и GND , вот и очень экономно в 32пин корпусе.

не то что в оригинальной atmega328 продублированы питающие пины.

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

получается даже шина 16 бит реализуема. и еще десяток пинов для художеств.

renoshnik
Offline
Зарегистрирован: 11.04.2013

 bool BIT;
void setup()  { Serial.begin(57600);
Serial.println(F("               Test - PMCR: 0xF2"));
Serial.println(F("               ================="));
Serial.println(F("PMCE CLKFS CLKSS WCLKS OSCKEN OSCMEN RCKEN RCMEN"));
Serial.print(F("  "));
    BIT =(PMCR & (bit(PMCE)));    Serial.print(BIT);  Serial.print(F("    "));
    BIT =(PMCR & (bit(CLKFS)));   Serial.print(BIT);  Serial.print(F("     "));
    BIT =(PMCR & (bit(CLKSS)));   Serial.print(BIT);  Serial.print(F("     "));
    BIT =(PMCR & (bit(WCES)));    Serial.print(BIT);  Serial.print(F("     "));
    BIT =(PMCR & (bit(OSCKEN)));  Serial.print(BIT);  Serial.print(F("      "));
    BIT =(PMCR & (bit(SCMEN)));   Serial.print(BIT);  Serial.print(F("      "));
    BIT =(PMCR & (bit(RCKEN)));   Serial.print(BIT);  Serial.print(F("     "));
    BIT =(PMCR & (bit(RCMEN)));   Serial.println(BIT);
  
Serial.println(F(""));
Serial.println(F("               Test - CLKPR: 0x03"));
Serial.println(F("               =================="));
Serial.println(F("CLKPCE CLKOEN1 CLKOEN0 - CLKPS3 CLKPS2 CLKPS1 CLKPS0"));
Serial.print(F("  "));
    BIT =(CLKPR & (bit(CLKPCE))); Serial.print(BIT);  Serial.print(F("       "));
    BIT =(CLKPR & (bit(CLKOE1))); Serial.print(BIT);  Serial.print(F("       "));
    BIT =(CLKPR & (bit(CLKOE0))); Serial.print(BIT);  Serial.print(F("    "));
                                  Serial.print("-");  Serial.print(F("    "));       
    BIT =(CLKPR & (bit(CLKPS3))); Serial.print(BIT);  Serial.print(F("     "));
    BIT =(CLKPR & (bit(CLKPS2))); Serial.print(BIT);  Serial.print(F("      "));
    BIT =(CLKPR & (bit(CLKPS1))); Serial.print(BIT);  Serial.print(F("      "));
    BIT =(CLKPR & (bit(CLKPS0))); Serial.println(BIT);
  
Serial.println(F(""));
Serial.println(F("               Test - PRR : 0x64"));
Serial.println(F("               =================="));
Serial.println(F("PRTWI PRTIM2 PRTIM0 - PRTIM1 PRSPI PRUSART0 PRADC"));  
Serial.print(F("  "));
    BIT =(PRR & (bit(PRTWI)));    Serial.print(BIT);  Serial.print(F("       "));
    BIT =(PRR & (bit(PRTIM2)));   Serial.print(BIT);  Serial.print(F("    "));
    BIT =(PRR & (bit(PRTIM0)));   Serial.print(BIT);  Serial.print(F("    "));
                                  Serial.print("-");  Serial.print(F("    "));       
    BIT =(PRR & (bit(PRTIM1)));   Serial.print(BIT);  Serial.print(F("     "));
    BIT =(PRR & (bit(PRSPI)));    Serial.print(BIT);  Serial.print(F("      "));
    BIT =(PRR & (bit(PRUSART0))); Serial.print(BIT);  Serial.print(F("      "));
    BIT =(PRR & (bit(PRADC)));    Serial.println(BIT);
   
Serial.println(F(""));
Serial.println(F("               Test - PRR1 : 0x65"));
Serial.println(F("               =================="));
Serial.println(F("  - - PRWDT - - PREFL PRPCI -"));  
Serial.print(F("  "));
                                  Serial.print("-");  Serial.print(F(" "));
                                  Serial.print("-");  Serial.print(F("   "));
    BIT =(PRR1 & (bit(PRWDT)));   Serial.print(BIT);  Serial.print(F("   "));
                                  Serial.print("-");  Serial.print(F(" "));
                                  Serial.print("-");  Serial.print(F("   "));
    BIT =(PRR1 & (bit(PREFL)));   Serial.print(BIT);  Serial.print(F("     "));
    BIT =(PRR1 & (bit(PRPCI)));   Serial.print(BIT);  Serial.print(F("   "));
	} 
 
void loop()  { /* ========================================================= */ }

 

Думаю, что кому-то пригодится для контроля настроек :-)

 

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

Измерил скорость АЦП с делителем клоков на 2.

//ADC speedtest
#include "lgtx8p.h"
void setup() {
Serial.begin(115200);
ADCSRA=1<<ADEN |0<<ADIE | 1<<ADSC | 0<<ADATE | 0<<ADPS2 |0<<ADPS1 |0<<ADPS0; // clk /2 !!!
ADCSRB=0; ADCSRD=0;
ADCSRD=1<<REFS2; VCAL=VCAL3;
ADMUX=0;     // ADC0 , AREF=4096

TCKSR=0; TIMSK1=0; TCCR1A=0; TCCR1B=0; //обнулить лишнее
OCR1A=65535u; OCR1B=65535u;// чтоб удобнее читать регистр флагов

}

void loop() {

if ( (ADCSRA&(1<<ADSC))==0   ){
cli();
TCNT1=0; TIFR1=TIFR1;
TCCR1B=1<<CS10;//подсчёт времени включён
ADCSRA|=1<<ADSC;
while ( ADCSRA&(1<<ADSC)  );
TCCR1B=0; sei();
Serial.print("Test speed ADC  ");
if (TIFR1) {Serial.println("Timer overload");} 
  else Serial.print((float)(TCNT1-2)/16); Serial.print(" uS  "); 
  Serial.print(ADC); Serial.println(" mV"); 

 }
delay(300);
}

Результат при тактовой МК 16МГц:

Test speed ADC  3.31 uS  1247 mV

Что поболее рассчётного ( 0,125 * 15 =1,875µS)  

С делителем /128 -166 µS

 

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

У Вас ко времени преобразования добавилось время обработки и подготовки. Наступал на эти грабли в это теме и тоже долго не мог понять почему не получалось снять АЦП за заявленные 13.5 тактов. Оказывается, там есть регистр-защелка вых. данных, и после выставления флага/прерывания вполне можно сначала(!) запустить следующий цикл измерений, и уже по его ходу считывать значение предыдущего замера. Только в этом случае получается то, что написано в даташите. А так, на чтение и сохранение значения уходит около 8-10 тактов ЦП (4-5 тактов АЦП при делителе 1:2), даже если его складывать в массив по автоинкременту регистра.

В общем, чтобы добиться 13.5 тактов на замер мне там пришлось нефигово попотеть пока дошло "что тут не так"..

По вашему коду: Запуск таймера перед запуском АЦП .. -2 такта ЦП; выход из цикла -1 такт и останов таймера .. -1 такт ЦП; Итого измеренное время надо уменьшить на время "накладных расходов" в 4 такта ЦП. Нет? :)

P.S. Пересчитал ваши замеры и просмотрел код внимательней. 2 такта Вы и так вычитаете при печати .. всё как-то очень странно.

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

Прибейте тему гвоздиком вверху - утонет жеж! :)

GarryC
Offline
Зарегистрирован: 08.08.2016

Ну все таки, почему не

inline void guid(uint32_t *guid) {
*((uint8_t *)guid)+0)=GUID0;
*((uint8_t *)guid)+1)=GUID1;
*((uint8_t *)guid)+2)=GUID2;
*((uint8_t *)guid)+3)=GUID3;
};

В данном конкретном случае совершенно излишне, понимаю, но код порождается ничуть не больший, зато переносимость, хотя я признал, что она не нужна.

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

Приехал с https://ru.aliexpress.com/item/WAVGAT-Nano-Mini-USB-Nano-3-0/32868170637.html?spm=a2g0s.9042311.0.0.512b33edV45Rza Пока он ехал, я забыл че хотел ;)

Фото с старшим братом. Похожи.

Тыкаю как есть в USB. Заморгал продвинутым блинком, по несколько вспышек подряд. Заливаю стандартный блинк. Успешно, но моргает в 4 раза медленей обычного. Знчить завелся на 4МГц.. Ах да аддон, выбор платы. Тяну по ссылке в начале темы папку update, из неё копирую hardware в ...\Documents\Arduino\hardware, либы пока не спешу копировать, там имена частично перекрываются с стандартными. После рестарта ИДЕ имею 3 новые платы WAVGAT: UNO, NANO и ProMini. Первые две пробовал - разницы не заметил.

Теперь блинк честно моргает с периодом 2 сек, значить 16МГц есть. Дописываем пару строк, получаем

void setup() {
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
  
 CLKPR = 1<<PMCE;//разрешить изменение
 CLKPR = B00000000;


}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

и моргает в 2 раза быстрей. Значить на 32МГц перешли.

Иду далее.

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 guid= *(uint32_t*)&GUID0 ;
Serial.println(guid,HEX); 
}

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(){}

Start..
a= 16173  b= 7522
a * b = 0
299C385A

Хмм... Умножалка не работает, а UID дает. Пробую перевести на 32МГц, добавив 2 строки аналогично блинку. Посыпался обменн.. Ну понятно, меняю скорость в скетче на 57600, а в мониторе остается 115200.

EÉѹ.
a= 16173  b= 7522
a * b = 0
299C385A
 

Хмм... Ну допустим. Но чего умножалка не пашет?

скетч из #57 дает

                Test - PMCR: 0xF2
               =================
PMCE CLKFS CLKSS WCLKS OSCKEN OSCMEN RCKEN RCMEN
  0    0     0     1     0      0      1     1

               Test - CLKPR: 0x03
               ==================
CLKPCE CLKOEN1 CLKOEN0 - CLKPS3 CLKPS2 CLKPS1 CLKPS0
  0       0       0    -    0     0      0      1

               Test - PRR : 0x64
               ==================
PRTWI PRTIM2 PRTIM0 - PRTIM1 PRSPI PRUSART0 PRADC
  0       0    0    -    0     0      0      0

               Test - PRR1 : 0x65
               ==================
  - - PRWDT - - PREFL PRPCI -
  - -   0   - -   1     0 

Из #58 тест ацп подтверждается

Test speed ADC  3.31 uS  1151 mV
Test speed ADC  3.31 uS  1151 mV
Test speed ADC  3.31 uS  1151 mV
Test speed ADC  3.31 uS  1151 mV
Test speed ADC  3.31 uS  1087 mV
Test speed ADC  3.31 uS  1203 mV
Test speed ADC  3.31 uS  1151 mV