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

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

pittyalex, таймер можно затактировать от pll 64МГц, соответссно максимальная частота с выхода таймера 32МГц. Про отладку не знаю, за неимением программатора я не угублялся в эту тему. По идее под их программатор есть USB драйвер, который виден из под студии.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Сегодня получил платку и попытал, а как у неё с Таймерами? Очень достойно!

Отклонение от расчетных данных по нулям, скетч и осциллограмма ниже:
 

/*
 * 
 * 
Results for frequency: 2250.00Hz
(1) Prescaler: 1; MaxValue: 3555; Frequency: 2249.72Hz; Diff: 0.28Hz
(1) Prescaler: 8; MaxValue: 443; Frequency: 2252.25Hz; Diff: 2.25Hz
(2) Prescaler: 32; MaxValue: 110; Frequency: 2252.25Hz; Diff: 2.25Hz
(0,1,2) Prescaler: 64; MaxValue: 55; Frequency: 2232.14Hz; Diff: 17.86Hz
(2) Prescaler: 128; MaxValue: 27; Frequency: 2232.14Hz; Diff: 17.86Hz
(0,1,2) Prescaler: 256; MaxValue: 13; Frequency: 2232.14Hz; Diff: 17.86Hz
(0,1,2) Prescaler: 1024; MaxValue: 2; Frequency: 2604.17Hz; Diff: 354.17Hz


Results for frequency: 1800.00Hz
(1) Prescaler: 1; MaxValue: 4443; Frequency: 1800.18Hz; Diff: 0.18Hz
(1) Prescaler: 8; MaxValue: 555; Frequency: 1798.56Hz; Diff: 1.44Hz
(2) Prescaler: 32; MaxValue: 138; Frequency: 1798.56Hz; Diff: 1.44Hz
(0,1,2) Prescaler: 64; MaxValue: 68; Frequency: 1811.59Hz; Diff: 11.59Hz
(2) Prescaler: 128; MaxValue: 34; Frequency: 1785.71Hz; Diff: 14.29Hz
(0,1,2) Prescaler: 256; MaxValue: 16; Frequency: 1838.24Hz; Diff: 38.24Hz
(0,1,2) Prescaler: 1024; MaxValue: 3; Frequency: 1953.13Hz; Diff: 153.13Hz



Results for frequency: 225.00Hz
(1) Prescaler: 1; MaxValue: 35555; Frequency: 225.00Hz; Diff: 0.00Hz
(1) Prescaler: 8; MaxValue: 4443; Frequency: 225.02Hz; Diff: 0.02Hz
(1) Prescaler: 64; MaxValue: 555; Frequency: 224.82Hz; Diff: 0.18Hz
(0,1,2) Prescaler: 256; MaxValue: 138; Frequency: 224.82Hz; Diff: 0.18Hz
(0,1,2) Prescaler: 1024; MaxValue: 34; Frequency: 223.21Hz; Diff: 1.79Hz
Prescaler: 128 - Not possible
Prescaler: 32 - Not possible


 * 
 */


enum Prescalers {
   PRESCALER_STOP = 0,
   PRESCALER_1 = 1, 
   PRESCALER_8 = 2, 
   PRESCALER_32 = 3, 
   PRESCALER_64 = 4, 
   PRESCALER_128 = 5, 
   PRESCALER_256 = 6, 
   PRESCALER_1024 = 7
};

// Таймера|   Делитель    |    Счетчик   |           Частоты |  Отклонение 
//      (2) Prescaler: 32; MaxValue: 138; Frequency: 1798.56Hz; Diff: 1.44Hz
//      (2) Prescaler: 32; MaxValue: 110; Frequency: 2252.25Hz; Diff: 2.25Hz
//  (0,1,2) Prescaler: 256; MaxValue: 138; Frequency: 224.82Hz; Diff: 0.18Hz


void setup() {
   uint8_t prescaler = PRESCALER_32;
   uint16_t topValue = 110;
   pinMode(11, OUTPUT);
   TCCR2A = 0x42;              // Инвертирование пина 11 по сравнению и режим CTC то OCR2A
   TCCR2B = 0x00 | prescaler;  // Установить СТС режим и делитель частоты
   OCR2A = topValue;           // установить TOP равным topValue
}

void loop() {
  delay(20000);
  uint8_t prescaler = PRESCALER_STOP;
  TCCR2B = 0x00 | prescaler;
}

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

А вот меандр, при переводе тактовой на 32Mhz совсем не меандр )))
 

enum Prescalers {
   PRESCALER_STOP = 0,
   PRESCALER_1 = 1, 
   PRESCALER_8 = 2, 
   PRESCALER_32 = 3, 
   PRESCALER_64 = 4, 
   PRESCALER_128 = 5, 
   PRESCALER_256 = 6, 
   PRESCALER_1024 = 7
};

// Таймера|   Делитель    |    Счетчик   |           Частоты |  Отклонение 
//      (2) Prescaler: 32; MaxValue: 138; Frequency: 1798.56Hz; Diff: 1.44Hz
//      (2) Prescaler: 32; MaxValue: 110; Frequency: 2252.25Hz; Diff: 2.25Hz
//  (0,1,2) Prescaler: 256; MaxValue: 138; Frequency: 224.82Hz; Diff: 0.18Hz


