* Не, того, для чего это надо, никто никогда не видел
Добавлено after 1 hour 33 minutes 10 seconds:
Впендюрил микрос, даже отключил чтение потенциометра и жёстко задал период - всё равно длительность полупериода дрыгается примерно в пределах 4-х мкс. Не понимяу.
Спойлер
Код:
// Set up potentiometer pin #define POT_PIN A3
// Set up clock out pin #define CLC_OUT 9
// Set up free pin (для ловли наводок) #define FREE_PIN A1
// Set up random out pin (выход данных) #define RANDOM_OUT 10
// Set up MFM out pin (выход МЧМ) #define MFM_OUT 2
int RND = 0; // текущий бит данных int RND_OLD = 0; // предыдущий бит данных unsigned int POT = 20; // полпериода в микросекундах int MFM = 0; // текущий бит МЧМ
unsigned int arr[100]; // массив случайных чисел int i=0; int j=0;
unsigned long time;
void setup() { // put your setup code here, to run once:
// Set ADC mode // Регистр настройки мультиплексора ADMUX = 0b01000011; // 0B0100011 - опорное Uпит (первые 01), 10 bit (3-й 0), A3 (последние 0011) // Регистр статуса и контроля ADCSRA = 0b11110011; // CLK/8 - ускоряем АЦП - в 8 раз ниже частоты процессора (32/8=4МГц)
// Set up pins as input pinMode(POT_PIN, INPUT); pinMode(FREE_PIN, INPUT);
// Set up pins as outputs pinMode(CLC_OUT, OUTPUT); pinMode(RANDOM_OUT, OUTPUT); pinMode(MFM_OUT, OUTPUT);
digitalWrite(MFM_OUT, MFM);
randomSeed(analogRead(FREE_PIN));
// для пинов 9 и 10 (таймер1) - для 10 кГц вроде не обязательно // TCCR1A = 0b00000001; // 8bit // TCCR1B = 0b00001001; // x1 fast pwm - 62.5 кГц - для UNO и 125 кГц - для LGT8F328P
time = micros();
}
// Main loop - put your main code here, to run repeatedly:
void loop() { // до 30 кГц без задержек на random и ускорением чтения потенциометра
for(i = 0; i < 100; i++){ // в массиве будет 100 элементов // arr[i] = random(65536); // заполним массив случайными числами // Чтобы потом в цикле не вносить задержек }
while(true){ // бесконечный цикл для основной программы
while(micros()-time < POT+10){ } time = micros();
digitalWrite(CLC_OUT, HIGH); // переключаем СLC на HIGH - тактовая частота, желателен меандр
RND = bitRead(arr[i], j); // чтение битов массива
digitalWrite(RANDOM_OUT, RND); // вывод случайных данных на 10-й пин
if (RND < 1 && RND_OLD < 1) digitalWrite(MFM_OUT, !digitalRead(MFM_OUT)); // смена логического уровня МФМ в начале // бита данных, если второй 0 подряд
j=j+1; // if(j > 15) { // последовательное чтение j = 0; // битов из массива i=i+1; // (быстрее, чем random (2)) } // if(i > 99) i = 0;
// POT = analogRead(POT_PIN); // чтение потенциометра // POT = map(POT, 20, 1000, 1, 512); // масштабируем до диапазона 1 ... 512 // POT = constrain(POT, 1, 512); // ограничиваем диапазон, чтобы исключить выбросы
if (RND > 0) digitalWrite(MFM_OUT, !digitalRead(MFM_OUT)); // переход уровня МФМ при 1 данных по спаду CLC - // в середине бита, т.е. CLC должен быть меандром RND_OLD = RND;
// POT = analogRead(POT_PIN); // // POT = map(POT, 20, 1000, 1, 512); // 25 мкс // POT = constrain(POT, 1, 512); // поэтому пока отключил
} // закрыли while
} // закрыли loop
может сам микрос в таких пределах дрыгается ... беру таймаут ...
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
"Мне говорят обидные слова. Зачем тебе, мол Коля, голова? Держать удар! Отвечу я вам всем. И, между прочим, головой я ем." Навеяло. Усы, хвосты, коты... ППЦ!
аппаратный модуль SPI, ежли программный shiftOut() не устраивает ну на крайний случай простейший "ногодрыг" вполне обеспечивает загрузку... А вот по ним урок от Гайвера: https://alexgyver.ru/lessons/max7219/ Вопрос кодогенератора и исходного ОЗУ буфера видеопамяти - то кому чего и как пожелается. Регенерация изображения в пределах матрицы выполняется самим контроллером MAX7219. Интервал загрузок для 4-8 байт не столь ж и велик (тем более, что вопросом регенерации заниматься не надо...
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
Там строка бежит и ссылку на даташит давал в начале темы, только лапы так и не добрались разобраться, куда делись полматрицы от 8-и.
А тут я написал, что тот же скетч в китайском LGT бежит в два раза быстрее.
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
Ну да, сия хрень только с микросом почти на 25 кГц тоже дрыгается:
Спойлер
Код:
// Set up clock out pin #define CLC_OUT 8 // PORTB нулевой бит PBO
unsigned long time;
void setup() {
// Set up pins as outputs pinMode(CLC_OUT, OUTPUT);
time = micros();
}
void loop() {
label:
PORTB |= (1 << 0);
while(micros()-time < 20){ }
time = micros();
PORTB &= ~(1 << 0);
while(micros()-time < 20){ }
time = micros();
goto label;
} // закрыли loop
и чё делать пока непонятно. Ладно, разборки на потом оставлю, сейчас сделаю с тем, что есть.
Добавлено after 2 hours 1 minute 53 seconds:
"Люблпытно, что команда запроса времени micros() выполняется вдвое дольше, чем millis(), хотя, по логике следовало бы сделать это наоборот.
Кстати, кто не знает, micros() округляет показания до ближайшей "четверки", т.е. результат ее выполнения всегда делится нацело на 4. Это для тактовой частоты 16 МГц. Для 8 МГц - на 8, т.е. результатом можкт быть 8, 16, 32, 48, 64, 80, 96..., но никак не 28 или 60."
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Пока что мне совершенно непонятно - а к чему такая заморочка со скоростями то нужна? Только для обслуживания вывода в беглу строку это в случае с MAX7219 совсем не требуется... Обработка чего то другого - так вроде для световых замигаек также не слишком нужно... Да и на приемопередачу можно аппаратные средства МК задействовать...
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
От ардуины надо три вывода: - тактовая частота CKC - желательно до 100 кГц, но можно и 20, желательно меандр, регулируемая внешним потенциометром, - выход данных - типа "случайные", на самом деле до лампочки, просто чтобы явно не повторялись, - дополнительный выход обработанных данных (два if'а, по одному на полупериод) - не проблема.
Вообще всё не проблема, но на 10-20 кГц уже явный джиттер - фронты CLC дрыгаются в пределах 5 мкс, что нехорошо. Боролся я с этим на форуме arduino.ru и в результате получилось избавиться от джиттера. Частота регулируется от 900 Гц (укоротил POT на четверть) до 20 кГц, стабильность нормальная.
Спойлер
Код:
// Получение последовательности псевдослучайных данных с регулируемой внешним потенциометром // стабильной частотой (без джиттера) от 900 Гц до 20 кГц.
// Set up potentiometer pin #define POT_PIN A3
// Set up clock out pin #define CLC_OUT 9 // PORTB первый бит PB1
// Set up random out pin (выход данных) #define RANDOM_OUT 10 // PORTB второй бит PB2
byte RND = 0; // текущий бит данных
int GEN=650; bool XOR=1;
unsigned int POT = 10; // unsigned int m=30; // считал, что 20 мкс - это 160 тактов при частоте 8 МГц, но получилось 30 (?) // unsigned int POT_PLUS = POT + m; // добавка для выравнивания меандра
unsigned int l=0;
void setup() {
// Set up pins as input pinMode(POT_PIN, INPUT);
// Set up pins as outputs pinMode(CLC_OUT, OUTPUT); pinMode(RANDOM_OUT, OUTPUT);
}
void loop() {
noInterrupts();
label: // до метки заполнялся массив случайных данных, пришлось убрать
XOR=bitRead(GEN, 14)^bitRead(GEN, 13); // GEN=GEN<<1; // псевдослучайная последовательность на переменной GEN (аналог LFSR) bitWrite(GEN, 0, XOR); // более стабильная, чем random (фронты CLC не дрожат)
RND=bitRead(GEN, 15); // "случайные" биты данных
// RND = analogRead(A1)&0b1; // 23-24 мкс, тоже без джиттера, но нужен шум на А1
PORTB |= (1 << 1); // фронт CLC
// Вывод данных
// digitalWrite(RANDOM_OUT, RND); // вывод данных на 10-й пин - около 3 мкс, сильный джиттер
if (RND < 1) PORTB &= ~(1 << 2); // установить 0 в бите 2 (10-й пин), всего за пару микросекунд else PORTB |= (1 << 2); // установить 1 в бите 2 (10-й пин)
POT = analogRead(POT_PIN); // "чтение" потенциометра - 23-24 мкс
POT=POT/4*3; // уменьшил, чтобы приблизить мин. частоту к 1 кГц
for (l = 0; l < POT; l++) { // задержка, определяемая потенциометром asm ("nop"); }
PORTB &= ~(1 << 1); // спад CLC
for (l = 0; l < POT+30; l++) { // добавка +30, чтобы приблизить CLC к меандру (не обязательно) asm ("nop"); }
goto label;
interrupts();
} // закрыли loop
Меандровый CLC нужен только мне для третьего выхода, а тут только "случайные" данные с регулируемой частотой. Для них меандр не нужен. Если убрать добавку +30, то отрицательный полупериод станет коротким и максимальная частота будет больше 30 кГц, стабильность не пострадает. Если после этого перенести POT = analogRead(POT_PIN); после спада CLC, то положительный полупериод CKC будет коротким, что более котфортабельно
Да, у меня китайский аналог LGT8F328P, на уне не пробовал.
* * *
Добавлено after 6 hours 17 minutes 53 seconds:
И всё было хорошо, пока мне не захотелось транслировать данные на другой выход ... ещё одна хрень выскочила из-за угла Ну это как бы внутренние данные (которые "случайные"), но было бы неплохо вместо них какие-то внешние подключить.
На 10-й пин выводятся внутренние. С 10-го пина на 11-й подключил резистор 3,9 кОм - перевёл данные с 10-го выхода на 11-й вход. А снова они выходят на 5-м пине (увидел, что там якобы больше нагрузочная способность, но не суть). Расписал это так:
Спойлер
Код:
. . . PORTD |= (1 << 2); // фронт CLC
if (RND < 1) PORTB &= ~(1 << 2); // установить 0 в бите PB2 (10-й пин) // вывод "случайных" данных else PORTB |= (1 << 2); // установить 1 в бите PB2 (10-й пин) // пара микросекунд
// int dat = (PINB & (1 << 3)); // не удлиняет период
int dat = digitalRead(RANDOM_IN); // плюс ещё пара микросекунд - чуть удлиняет период
if (dat < 1) PORTD &= ~(1 << 5); // установить 0 в бите PD5 (5-й пин) - трансляция c 3-го бита PB else PORTD |= (1 << 5); // установить 1 в бите PD5 (5-й пин)
. . .
digitalRead чётко отрабатывает функционал, хотя и длиннее на пару микросекунд. Данные на входе и на выходе идентичные и синхронные.
А вот это безобразие - int dat = (PINB & (1 << 3)); вроде должно делать то же самое и делает, но с задержкой на период клока, независимо от частоты. Т.е. делает только в следующем такте. Это какого лошадиного хрена? /(с) моё/
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
Справились с хренью:
Спойлер
Код:
PORTD |= (1 << 2); // фронт CLC
if (RND < 1) PORTB &= ~(1 << 2); // установить 0 в бите PB2 (10-й пин) // вывод "случайных" данных else PORTB |= (1 << 2); // установить 1 в бите PB2 (10-й пин) // пара микросекунд
for (int k = 0; k < 5; k++) { // задержка перед считыванием данных (надёжность записи) asm ("nop"); // нужна для срабатывания int dat = (PINB & (1 << 3)); } //
int dat = (PINB & (1 << 3));
// int dat = digitalRead(RANDOM_IN); // работает нормально, не требует задержки, +2 мкс
if (dat < 1) PORTD &= ~(1 << 5); // установить 0 в бите PD5 (5-й пин) - трансляция c 3-го бита PB else PORTD |= (1 << 5); // установить 1 в бите PD5 (5-й пин)
"Обзор от ИИ: На Ардуино нет встроенного флага подтверждения записи в порт"
Ушёл спать ...
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Неужели то каждому тактовому импульсу нужно запустить ГСЧ и выдать полученный результат на шину даных? Т. Е. Сначала запуск ГСЧ, затем вывод значения на шину данных и затем генерация строба тактирования? Или таки подобная скророспелость/садомазохизм штука излишняя? Ведь ещё и корректура частоты по АЦП вроде есть - а то процесс не слишком шустрый (с учётом всех дополнительных процессов). Может не стоит гнаться за немедленным выполнением всего вышеуказанного, а согласиться на возможность прохода одного/нескольких тактовых импульсов подряд с одинаковым значением частоты и выходных данных при заметно лучшей "прозрачности" по отношению к основной программе? Зато и стабильность генерации тактов и чёткость вывода заметно повысится. Плюс вполне доступна и основная программа будет, а не только "дрыголап".
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
Да там всё просто, только от random() фронты дрыгаются и если сначала заполнять случайный массив, а потом читать в цикле - тоже дрыгаются. Не дрыгаются, только если читать шум с висящего аналогового входа, но должен быть шум (кто-то должен стоять рядом и громко ругаться матом ) Уже хотел лепить сверхрегенератор на одном транзисторе (хорошо шумит), а потом такую штуку придумал. Там всего две строчки - сдвиг битов (типа "регистр сдвига") и запись в нулевой бит (типа "обратная связь"). Никаких дополнительных ресурсов и проблем. Другое ограничение - максимальная частота, пока только до 20 кГц, потому что дольше всего читается с потенциометра. Если можно увеличить частоту АЦП, то это интересно, но пока и 20-и хватит.
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Если выполнять на Т1 (с учетом его аппаратной начинки и прерываний) никаких дрожаний фронтов для тактового сигнала не будет. Единственно - выходной тактовый сигнал на фиксированных аппаратных выводах - перебросить на другие будет невозможно. Плюс настройки таймера придется "вне рамок референса" делать - по даташитам и с учетом соответствующих заголовочных файлов (они в IDE имеются - только поискать надо). Связь с результатом АЦП и ГСЧ по флагам запросов по готовности данных.
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Так с CLC напрямую завязан вывод заранее подготовленных данных на другой вывод. Сам тактовый сигнал формируется аппаратно на Т1. Одно из аппаратных прерываний выполняет выдачу данных в промежутках между активным статусом тактового сигнала. Быстрее уж никак не получится.
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
На прерывания я потом прервусь сейчас до 20 кГц работает и ладно. Это только небольшая часть макета, надо всё доделать, а потом буду разбираться.
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Лаподрыг то работает, но уж слишком ЖАБА давит заставлять МК только одной задачей заниматься (ежли то не тинька 13/2313)... А тут практически "без дела" аппаратный генератор с весьма приличными возможностями прохлаждается. Правда там также некоторые ограничения по максимальной частоте и шагу смены частоты имеются, но все же гораздо удачнее результат может получиться.
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
Это глобальная философия для более масштабных задач. И, разумеется, всё это надо знать и уметь использовать. Но если надо на практике просто заменить вот этим:
5-7 корпусов логики с обвязкой, то тут жаба скорее сама повесится
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Меня ЖАБА удавит использовать жирный МК для задач "программируемого периферийного контроллера", если задачу можно решить "мелколапкой" (Однако на сегодня с учетом поставок, ценовой политики и наличия комплектующих вероятно такой подход будет абсолютно не актуален ) Тем более, что у ардуино на сегодня в качестве "платформ" представлены практически все "ходовые" АВРки.. Да и ассемблер под остатки запасов мелкопиков и АВРок пока еще в силе (плюс 51я в вариантах от атмела да других). Ардуинка упрощает старт создания проекта под СИ, но не отменяет процесса продумывания программ для более удачного решения. Это всего лишь один из возможных инструментов разработки для МК АВР. Пы.сы... Ежли лень не удавит выложу чуток позже свое видение решения...
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
Вставил вот это - фронты снова дрыгаются ... в пределах около 7 мкс при длительности полупериода 25 мкс:
Спойлер
Код:
. . .
if (DAT < 1 && DAT_OLD < 1) { PORTD = PORTD^0b01000000; // в начале бита данных, если второй 0 подряд
MFM = PIND & (1 << 6);
if (MFM < 1) PORTB = PORTB & 0b11111100; // 0 - в PB0 и PB1 (операция И меняет 2 младших бита) else { if (SIDE < 1) PORTB |= (1 << 0); // 1 в PB0 (на левой стороне) if (SIDE > 0) PORTB |= (1 << 1); // 1 в PB1 (на правой стороне) SIDE = 1.3 - SIDE; // округление до целого числа (меняем сторону) } }
. . .
if (DAT > 0) { PORTD = PORTD^0b01000000; // в середине бита, т.е. CLC должен быть меандром
MFM = PIND & (1 << 6);
if (MFM < 1) PORTB = PORTB & 0b11111100; // 0 - в PB0 и PB1 (операция И меняет 2 младших бита) else { if (SIDE < 1) PORTB |= (1 << 0); // 1 в PB0 (на левой стороне) if (SIDE > 0) PORTB |= (1 << 1); // 1 в PB1 (на правой стороне) SIDE = 1.3 - SIDE; // округление до целого числа (меняем сторону) } } . . .
перед этим тоже были аналогичные операции и так не дрыгалось.
Т.е. это не из-за способа получения случайных данных, как я раньше думал. Тут какие-то другие накладки.
А функционально всё нормально работает.
Для макета и так сойдёт, напрягаться не надо. Потом можно будет спокойно разобраться. Только ещё хочу попробовать залить сие в стандартную дуньку, а не китайскую.
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Карма: 22
Рейтинг сообщений: 94
Зарегистрирован: Чт мар 26, 2009 04:35:04 Сообщений: 3135 Откуда: Москва
Рейтинг сообщения:0
И ещё 168-я атмега нано не шьётся ... если думать, что она 328-я ... совсем буржуи распоясались
Частота клока, понятно, меньше (в 3 раза) и он уже не меандр - 120 мкс высокий и 75 низкий, все фронты так же дрыгаются. А сначала не замкнул 10-й и 11-й выводы и получил такую фигню:
Уже просто интересно, откуда она взялась
_________________ (Аль Котоне,кот ещё тот,Cattus Sapiens) Усы и хвост - мои документы. Кот - авторитет! Скажет "Мяу!" - не поспоришь. (скажи мне "мяу" и я скажу кто ты)
Для каждой АВРки в адуринке своя "платформа" или опции выбора из нескольких подобных в пределах одной платформы. Настройки и фузов и бутлоадера могут заметно отличаться. Да и бутлоадеры могут иметь варианты в пределах одной платформы. Работать надо таким же набором опций, с каким выполнено ранее "инструменты ->записать загрузчик" (естественно эту операцию делаем через программатор*). Относительно "трещалки-пищалки" Вашей... Ниже вариант тестового "писка с треском" на ардуино - нано : Спойлер
#define outdat 8 // вместо D8 ставим соотвествующий (любой из возможных) номер вывода адуринки #define outclock 10 // OC1A = D9/PB1, OC1B = D10/PB2 возможные варианты вывода // сигнала Clc (OC1A при ICR=периоду, OC1B при OC1A=периоду) volatile unsigned int tmpClc; // РВХ данных периода volatile unsigned int tmpPwm; // РВХ данных активной части Clc (ШИМ) // volatile byte tmpOut; // буфер данных для вывода на линию данных volatile byte FqClc; // флаг запроса смены параметров тактового сигнала // активный уровень = 1 volatile byte FqRnd; // флаг запроса обработчика для очередного вывода данных // в tmpOut (на линию outdat в следующих циклах Clc)
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения