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

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

ua6em пишет:

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

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

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

asam пишет:

ua6em пишет:

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

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

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

 

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

DeniskaAB пишет:

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

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

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

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

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

 

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

DeniskaAB пишет:

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

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

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

Думаю что не стоит. А те кто разбираются сразу видят что различно и могут помочь. Какая ардуно я написал что такая как описано на старте темы.

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

DeniskaAB пишет:

Думаю что не стоит. А те кто разбираются сразу видят что различно и могут помочь. Какая ардуно я написал что такая как описано на старте темы.

Во первых: "На старте темы" написано - "Обзор клона меги328 -LGT8F328P". И на этом клоне только у меня дома есть 2 довольно отличные друг от друга ардуины. А сколько может их еще существовать?

Во вторых "На старте темы" написано - "Обзор клона меги328 -LGT8F328P", а не "Как мне программировать флеш используя плату на базе LGT8F328P". Так что не стоит засорять этот топик посторонними вопросами.

В третьих гадание на кофейной гуще это в другие форумы. Хотите помощи - давайте подробную информацию о вашей проблеме.

 

b707
Offline
Зарегистрирован: 26.05.2017

DeniskaAB пишет:

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

А оно им надо?

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

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

progrik пишет:

а как же char far *? до любого адреса дотягивается ведь (в пределах базовых 640КБ точно) и содержит полный 32бит адрес памяти, включая сегмент, а не только кусок в каком-то там сегменте. ...от темы я всех увел)

Не дотягивается, а может дотянутся, если не помешают. Но помешают. При попытке выйти за границу своего сегмента даст ошибку сегментации. Но это не совсем о том. Речь о компиляции. Сразу сущности присутствующие в коде разделяются по секциям. Встретился исполняемый код - помещается машинный код в свою секцию, обявлены новые данные - в свою и т.д. Адресация в каждой секции идет своя, независимая от других, после добавления очередно "порции" адрес соответственно подростает на размер "порции". Вот собственно отчего возникает то различие между указателями на функции и на данные. Таких секций обычно довольно много, даже коменты в свою могут собиратся перед тем как игнорится :) Затем по настройкам линкера эти секции в некотором порядке собираются вместе в сегменты. Для ПК это код и переменные, оба в ОЗУ, понятное дело, но с разными атрибутами, чтоб не исполнять даенные как код и не обращатся к коду как к данным, защита вобщем, но методы находятся;)  Ну а для МК - код в флеш и константы PROGMEM тудаже. А переменные в ОЗУ.  Полезно иногда в файле map посмотреть для общего развития.

hungdk
Offline
Зарегистрирован: 24.03.2018

hi Dimax! I saw you introduce LGT8F328P, I found it to be the same as the nano mode, I asked about the code, if the code is on this device, can I use it with the Arduino? thank you

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

hungdk пишет:
hi Dimax! I saw you introduce LGT8F328P, I found it to be the same as the nano mode, I asked about the code, if the code is on this device, can I use it with the Arduino? thank you

можно ))) #41 как образец использования

Stargazer
Offline
Зарегистрирован: 09.12.2018

dimax пишет:

AS31979, так обзор не для новичков был, я думал по примерам это понятно :)  Я даже не советывал бы начинающим покупать эту плату.

Золотые слова, только покупалось то как "WAVGAT Pro Mini ATMEGA328P" (чтоб они были здоровы...)

Благодаря этой теме хоть как-то задышало, а поначалу был шок :)  Кстати, при аддоне "от wavgat" времянка по millis совпадает (т.е. заветные 16МГц ©), а WDTO_2S срабатывает ровно через 8 секунд (т.е. в 4 раза дольше)

 

 

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

рискну показать результаты своего небольшого теста ADC.

правда я использовал  WEMOS XI LGT8F328D  это немного отличается от сабжа ...

Подопытными будут выступать WEMOS XI LGT8F328D и arduino Pro Mini

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

WEMOS XI

https://a.d-cd.net/X2AAAgDPYuA-1920.jpg

Pro Mini

https://a.d-cd.net/TuAAAgDPYuA-1920.jpg

затем из скетчей убрал все, что касается замера времени и вывел результат в плотер.
номер графика соответствует номеру способа замера.

WEMOS XI

https://a.d-cd.net/f2AAAgDPYuA-1920.jpg

 

Pro Mini

https://a.d-cd.net/weAAAgDPYuA-1920.jpg

 

 

mataor
Offline
Зарегистрирован: 30.01.2014

renoshnik пишет:

рискну показать результаты своего небольшого теста ADC.

хм. а что за сигнал вообще ты измерял? ножку в воздухе?

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

mataor пишет:

renoshnik пишет:

рискну показать результаты своего небольшого теста ADC.

хм. а что за сигнал вообще ты измерял? ножку в воздухе?


Переменный резистор 10кОм, ползунок примерно в среднем положении.

12val12
Offline
Зарегистрирован: 19.02.2019

Здравствуйте .на этом клоне возможно ли вывести полноценный vga(640х480  c частотой точки 25.175Мгц).?

(если пишут  заявлено 32 МГц для питания от 1.8 вольт??!!. то моя чуйка говорит что при 5 вольтах будет работать на  60МГц )

 

 А АЦП интересно  проверять закольцовыванием PWM(DAC)--фильтр--ADC

так проверял на пропуск  (монотонность ?)кодов.. при тактовой ацп меги8 800кГц еще все коды были  ,но с разной вреоятностью

//// (Codevision)-----------------ADC-PWM  loop   -------------------------------------
//ADC_PWM:   
//  DDRD.1=1;    
//  i=0;  pwm_val=50;   
//   Input= FAST_adc(5)  ;   //28 PIN     
//    for ( i=0; i<=1023; i++)  //  target 
//  {       
//     PORTD.0=0;
//     //   for ( iter=1;iter<=50;iter++)          
//     while    (Input !=i )  
//             {    
//             CS=1; // CS=1 chip deselect   
//               delay_ms(200) ;   
//              Input= FAST_adc(5)  ;   //28 PIN            
//             if (Input>i)    { pwm_val--;}
//             if (Input<i)   { pwm_val++;}    
//              if (Input==i)    { PORTD.0=1;}   //  target captured 
//           if    ( pwm_val<0 )  pwm_val=0;     //PWM signed int 
//           if    ( pwm_val>1023 )  pwm_val=1023;     
//                 OCR1BH = (char)(pwm_val>>8);
//                 OCR1BL = (char)pwm_val;
//       CS=0; // CS=0 chip select
//       print_int (0,78,white  , i)  ;   
//       print_int (0,39,yellow, pwm_val )    ;        
//       print_int (0,0, cyan, Input)  ;    
//       }   
//  }
 

 

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

12val12 пишет:

 то моя чуйка говорит что при 5 вольтах будет работать на  60МГц

Чуйка херовая, надо менять, а то попалишся.