void setup() {
   delay(10000);
   CLKPR = 1<<PMCE;//разрешить изменение частоты кварца
   CLKPR = B00000000;

   uint8_t prescaler = PRESCALER_1;
   uint16_t topValue = 0;
   pinMode(11, OUTPUT);
   TCCR2A = 0x42;              // Инвертирование пина 11 по сравнению и режим CTC то OCR2A
   TCCR2B = 0x00 | prescaler;  // Установить СТС режим и делитель частоты
   OCR2A = topValue;           // установить TOP равным topValue
}

void loop() {
  delay(20000);
  uint8_t prescaler = PRESCALER_STOP;
  TCCR2B = 0x00 | prescaler;
}

asam
Offline
Зарегистрирован: 12.12.2018

ua6em пишет:

А вот меандр, при переводе тактовой на 32Mhz совсем не меандр )))

А какой у вас осцил? Может просто не тянет. Или щупы хреновые.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

HANTEK-6022BE
Эти щупы и для 200Mhz осциллографов предлагают, может и не тянет, правда частота всего 16 мегагерц, не 160, не 1600 )))

asam
Offline
Зарегистрирован: 12.12.2018

Нормальные пробы на 300MHz стоят дороже чем весь HANTEK-6022BE вместе взятый - https://www.mouser.com/Test-Measurement/Test-Equipment-Accessories/Test-Probes/_/N-7uqd9?P=1z0w6tm

А то, что на Ali или eBay продают под видом 300Mhz проб за 10$ - полный отстой. У нас на работе брали в рент скоп на 4ГГц, так я поигрался с пробами немного. 

asam
Offline
Зарегистрирован: 12.12.2018

Достал из загашника платку с этим 8F328P

У меня, правда, немного другая, без кварца - https://ru.aliexpress.com/item/TTGO-XI-8F328P-U-arduino-nano-V3-0-promini/32947390528.html

Так вот, нормальный там меандр на 16и МГц. Это у вас скоп или/щупы 

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Это тот скетч, что я привел? И что за модель осциллографа, явно выше 100 мгц )))

asam
Offline
Зарегистрирован: 12.12.2018

Да скетч из поста N103. А скоп, как раз, на 100МГц - Hantek DSO5102P

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

asam пишет:

Да скетч из поста N103. А скоп, как раз, на 100МГц - Hantek DSO5102P

То что 100 по осциллограмме видно ))) (затухающие колебания на нижней ступеньке как раз в районе 100 Mhz)

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

ua6em , переключите на щупе  делитель на 10  . на первой странице же об этом предупреждал.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

slider пишет:

ua6em , переключите на щупе  делитель на 10  . на первой странице же об этом предупреждал.

У меня шупы плохие, продавану я весь мозг за них вынес, но спор так и не выиграл )))
Откалибровал, так что работают что при делителе 1, что 10 одинаково, за исключением шумов, с делителем 10 - лезут

Второе, а почему при использовании таймеров такой огромный джиттер, когда программно реализую через микрос() - понятно, точность попадания как минимум 4 микросекунды, ну а через таймеры??? в чем засада?

asam
Offline
Зарегистрирован: 12.12.2018

ua6em пишет:

Второе, а почему при использовании таймеров такой огромный джиттер, когда программно реализую через микрос() - понятно, точность попадания как минимум 4 микросекунды, ну а через таймеры??? в чем засада?

Так там встроенный генератор хреновенький. А от него и все остальное дрожит. На твоей платке кварц есть? Если от кварца тактоваться разве джиттер не уменьшается?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

asam пишет:

ua6em пишет:

Второе, а почему при использовании таймеров такой огромный джиттер, когда программно реализую через микрос() - понятно, точность попадания как минимум 4 микросекунды, ну а через таймеры??? в чем засада?

Так там встроенный генератор хреновенький. А от него и все остальное дрожит. На твоей платке кварц есть? Если от кварца тактоваться разве джиттер не уменьшается?

кварц есть, что надо, чтобы от кварца тактироваться?

 

asam
Offline
Зарегистрирован: 12.12.2018

ua6em пишет:

кварц есть, что надо, чтобы от кварца тактироваться?

 

sysClock(EXT_OSC);
CLKPR = 1<<PMCE;//разрешить изменение 
CLKPR = 1<<5; // вывод clk

 

Cмотри пост №1 - http://arduino.ru/forum/apparatnye-voprosy/obzor-klona-megi328-lgt8f328p#comment-390436

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

pittyalex, таймер можно затактировать от pll 64МГц, соответссно максимальная частота с выхода таймера 32МГц. Про отладку не знаю, за неимением программатора я не угублялся в эту тему. По идее под их программатор есть USB драйвер, который виден из под студии.


Дмитрий!
А как затактироваться 64Мгц?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Продолжаю исследовать таймеры!
Ниже привожу пример использования таймера 3 и немного добавленный код в Калькулятор версии 2 от ЕвгенияП

Таймер:

// Пример использования Таймера 3 (с) UA6EM на основет заимствований на arduino.ru у DIMAX и ЕвгенийП

#include "lgtx8p.h"

enum Prescalers {
   PRESCALER_STOP = 0,
   PRESCALER_1 = 1, 
   PRESCALER_8 = 2, 
// PRESCALER_32 = 3, 
   PRESCALER_64 = 3, 
// PRESCALER_128 = 5, 
   PRESCALER_256 = 4, 
   PRESCALER_1024 = 5
};

int dig = 256;
uint8_t r3ah; 
uint8_t r3al; 

void setup() {
  uint8_t prescaler = PRESCALER_1024;
  uint16_t topValue = 0;
  if(topValue > dig){
  r3ah = topValue / dig;
  r3al = topValue % dig;
  }
  else{
  r3ah = 0x00;
  r3al = topValue;
  }
 //*(uint8_t*)0x33 =0x2; //  DDRF=1<<DDF1 // ПИН TXI
 //*(uint8_t*)0x33 =0x4; //  DDRF=1<<DDF2 // ПИН D2
 *(uint8_t*)0x33 = 0x6;  //  DDRF=1<<DDF2,DDF1 // ПИН D2 + TXI
 
 OCR3AH=r3ah;          // Важно, вначале необходимо загрузить верхний регистр!!!
 OCR3AL=r3al;          // затем нижний
                       // Нельзя как для Atmega328 -  OCR3A = topValue;
 //TCCR3A=1<<COM3A0;     // ПИН TXI
// TCCR3A=1<<COM3B0;     // ПИН D2
 TCCR3A=1<<COM3A0 | 1<<COM3B0;  // ПИН D2 + TXI
 TCCR3B=1<<WGM32 | prescaler;   // Режим СТС WGM3[3:0]=4 или 12
}

void loop(){}

 

Калькулятор для таймеров от 0 до 3 (Very TKS ЕвгенийП)

/////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Калькулятор тактов и делителя частоты СТС режима таймера/счётчика микроконтроллера ATMega328
//  Добавлена поддержка Таймера 3 микроконтроллера WAVGAT LGT8F328P ;-))) (C) UA6EM
//  
//  По заданной желаемой частоте вычисляет количество тактов для всех делителей частоты.
// Перед словом Prescaler в скобках указывается для каких таймеров/счётчиков такой результат может быть получен.
//
//  Результат выдаётся для всех делителей частоты в порядке возрастания погрешности. Делители для
//  которых такая частота невозможна, печатаются последними.
//
//  Результат считается для текущей тактовой частоты микроконтроллера, на котором на котором
//  производится расчёт. Частоту, для которой считается результат, можно изменить - см. комментарий
//  в тексте скетча.
//  
//  Условия использования:
//  
//  - допускается свободное и безвозмездное использование скетча в коммерческих и некоммерческих целях;
//  - модификация допускается только с указанием факта (и автора) модификации в заголовке файла;
//  - не допускается использование в проектах, связанных с разработкой устройств, предназначенных для
//    совершения или подготовки терактов, незаконного сбора информации и любых иных устройств,
//    предназначенных для противозаконной деятельности.
//  
//  Ответственность и обязательства автора:
//
//  - каждый разработчик может использовать или не использовать данный код на свой страх и риск;
//  - автор не несёт решительно никакой ответственности за прямые или косвенные негативные или 
//    позитивные последствия использования или неиспользования данного кода;
//  - автор с благодарностью примет сообщения о проблемах, ошибках и т.п., а также предложения 
//    по совершенствованию скетча и постарается исправить код в кратчайшие сроки, однако 
//    никаких обязательств по оперативному исправлению на себя не берёт;
//  - автор по мере возможности, сил и времени готов ответить на вопросы пользователей, но
//    обязательств на этот счёт на себя не берёт.
//
//  Расширение обязательств и ответственности автора:
//
//  - если код предполагается использовать в серьёзном проекте, где обязательства автора по 
//    исправлению ошибок и предоставлению консультаций необходимы, следует связаться с автором
//    на предмет заключения гражданско-правового договора. Тогда обязанности и ответственность 
//    автора будут определяться не настоящей декларацией, а условиями договора
//    
//  Если данный код Вам пригодился как готовый скетч, или как учебное пособие, и у Вас возникло желание
//  материально поддержать автора (что ни в коей мере НЕ является обязательным условием использования 
//  кода), Вы можете воспользоваться службой WebMoney, кошелёк № R626206676373
//
//
#include <limits.h>

///////////////////////////////////////////////////////////////////////
//
// !!! ВАЖНО !!!
//  Результат считется для текущей тактовой частоты микроконтроллера, на котором на котором
//  производится расчёт. Она доступна в константе F_CPU.
//  Если необходимо посчитать для другой тактовой частоты, следует в строке ниже вместо F_CPU
//  указать желаемую тактовую частоту в герцах. Например,
// static const double fCPU = 16000000.0;  // 8МГц
//
static const double fCPU = F_CPU;

// Всего у таймера/счётчика может быть семь делителей частоты
#define TOTAL_PRESCALERS  7 

//  Потоковая печать в Serial
template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

////////////////////////////////////////////
//
//  Класс, для расчёта количества тактов и делителя
//
//  Расчёт производится в функции Calculate по формуле 
//  со стр.123 ATmega48A/PA/88A/PA/168A/PA/328/P [DATASHEET]
//  Сначала производится прямой расчёт для данного делителя,
//  Затем, после округления, обратный и определяется разница
//  желаемой и полученной частоты.
//
class CalcResult : public Printable {
public:
  CalcResult(uint16_t p) {
    prescaler = p;
    valid = false;
  }

  void Calculate(const double freq) {
    frequency = floor(fCPU / (2.0 * prescaler * freq) - 0.5);
    if (frequency < 0.0 || frequency > (double)UINT_MAX) return;
    counter = (uint16_t) frequency;
    if ((prescaler==32 || prescaler==128) && (counter > 255)) return;
    valid = true;
    frequency = fCPU / (2.0 * prescaler * (1.0 + counter));
    difference = fabs(frequency - freq);
  }

protected:
  size_t printTo(Print& p) const {
    size_t res = 0;
    if (valid) {
      res += p.print((prescaler==32 || prescaler==128) ? "(2) " : ((counter > 255) ? "(1,3) " : "(0,1,2,3) "));
    }
    res += p.print("Prescaler: ");
    res += p.print(prescaler);
    if (! valid) return res + p.println(" - Not possible");
    res += p.print("; MaxValue: ");
    res += p.print(counter);
    res += p.print("; Frequency: ");
    res += p.print(frequency);
    res += p.print("Hz; Diff: ");
    res += p.print(difference);
    return res += p.println("Hz");
  }

private:
  uint16_t counter; 
  int16_t prescaler;
  double frequency;
  double difference;
  bool valid;

friend int cmp(const void *, const void *); 
};

/////////////////////////////////////////////////////////
//
//  Функция сравнения двух результатов для qsort
//  Правила: 
//  1. если для одного делителя результат получен, а для другого нет, то первый меньше второго
//  2. Из двух результатов меньше тот, у которого меньше difference (погрешность частоты)
//
static int cmp(const void * va, const void * vb) {
  const CalcResult * a = (const CalcResult *) va;
  const CalcResult * b = (const CalcResult *) vb;
  if (a->valid && ! b->valid) return -1;
  if (! a->valid && b->valid) return 1;
  if (! a->valid && ! b->valid) return 0;
  if (a->difference - b->difference < 0) return -1;
  if (a->difference - b->difference > 0) return 1;
  return 0;
}

////////////////////////////////////////////////////////////////||||||
//
//  расчёт для пяти делителей, сотрировка и вывод результатов в Serial
//
void CalculateParameters(const double frequency) {
  CalcResult results [TOTAL_PRESCALERS] = {
    CalcResult(1), CalcResult(8), CalcResult(32), CalcResult(64), CalcResult(128), CalcResult(256), CalcResult(1024) 
  };
  for (int8_t i = 0; i < TOTAL_PRESCALERS; i++) results[i].Calculate(frequency);
  qsort(results, TOTAL_PRESCALERS, sizeof(results[0]), cmp);
  for (int8_t i = 0; i < TOTAL_PRESCALERS; Serial << results[i++]);
}



////////////////////////////////////////////////////////////////||||||
//
//  инициализация
//
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(LONG_MAX);  
}

////////////////////////////////////////////////////////////////||||||
//
//  На каждом шаге производим расчёт для одного значения частоты
//
void loop() {
  Serial << "\nEnter desired frequency in Hz\n(use decimal point for fractions. I.e. 0.12 means 0,12Hz):\n";
  const double frequency = Serial.parseFloat();
  Serial << "\nResults for frequency: " << frequency << "Hz\n";
  if (frequency < 0) {
    Serial << "ERROR: frequency cannot be negative.\n";
  } else if (frequency > fCPU / 2.0) {
    Serial << "ERROR: frequency should not be greater then " << fCPU / 2.0 << "Hz\n";
  } else {
    CalculateParameters(frequency);
  }
}

//  собственно. всё.

Да, использование Pin TXI для вывода меандра - плохая идея, подпорка порядка 1.5 вольта, а это в логике уже за гранью добра и зла )))

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

ua6em пишет:

[А как затактироваться 64Мгц?

Тактирование таймера1 от 64 МГц
#include "lgtx8p.h"
TCKSR|=1<<F2XEN;
TCKSR|=1<<TC2XS1;
 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

ua6em пишет:

[А как затактироваться 64Мгц?

Тактирование таймера1 от 64 МГц
#include "lgtx8p.h"
TCKSR|=1<<F2XEN;
TCKSR|=1<<TC2XS1;
 

Нашёл и в даташите!
Вот видно, что ты в изучении зачитал его до дыр...
Еще один вопрос?
Инициализация порта на вывод для таймера 3 через pinMode(2,OUTPUT)  эффекта не имеет!
Как делать правильно? Средствами IDE.

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

ua6em, ну ведь прямо в аддоне есть пример. 

https://github.com/LGTMCU/Larduino_HSP/tree/master/hardware/LGT/avr/libr...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

ua6em, ну ведь прямо в аддоне есть пример. 

https://github.com/LGTMCU/Larduino_HSP/tree/master/hardware/LGT/avr/libraries/Larduino_HSPExamples/examples/lgt8fx8p_pwm_d1d2_solo_fast

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

PS
Ни один из режимов настройки пинов из нового аддона для CTC режима не подошёл )))

Так получается, что аддоны разные оказывается:

Проверочные скетчи.
Таймер 0:
 

// Пример использования Таймера 0 (восьмибитный) (с) UA6EM 
// на основе заимствований на arduino.ru у DIMAX и ЕвгенийП
#include "lgtx8p.h"

enum Prescalers {
   PRESCALER_STOP = 0,
   PRESCALER_1 = 1, 
   PRESCALER_8 = 2, 
   PRESCALER_64 = 3, 
   PRESCALER_256 = 4, 
   PRESCALER_1024 = 5
};
unsigned int counter = 0;

void setup() {
   pinMode(13, OUTPUT);
   
   uint8_t prescaler = PRESCALER_1024;
   uint8_t topValue = 255;
   pinMode(6, OUTPUT);
   TCCR0A = 0x42;              // Инвертирование пина 6 по сравнению и режим CTC то OCR0A
   TCCR0B = 0x00 | prescaler;  // Установить СТС режим и делитель частоты
   OCR0A = topValue;           // установить TOP равным topValue
}

void loop() {
  while(digitalRead(6)==LOW);
  counter++;
  if(counter==60000){
  digitalWrite(13,!digitalRead(13));
  counter = 0;}
}

Таймер 1:
 

// Пример использования Таймера 1 (шестнадцатибитный) (с) UA6EM 
// на основе заимствований на arduino.ru у DIMAX и ЕвгенийП
#include "lgtx8p.h"

enum Prescalers {
  PRESCALER_1 = 1,
  PRESCALER_8 = 2,
  PRESCALER_64 = 3,
  PRESCALER_256 = 4,
  PRESCALER_1024 = 5
};

void setup() {
  pinMode(13,OUTPUT);
  uint8_t prescaler = PRESCALER_1024;
  uint16_t topValue = 30000;
  pinMode(9, OUTPUT);
  TCCR1A = 0x40;              //  Инвертирование пина 9 по сравнению
  TCCR1B = 0x08 | prescaler;  // Установить СТС режим и делитель частоты
  OCR1A = topValue;           //  установить TOP равным topValue
}

void loop() {
  digitalWrite(13,digitalRead(9));
  }

Таймер 2:

// Пример использования Таймера 2 (восьмибитный)(с) UA6EM 
// на основе заимствований на arduino.ru у DIMAX и ЕвгенийП
#include "lgtx8p.h"

enum Prescalers {
   PRESCALER_STOP = 0,
   PRESCALER_1 = 1, 
   PRESCALER_8 = 2, 
   PRESCALER_32 = 3, 
   PRESCALER_64 = 4, 
   PRESCALER_128 = 5, 
   PRESCALER_256 = 6, 
   PRESCALER_1024 = 7  
};
unsigned int counter = 0;

void setup() {
   pinMode(13, OUTPUT);
   
   uint8_t prescaler = PRESCALER_128;
   uint8_t topValue = 255;
   pinMode(11, OUTPUT);
   TCCR2A = 0x42;              // Инвертирование пина 11 по сравнению и режим CTC то OCR2A
   TCCR2B = 0x00 | prescaler;  // Установить СТС режим и делитель частоты
   OCR2A = topValue;           // установить TOP равным topValue
  }
   
void loop() {
 while(digitalRead(11)==LOW);
  counter++;
  if(counter==60000){
  digitalWrite(13,!digitalRead(13));
  counter = 0;}
}

Таймер 3: (он несколько особенный, кстати шестнадцатибитный как и таймер1)
 

// Пример использования Таймера 3 (шестнадцатибитный)(с) UA6EM 
// на основе заимствований на arduino.ru у DIMAX и ЕвгенийП
#include "lgtx8p.h"

enum Prescalers {
   PRESCALER_STOP = 0,
   PRESCALER_1 = 1, 
   PRESCALER_8 = 2, 
   PRESCALER_64 = 3, 
   PRESCALER_256 = 4, 
   PRESCALER_1024 = 5
};

int dig = 256;
uint8_t r3ah; 
uint8_t r3al; 

void setup() {
   pinMode(13,OUTPUT);
   
  uint8_t prescaler = PRESCALER_1024;
  uint16_t topValue = 30000;
  if(topValue > dig){
  r3ah = topValue / dig;
  r3al = topValue % dig;
  }
  else{
  r3ah = 0x00;
  r3al = topValue;
  }
 //*(uint8_t*)0x33 = 0x2;  //  DDRF=1<<DDF1 // ПИН TXI
 //*(uint8_t*)0x33 = 0x4;  //  DDRF=1<<DDF2 // ПИН D2
 //*(uint8_t*)0x33 = 0x6;  //  DDRF=1<<DDF2,DDF1 // ПИН D2 + TXI DDRF = 1<<2 | 1<<1;

 DDRF = 1<<2 | 1<<1;   // Разрешаем вывод в порты D1 и D2 
 
 OCR3AH=r3ah;          // Важно, вначале необходимо загрузить верхний регистр!!!
 OCR3AL=r3al;          // затем нижний
                       // Нельзя как для Atmega328 -  OCR3A = topValue;
                       // TCCR3A=1<<COM3A0;     // ПИН TXI
                       // TCCR3A=1<<COM3B0;     // ПИН D2
 TCCR3A=1<<COM3A0 | 1<<COM3B0;  // ПИН D2 + TXI
 TCCR3B=1<<WGM32 | prescaler;   // Режим СТС WGM3[3:0]=4 или 12
}

void loop(){
  digitalWrite(13,!digitalRead(2)); // L-)))
  }     

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Вот это замутили китайцы )))
Беру код Таймер 3 из поста, что выше. Если выбираю плату LGT8F328P-LQFB32-MiniEVB то светодиоды на пинах D1 и D13 blinkают синхронно, а если выбираю плату WAVGAT NANO 3.0 то блинкают, как в скетче задумано, попеременно ...

И как тут не быть? )))

Снял осциллограмму с пинов D1 и D2, а сигналы то противофазны, если выбрать LGT8F328P-LQFB32-MiniEVB

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Выходит что аддоны корявые.
Сигналы на выходных пинах от Таймера 3 противофазные.
 

 

progrik
Offline
Зарегистрирован: 30.12.2018

dimax пишет:
Предлагаю другой вариант чтения GUID, без всяких байтовых сдвигов.

uint32_t guid= *(uint32_t*)&GUID0 ;

не многовато буков? ))

у меня такой микрухи пока нет, и очень лень проверять на чем либо другом, но должно работать и будет понятнее так:

uint32_t *guid = &GUID0;

а вот это вот все вот это вот *(uint32_t*) это лишнее)) мы указателю на тип uint32 присвоили адрес первого байта числа, все. а в твоем случае ты сразу извлекаешь значение, и это в значительной мере затрудняет понимание кода и побуждает новичка поскорее закрыть код и просто посмотреть - работает или нет. ногу сломишь. и еще в твоем варианте создается переменная и выделяется память 32бита под ее значение. в моем - экономия, храним только указатель. и по скорости - не нужно копировать значение в другую область памяти..

если ошибаюсь - раскодируюсь и напьюсь))

sadman41
Offline
Зарегистрирован: 19.10.2016

А теперь нам надо, положим, сделать guid|=0xFF ...

progrik
Offline
Зарегистрирован: 30.12.2018

блин, точно! а вдруг мне из считанного из ADCH 8-ми битного значения, положим, захочется сделать int32_t, и реверснуть его биты. не знаю зачем, но "теперь нам надо". значит под adc буфер _надо_ выделить не 256 байт, например, а 1024. без вариантов. а я сразу не подумал. пойду скетч поправлю...)))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

progrik пишет:

dimax пишет:
Предлагаю другой вариант чтения GUID, без всяких байтовых сдвигов.

uint32_t guid= *(uint32_t*)&GUID0 ;

не многовато буков? ))

у меня такой микрухи пока нет, и очень лень проверять на чем либо другом, но должно работать и будет понятнее так:

uint32_t *guid = &GUID0;

а вот это вот все вот это вот *(uint32_t*) это лишнее)) мы указателю на тип uint32 присвоили адрес первого байта числа, все. а в твоем случае ты сразу извлекаешь значение, и это в значительной мере затрудняет понимание кода и побуждает новичка поскорее закрыть код и просто посмотреть - работает или нет. ногу сломишь. и еще в твоем варианте создается переменная и выделяется память 32бита под ее значение. в моем - экономия, храним только указатель. и по скорости - не нужно копировать значение в другую область памяти..

если ошибаюсь - раскодируюсь и напьюсь))

У меня есть, полный скетч приведите, я проверю )))

sadman41
Offline
Зарегистрирован: 19.10.2016

progrik пишет:

блин, точно! а вдруг мне из считанного из ADCH 8-ми битного значения, положим, захочется сделать int32_t, и реверснуть его биты. не знаю зачем, но "теперь нам надо". значит под adc буфер _надо_ выделить не 256 байт, например, а 1024. без вариантов. а я сразу не подумал. пойду скетч поправлю...)))

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

progrik
Offline
Зарегистрирован: 30.12.2018

кто в своем уме захочет менять фактически константу?

вообще надо все проверять, я не знаю, как работает этот мк...

progrik
Offline
Зарегистрирован: 30.12.2018

ua6em пишет:
У меня есть, полный скетч приведите, я проверю )))

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

и это

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

по моему должно выводить одно и тоже

просто uint32_t guid= *(uint32_t*)&GUID0; меняется на uint32_t *guid = &GUID0; имхо так понятнее = указатель обрел адрес)))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

progrik пишет:

ua6em пишет:
У меня есть, полный скетч приведите, я проверю )))

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

и это

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

по моему должно выводить одно и тоже

просто uint32_t guid= *(uint32_t*)&GUID0; меняется на uint32_t *guid = &GUID0; имхо так понятнее = указатель обрел адрес)))

GUID0-Read:14:25: error: invalid conversion from 'uint32_t* {aka long unsigned int*}' to 'long unsigned int' [-fpermissive]

exit status 1
no matching function for call to 'println(uint32_t*&, int)'
 

progrik
Offline
Зарегистрирован: 30.12.2018

ну да, я звезду перед guid забыл

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

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

progrik пишет:

ну да, я звезду перед guid забыл

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

 cannot convert 'volatile unsigned char*' to 'uint32_t* {aka long unsigned int*}' in initialization

 #define GUID0 (*((volatile unsigned char *)0xF3))

progrik
Offline
Зарегистрирован: 30.12.2018

ааа, я вообще по диагонали смотрю) вопрос снят) таки приводить тип нужно явно.

посыпаю голову пеплом)

зы: в далекие времена на Си можно было указателю присвоить адрес функции, и потом вызвать эту функцию, написав имя переменной со скобками, как будто она и есть функция... а тут такие нежности, уже нельзя пошалить с указателями, фи, как грубо))

спасибо за потраченное время. обратно хочу себе 286-й на 20 МГц 1 МБ оперативы и 41 МБ винт, MS-DOS 6.22 и какой-нибудь нортон коммандер и турбо-Си ))

ЗЫ: наверное, можно прям в библиотеке от микрухы рядышком с дефайнами GUID0,GUID1.. прописать

#define GUID (*((volatile uint32_t *)0xF3))

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

DeniskaAB
Offline
Зарегистрирован: 19.01.2019

Приветствую. Тоже приобрел данное устройтво, хотел сделать с ребенком мини плоттер из старых DVD, как теперь разобраться чтоб переделать программы, даже либа серв не работает на нем. А я уже и драйверы и шиелд купил под это дело. Без сишки никак? Как в документации разобраться что значат обозначения в таблице выводов?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DeniskaAB пишет:

Приветствую. Тоже приобрел данное устройтво, хотел сделать с ребенком мини плоттер из старых DVD, как теперь разобраться чтоб переделать программы, даже либа серв не работает на нем. А я уже и драйверы и шиелд купил под это дело. Без сишки никак? Как в документации разобраться что значат обозначения в таблице выводов?

обязана работать если всё сделано по инструкции (тип платы правильно выбран)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

progrik пишет:

зы: в далекие времена на Си можно было указателю присвоить адрес функции, и потом вызвать эту функцию, написав имя переменной со скобками, как будто она и есть функция... а тут такие нежности

Дак и щас можно


using pvfError = void(*)(int);    // pointer to void function(int)

pvfError onError;           // переменная, где храница адрес такой функции

void error(int errorcode){   //  функция, обрабатывающая ошибки
.
.
}

int main(){
.
onError = error;         // в переменную пхаем адрес функции
.
.
.
if (onError != NULL) onError(err_OutOfMemory);  // вызываем
.
.
}

 

RG22EM
Offline
Зарегистрирован: 27.08.2016

Поиск переднего или заднего фронта импульса(немного исправил):
 

#include "lgtx8p.h"

int flag = 0;
int pin_strobe = 9;

enum Prescalers {
  PRESCALER_1 = 1,
  PRESCALER_8 = 2,
  PRESCALER_64 = 3,
  PRESCALER_256 = 4,
  PRESCALER_1024 = 5
};

void setup() {
  pinMode(13,OUTPUT);
   pinMode(1,OUTPUT);
  
  uint8_t prescaler = PRESCALER_1024;
  uint16_t topValue = 1562;
  pinMode(9, OUTPUT);
  TCCR1A = 0x40;              //  Инвертирование пина 9 по сравнению
  TCCR1B = 0x08 | prescaler;  // Установить СТС режим и делитель частоты
  OCR1A = topValue;           //  установить TOP равным topValue
}

boolean strobe_high(int pin){
 int result;
 if(digitalRead(pin)== HIGH && flag == 0){
 flag=1; result = 1;} else{ result = 0;}
 if(digitalRead(pin)==LOW){flag=0; result = 0;}
 return result;
}

boolean strobe_low(int pin){
 int result;
 if(digitalRead(pin)== LOW && flag == 0){
 flag=1; result = 1;} else{ result = 0;}
 if(digitalRead(pin)==HIGH){flag=0; result = 0;}
 return result;
}

void loop() {
  digitalWrite(13,digitalRead(9));
 // if (int strobe=(strobe_high(pin_strobe)) == 1) digitalWrite(1,!digitalRead(1));
  if (strobe_low(pin_strobe)) digitalWrite(1,!digitalRead(1));
  
}

 

progrik
Offline
Зарегистрирован: 30.12.2018

DetSimen пишет:
Дак и щас можно
ну ты объявил указатель на функцию, а сделай тоже самое, например, с char * :) может я сильно путаю, но еще ковыряясь на 286 проце с 1МБ мозга и 41МБ винт я сам обнаружил это, пока игрался с указателями. могу сильно ошибаться ибо память, уже лет 28+ как прошло...

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

в случае с копированием значения пускай себе проверяет типы, а для адреса зачем? хотя тут ему пофиг что куда присваивать, байт, сигн/ансигн инт, долби, бул - присваивай в любом порядке. то есть, подразумевается, что ты знаешь, что делаешь... это же двойные мать его стандарты! когда ты байту присваиваешь инт32 - теряешь 3/4 верхних байтов или инт32 присваиваешь булевое - не, не о чем предупреждать, твои проблемы. а адрес попросил - ругается. хочет явного указания типа - ладно, бум указывать. но имхо по задорнову - ну вы... компилятор перепишите))

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

progrik пишет:

ну ты объявил указатель на функцию, а сделай тоже самое, например, с char * :) может я сильно путаю, но еще ковыряясь на 286 проце с 1МБ мозга и 41МБ винт я сам обнаружил это, пока игрался с указателями. могу сильно ошибаться ибо память, уже лет 28+ как прошло...

Не было такого.  по указателю на char*  функцию не вызовешь.  всё равно предварительно кастовать надо.  

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Хотя, я не профессионал, надо у взрослых спросить.

progrik
Offline
Зарегистрирован: 30.12.2018

DetSimen пишет:
Хотя, я не профессионал, надо у взрослых спросить.
я тоже не профессионал. мне профик только подарил книгу Си на порезанной ленте. долго она в туалете лежала, пока от корки до корки не выучил. два раза) и с тех пор я пропал) такой себе доморощенный кодер-вебмастер-электроннщик-механька-абортмахер))) (последнее вычеркнуть)) все на уровне "с чем столкнулся - то и решил". мне не нужны горы академических знаний. вон, обезьяна знает, что такое палка, и как ее можно использовать))

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

DetSimen пишет:

Хотя, я не профессионал, надо у взрослых спросить.

Небыло. Они в разных сегментах памяти потому и не работает. Код по адресу 0х1234 и данные на таком же адресе - две большие разницы, хотя указатели численно и равны будут. Компилятор их в разные сегменты сует. Для МК это какбыдаже очевидно - одно во флеше другое ОЗУ. У ПК оба в ОЗУ, а сегменты разные.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Logik пишет:

DetSimen пишет:

Хотя, я не профессионал, надо у взрослых спросить.

Небыло. Они в разных сегментах памяти потому и не работает. Код по адресу 0х1234 и данные на таком же адресе - две большие разницы, хотя указатели численно и равны будут. Компилятор их в разные сегменты сует. Для МК это какбыдаже очевидно - одно во флеше другое ОЗУ. У ПК оба в ОЗУ, а сегменты разные.

У пк ФЛЭШ в одном сегменте с озу, как бы чернобыль жил )))

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

ua6em пишет:

У пк ФЛЭШ в одном сегменте с озу, как бы чернобыль жил )))

нда... Кто на ком стоял говорите?

progrik
Offline
Зарегистрирован: 30.12.2018

Logik пишет:
Небыло. Они в разных сегментах памяти потому и не работает. Код по адресу 0х1234 и данные на таком же адресе - две большие разницы, хотя указатели численно и равны будут. Компилятор их в разные сегменты сует. Для МК это какбыдаже очевидно - одно во флеше другое ОЗУ. У ПК оба в ОЗУ, а сегменты разные.
а как же char far *? до любого адреса дотягивается ведь (в пределах базовых 640КБ точно) и содержит полный 32бит адрес памяти, включая сегмент, а не только кусок в каком-то там сегменте. ...от темы я всех увел)

короче, микруха классная, надо брать!))) жаль, что SPI почти на любой скорости (ну, до вменяемых 32МГц, больше не тянут дисплейчики) не даст и половину скорости параллельного интерфейса, ибо spi это тупо узкий расширитель портов. но это уже такое...

DeniskaAB
Offline
Зарегистрирован: 19.01.2019

А это будет работать? Если нет то как изменить?

http://skproj.ru/programmator-spi-flash-svoimi-rukami/?from=flasher

asam
Offline
Зарегистрирован: 12.12.2018

DeniskaAB пишет:

А это будет работать? Если нет то как изменить?

http://skproj.ru/programmator-spi-flash-svoimi-rukami/?from=flasher

А вы попробуйте и тут расскажите.

DeniskaAB
Offline
Зарегистрирован: 19.01.2019

Я не разберусь. Собрал по схеме и ничего не происходит

 

asam
Offline
Зарегистрирован: 12.12.2018

DeniskaAB пишет:

Я не разберусь. Собрал по схеме и ничего не происходит

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