Генератор с регулируемоей частотой на ардуино.

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

kloker, кстати намедни на радиокоте выложили проект генератора на F303, видели?  Он конечно в разных весовых категориях с моим. По всем возможностям обходит мой, его смело можно отнести в категорию "измерительный прибор" ибо и аппаратно и программно соответствует, таких широких возможностей у самоделок я вообще никогда раньше не видел (!). Автор основательно поработал.  Но в отличии от моей поделки  в сборке  сложен, - требует изготовления печатных плат,  подетальной пайки, в общем только для опытных радиолюбителей.  Пробежавшись по характеристикам всё таки нашёл узкое место- частота дискретизации в режиме DDS всего 1.4МГц   . (У моего 4,5 МГц при  F_CPU= 72MHz &&  выводе в встроенный цап ). А ещё немаловажно, что обещает автор - проект будет развиваться.

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

К теме как отличить настоящий МК, сфоткал сейчас свой блюпил, у меня надписи читаются без труда (фотка кликабельна).

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

MAG-N пишет:
Так я выше сказал - замените на "Hz". Так будет правильнее.

заменил. обновил библиотеки в выложенном комплекте, поправил сдвиги. все работает. спасибо автору за полезный девайс.

а si5351 только меандр умеет выдавать? хотя конечно и цап неплохую форму выдает на довольно приличных частотах, но не на мегагерцах конечно. резисторы в делитель брал smd с допуском 1%.

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

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

venus, ещё adg704 давит фронты. У него заявлена пропускная способность что-то вроде до  200 МГц, но под этой цифрой подразумевается синус :) Если я когда нибудь буду переносить в другой корпус, то коммутацию сделаю на релюшках, как Mag-N. Может даже шикану, и куплю мелкие вч-релюшки.

PS про Herz я как-то и незадумывался, с буквой t оно даже симметричнее смотрится, надо тоже исправить  :)

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

venus пишет:

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

Я герконовые поставил, у них при пяти вольтах ток срабатывания меньше 10 мА - подключены напрямую к выходам дешифратора 74138. Вот такие:

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

по поводу реле - я тоже у себя использовал, в посте 81 писал. хз насколько высокочастотные, но мелкие, с 3.3в питанием и 30ма потреблением, по адекватной цене на али - G6K-2F-Y

да, если разводить - не стоит забывать что они имеют полярность.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

В данной конструкции можно любые малогабаритные реле использовать. Это ведь не реле обхода антенного усилителя или РА, где ВЧ напряжение 100-200 В и более.

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

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

загрузчик брал последний в теме. он, помнится, boot1 джампер использует вместо ресета, так что можно постоянно плату держать под прошивку. вот только у меня почему-то устройство usb только serial с pid=0004 появляется, а под прошивку pid=0003 упорно отсутствует, в том числе после добавления резистора с A12 на 3.3. и разъем microusb был дрянной родной, пропайка не помогла, поменял, но на usb-устройства само собой не повлияло. так что мне проще stlink'ом пользоваться. хотя в принципе неважно, девайс уже в корпус закинул, выбросив потроха из ростелекомовской iptv-приставки. брендовый девайс получился. :)

вольтметр зацеплен на аккум и немного подвирает, на 2%, на входе резистор больший воткнул без подбора. наверное, стоит коррекцию прямо в коде поставить.

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

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Заметил одну особенность : очищаем память контроллера, заливаем загрузчик. Далее прошиваем хоть Блинк, хоть Графиктест или что-то подобное и так раз 20 подряд - всё прошивается без лишних телодвижений. Но стоит прошить любую версию данного генератора, и для следующей прошивки надо давить РЕСЕТ. Если затем опять загрузить что-то другое (через РЕСЕТ), то автоматическая загрузка восстанавливается. Загружаем генератор - и опять те же Я...  Положение джампера BOOT1 никак не влияет.

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

MAG-N, я вроде писал про это. В скетче отключается всё лишнее, в том числе прерывания USB, без них не работает USBCDC, который образует ком-порт, без него IDE не может инициировать загрузку бутлоадера.

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

в режиме pwm, если поставить шаг 1E4, на второе увеличение частота прыгает на 36MHz.

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

venus пишет:

в режиме pwm, если поставить шаг 1E4, на второе увеличение частота прыгает на 36MHz.

Это из-за того, что на частотах выше 8кГц нет привязки шага к герцам. Можно ввести доп условие:

  if (tim_arr<10000 && encstep > 10000) encstep=10000; // уменьшать шаг с ростом частоты

И тогда не будет так резко скакать.

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

чисто для частотометра http://www.radioscanner.ru/forum/topic38601.html

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

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Собирал я этот формирователь (по номиналам деталей похож на тот, что с Радиосканнера)- и сейчас он работает, но у него нижний предел частоты был порядка нескольких сотен герц. Добился нижнего предела 1 Гц, для чего параллельно С2 поставил керамику 10 мкФ, а параллельно С7 и С10 - электролиты по 100 мкФ. При этом верхний предел упал где-то со 100 до 80 МГц. Мне нижний предел важнее был. А чувствительность - это питания полевику маловато, не зря в "Фрегате" он от 12В питается. В даташите на транзистор явно указано "VHF and UHF applications with 12 V supply voltage"

Tvics
Offline
Зарегистрирован: 12.04.2017

dimax, спасибо за генератор. Хороший приборчик, сделал усилитель на DDS OUT, но пока мучась идут искажения. Время будет доделаю.

man_200
Offline
Зарегистрирован: 29.04.2016

Dimax, тебе уже задавали этот вопрос на другой ветке, но позволю себе повториться: как программно, аппаратно или комплексно промодулировать сигнал Si5351? Предлагалось изменять биты управления, но как это практически сделать видимо так никто и не понял, а мне тем более не разобраться. Думаю, что одной частоты модуляции в 1000Гц всех устроило бы.

Спасибо!

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

man_200 пишет:

как программно, аппаратно или комплексно промодулировать сигнал Si5351? Предлагалось изменять биты управления

Он для  этого не предназначен. У AD985x есть токовый выход, там нетрудно сделать внешнюю амплитудную модуляцию. Так же там можно сделать частотную модуляцию -при подключении в 8бит параллельном режиме можно с высокой скоростью задавать частоту. Всего этого у Si нет.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

У Si5351 есть нога VddOut - питание выходного буфера, оно хоть в даташите конкретными значениями обозначено (Output VDDO: 1.8, 2.5, or 3.3 V), но может и как вход для АМ заработает? Тут пробовать надо. Вот только кому эта АМ нужна, разве что самолеты с землей работают. Как это ни странно, но до сих пор обмен на взлете-посадке идет в режиме АМ, хоть Боинг, хоть Кукурузник.

 

man_200
Offline
Зарегистрирован: 29.04.2016

MAG-N, это сообщение редактировалось. Поначалу плата Си и дисплей питались от USB, а после перепайки резисторов всю схему запитал от стаба STM.

Видимо придется ставить отдельные схемы модуляторов АМ и ЧМ, а Си использовать как задающий генератор

alex410
Offline
Зарегистрирован: 29.02.2020

Подскажите как в прошивке под stm32 прописать свою форму сигнал, ступеньки аля видеосигнал? в версии 2.4 это было легко, а тут не соображу

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

alex410, в 3.x это сложнее сделать, т.к. все готовые формы рассчитываются математически. Но суть будет такая же - создать массив на 512 байт, поместить его в флэш  my_mass[]  __FLASH__ ={ тут форма на 512 байт};  а в функции, где идёт расчёт и заливка массива в памяти вместо расчёта скопировать данные  из своего массива в основной.

alex_f73
Offline
Зарегистрирован: 17.03.2020

Всем привет. Собрал на печатке и вот какая засада. Заработал, почти сразу, только ресет как подпаял, забыл сразу. Через некоторое время вставляя холдер с аккумом, пока без тумблера, и не запускается. Экран сначала желтый потом срабатывает заливка черным и все, нет ничего более, генерации тоже нет. Аккумом 18650 питаю через Step Up, дает 4.99 с питанием норм. Не пойму на чем может тормозится программа. Кроме Блупилл, экрана и энкодера ни чего нет. Я так понял в коде ни чего не надо менять под такой конфиг?

Исправил, удалил вот эти строки и заработало:

	//si5351_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);//если нашёлся si5351 поднимается флажок
	//if (si5351_found == 1) { si5351.set_freq(16E6*SI5351_FREQ_MULT, SI5351_CLK1);// фиксированная частота с выхода 1
		//si5351.set_freq(20E6*SI5351_FREQ_MULT, SI5351_CLK2); }//фиксированная частота с выхода 2

Еще, может кому пригодится. У меня было смещение изображение небольшое, скомпенсировал в файле Adafruit_ST77xx.cpp

  x += _xstart+1; // добавил один пиксель по x
  y += _ystart+2; // добавил два по y

 

man_200
Offline
Зарегистрирован: 29.04.2016

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

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

man_200, честно говоря, уже не помню. вероятно, все это было здесь: http://venus.rontel.ru/gen35/

прошивка - обычная 3.5 с минимальной косметикой. ну и под делитель мой откалибрована, дабы правильно напряжение аккума показывать. которая с "144greentab" в названии - не под мой дисплей, а чей-то еще.

Silver_D
Offline
Зарегистрирован: 21.04.2020

Доброе время суток. Захотелось собрать это устройство, уже начал рисовать печатку. Решил проверить на макетке, залил 3,5 версию через СТ-линк, заработало, но, вывод изображения получилось перевернутым, тоисть контакты справа, а здесь смотрю у всех слева. Хорошо что не спешил делать плату.

 

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

Silver_D, в скетче нужный поворот задаётся функцией

tft.setRotation();

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

dimax я что то краем глаза глянул даташит и не увидел как записать данные в NVM ? Что бы стартовал на нужной мне частоте ?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

dimax Я не об этом ... В описании Si5351 написано что есть NVM память, из которой берутся настройки в момент старта Si5351. Я так понял что можно рассчитать данные для всех выходов, записать их в эту память и потом при старте нужные частоты будут на выходах без участия МК. Но вот как записать данные в эту память не увидел.

The Si5351 is a highly flexible clock generator which is entirely configurable through its I2C interface. The device’s default configuration is stored in non-volatile memory (NVM) as shown in Figure 11. The NVM is a one time programmable memory (OTP) which can store a custom user configuration at power-up. This is a useful feature for applications that need a clock present at power-up (e.g., for providing a clock to a processor).

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

Komandir пишет:

 Я так понял что можно рассчитать данные для всех выходов, записать их в эту память и потом при старте нужные частоты будут на выходах без участия МК.

вот это интересно, тоже хочу такое :) Почитаю.

PS: Разобрался.

How can I burn the NVM on a blank Si5351 part?Silicon Labs does not currently support customer NVM burning for this product family. However, you can easily create a new custom part with a newly defined default startup state using ClockBuilder Pro. Once the part is submitted at the end of the process,you will be able to contact your local distributor to order the new part number.

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

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013
Версия 3.6
Что нового:
-"Адаптивное" тактирование МК от si5351, за счёт чего: 
- регулировка частоты в PWM режиме стала линейной вплоть до конца диапазона. (условное ограничение на 1МГц, выше будет уменьшаться число градаций duty). 
-DDS режим теперь иначе сделан - не использует весь вычислительный ресурс МК, а работает "в фоне" через DMA. 
-добавлена возможность измерять среднеквадратичное напряжение в режиме генерации синуса. Это удобно, если
  сделана регулировка амплитуды переменным резистором.
-Сохранение настроек частоты, режима и шага при отключении питания (при наличии подключенной батарейки)
-режим "Meandr DDS" ввиду бесполезности заменил на режим "Noise DDS" (генератор шума)
-больше нет поддержки МК F103 с встроенным ЦАП
-больше нет поддержки фиксированных тактовых частот МК 72 /128 МГц  -МК автоматически задаст себе нужную тактовую частоту в зависимости от требуемой 
выходной, примерный диапазон перестройки тактовой не более 2МГц (98..100МГц, т.е. МК работает с небольшим разгоном.)
 
Новые тех. характеристики генераторов:
Управление тактовым генератором Si5351, "меандр":
Диапазон частот:  4кГц - 225 МГц
Шаг перестройки частоты: 1Гц ... 10МГц  
 
Генерация PWM/DDS :
Диапазон частот : 0,1 Гц – 1 МГц; 
Шаг перестройки частоты:  0,1Гц ... 100 кГц  
Частота дискретизации DDS: переменная,  до 7,7 МГц при 100 МГц тактовой.
Кол-во градаций регулировки заполнения PWM: 99 (от1 до 99%)
 
Изменения и советы по  аппаратной части:
- Схема от предыдущих версий отличается очень незначительно, всё тот же bluepill на stm32f103c8t6 как основа,
но подойдут только версии с 128к флэша. (Узнать можно программатором) Либо взять МК  stm32f103cbt6, в котором 128к обязано быть. si5351 теперь обязательный компонент проекта, т.к. он тактирует МК. Необходимо отпаять на плате микроконтроллера кварц и конденсатор от ноги PD0, а на  PD0 подать тактовый сигнал с вывода CLK0 si5351, очень желательно подвести и отдельную землю от выхода si5351. От этого соединения сильно зависит стабильность работы, поэтому надо сделать максимально качественно. 
-программа использует бэкап-регистры, для корректной работы должна быть подключена батарейка, при отсутствии её  подать  на вывод Vbat напряжение 3,3. вольта.
-Не желательно питать от дешевого импульсного источника (в режимах DDS возможны помехи)
-Улучшена защита от дребезга кнопки энкодера (изменено подключение RC-цепочки). 
-Применение мультиплексора как и ранее опционально, коммутация высокочастотного сигнала от si5351 через мультиплексор не желательна. Либо подключаться напрямую к разъёму на плате si5351, либо использовать реле (вариант от MAG-N в сообщении #57)
-для корректного измерения не-TTL высокочастотных сигналов в режиме "частотометр" желательно использовать специальный усилитель-формирователь в TTL, и подавать сигнал не коммутируя его прямо на пин А15 платы. Можно сделать простой пассивный формирователь TTL из конденсатора и 2х резисторов , который формирует смещение примерно 1,7 вольта для чёткого соответствия TTL уровням.  В этом случае входной амплитуды Vamp=1вольт должно быть достаточно для работы частотометра. Для меньших входных напряжений у измеряемой высокой частоты необходим вч-усилитель. 
 
Информация по программе:
Аддон (от Роджера Кларка) немного модифицировал, добавив новый профиль для платы,
что бы начальную конфигурацию программа прошла тактируюясь от встроенного в мк генератора (64МГц с учётом множителя на 16) , а не от кварца. После стандартной инициализации запускается генератор si5351, с частотой 25МГц с выхода CLK0, который идёт на вход OSC_IN (PD0) микроконтроллера. Далее в программе перенастраивается тактирование на внешний вход и включается умножение x4. В режимах PWM и DDS тактовая частота МК  подстраивается под необходимую выходную частоту. 
Так же сделаны мелкие модификации библиотек: ( SPI -что б дружила с самой последней версией графического драйвера от адафрута.
si5351 -что б не глючил при переходе через частоту 170MHz )
Ввиду этого разумнее будет либо заливать готовый BIN программатором, если менять под себя ничего не нужно. Либо скачать мой заархивированный ArduinoIDE со всеми необходимыми библиотеками и модификациями и уже из него компилировать. Скетч генератора уже есть в архиве, отдельно вставлять не надо (Файл-> Примеры -> 12.Generator_v3_6) 
-Объём скомпилированной прошивки уже перевалил за 80к, так что в меню МК надо выбирать stm32f103cb у которого размер флеша 128к. (скриншот выбора платы в меню выше)
-не проверялась возможность загрузки через бутлоадер, я грузил через STLINK
 
Схема:
 
Скетч:
/*       Генератор с регулируемой частотой v3.6  (C)Dimax         */
    #define pwm2_polar 0 //полярность выхода PWM2 (вывод PA7)
   #define paper        0x000000 // цвет фона экрана
//для пересчёта множителя необходимо: частоту на экране прибора * текущий множитель и разделить на фактически измеренную частоту
#define VrefINT 1209  //внутренее опорное напряжение в милливольтах 
 #define Mn 6.06  //множитель для пересчёта напряжения с учётом резисторного делителя.
#define SHOWVRMS 1 //измерять ли напряжение в режиме генерации синусоиды: 0-нет 1-да
#define DDSFREQMAX 5000000  //максимальная частота DDS *10
#define PWMFREQMAX 10000000  //максимальная частота PWM *10
#define FREQDEFAULT 10000 // частота по-умолчанию * 10
#define freq_save() bkp_write(1, freq & 0xffff); bkp_write(2, freq >> 16);//сохранение переменной с текущей частотой
#define freq_restore() freq = bkp_read(1) | (bkp_read(2) << 16);//восстановление частоты
#define freq_si5351_save()  bkp_write(4, freq & 0xffff); bkp_write(5, freq >> 16);//сохранение переменной с текущей частотой
#define freq_si5351_restore() freq = (bkp_read(4) | (bkp_read(5) << 16));//восстановление частоты si5351
#define mode_save() bkp_write(3, ( (mode&0xff) | (encstep<<8)) ); //сохранение № режима и шага
#define mode_restore() mode = bkp_read(3)&0xff; encstep =bkp_read(3)>>8;//восстановление режима и шага
#include "Adafruit_GFX.h"
 #include <Adafruit_ST7735.h> // Hardware-specific library
#include <libmaple/usart.h>
   #include <SPI.h>                 //https://github.com/etherkit/Si5351Arduino/issues/65
    #include "si5351.h"  
     #include <Wire.h> 
      #include <libmaple/bkp.h>
       Adafruit_ST7735 tft = Adafruit_ST7735(-1, PB11,PB10); //PB12 освобождён, вывод CS дисплея запаять на землю.
        Si5351 si5351;
         boolean modevolt, infreqpsc;
      volatile int enc_tic=0, duty=50, mon_flag=255, modebit=1;
     volatile int16_t mode;// 0- GEN_si5351, 1-PWM, 2-Duty, 3-impuls , 4..8 DDS, 9-Freqmeter, 10-VoltMeter 
    volatile uint8_t encstep=1; //шаг изменения частоты 0 - 0,1 Гц  1 -1Гц  2-10Гц 3-100Гц  4-1000Гц 5-10 000Гц 6- 100 000Гц.... 7 -1Mhz 8-10МГц
   volatile byte imp_mode=1; //единицы счёта длины импульса  по умолчанию 0-мс, 1-мкс, 2 -такт
  volatile byte imp_mode_menu=0; //переменная выбора меню в одновибраторе (значение длины/единица времени/шаг)
 volatile uint32_t freq; //частота по умолчанию (желаемая *10)
volatile  uint64_t fcpu=1000000000; // фактическая частота МК (*10), пересчитывается в программе автоматически
  float t_hi, t_low; //переменные счёта длины импульсов 
   uint32_t Vcc; //переменная внутреннего измерения напряжения питания МК (милливольты)
   int Vin_low=0, Vin_hi=15000; //переменные пределов для вольтмера (милливольты)
    uint8_t wave[512]; //массив для таблицы DDS синтеза
     uint8_t sine_logo[] __FLASH__ ={0x17,0x18,0x19,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x23,0x24,0x25,0x26,
      0x27,0x28,0x29,0x29,0x2a,0x2b,0x2b, 0x2c,0x2c,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2c,0x2c,0x2b,
       0x2b,0x2a,0x29,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x21,0x20,0x1f,0x1d,0x1c,0x1b,0x19,0x18,0x17,
        0x15,0x14,0x12,0x11,0x10,0xe,0xd,0xc,0xa, 0x9,0x8,0x7,0x6,0x5,0x4,0x4,0x3,0x2,0x2,0x1,0x1,0x0,0x0,
         0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x2,0x3,0x4,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xc,0xd,0xe,0x10,0x11,0x12,0x14,0x15};
          void setup() {
          SPI.setModule(2);// выбор SPI2
        tft.initR(INITR_BLACKTAB);
       tft.setRotation(3);//дисплей горизонтально, контакты слева
      tft.fillScreen(paper);//залить цветом по умолчанию
    tft.setTextWrap(0);//не переносить строки
// Serial1.begin(9600); //вывод в UART1 для отладки
RCC_BASE->APB1ENR|= (1<<2)|(1<<1)|(1<<0); //включить тактирование tim-2,3,4
 RCC_BASE->APB2ENR|= (1<<3)|(1<<11)|(1<<2)|(1<<0)|(1<<4);////включить тактирование port-a-b-c,tim1
  RCC_BASE->AHBENR|=1<<0;//включить тактирование dma1
  AFIO_BASE->MAPR|=(1<<25) |(1<<8)|(1<<6); //JTAG Disabled   tim 1 && tim 2 Partial remap
   i2c_master_enable(I2C1, I2C_REMAP, 200000); //SDA PB9, SCL PB8
    Wire.begin();
   //Serial1.println("Start");
  do{ //проверка si5351, если не найден то из цикла проверки не выйдет
if (si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0)==0){ //Serial1.println("I2C address Si5351 not detected"); 
} delay(300);  
  si5351.update_status(); 
   if ( !si5351.dev_status.REVID){ //Serial1.println("Error read Si5351 ID");
      }  }  while (!si5351.dev_status.REVID);
          si5351.set_freq(2500000000, SI5351_CLK0);// будущая тактовая 25МГц  для мк с выхода0 (*100)
                  //переключение на внешнее тактирование от si5351 25MHz и pll x4
                 RCC_BASE->CFGR&=~(3<<0);//set hsi system clock
                while (RCC_BASE->CFGR&(3<<2)); 
               RCC_BASE->CR&=~(1<<24);//pll off
              while (RCC_BASE->CR&(1<<25)); 
             RCC_BASE->CR|= (1<<18)|(1<<16);// HSE on, ext osc
            while ( !RCC_BASE->CR&(1<<17)); 
             RCC_BASE->CFGR|=1<<16; // HSE oscillator clock selected as PLL input clock
              RCC_BASE->CFGR&=~(15<<18);//clear pll mul
               RCC_BASE->CFGR|=2<<18;//PLLMUL:0010 , pll input clock x 4
                RCC_BASE->CR|=(1<<24);//pll on
                 while (!RCC_BASE->CR&(1<<25)); 
                  RCC_BASE->CFGR|=1<<1;//PLL selected as system clock
                   while (!RCC_BASE->CFGR&(2<<2)); 
                    RCC_BASE->CR&=~(1<<0);// hsi off
//usart_set_baud_rate(USART1, 100000000, 9600); //смена настройки UART на новую тактовую частоту
systick_init(SYSTICK_RELOAD_VAL);
 pinMode(PB0,PWM); //buzzer
  pinMode (PB1,INPUT_ANALOG); // вход АЦП
   pinMode(PB5,INPUT_PULLUP);//key encoder 
    pinMode(PB3,OUTPUT); //мультиплексор
     pinMode(PB4,OUTPUT); //мультиплексор
      pinMode(PB6,INPUT_PULLUP);//encoder
       pinMode(PB7,INPUT_PULLUP);//encoder
        mytone(1000,50);//сигнал после старта
      attachInterrupt(PB5, key_enc_int, RISING);//прерывание кнопки энкодера
     attachInterrupt(PB6, enc_int, CHANGE); attachInterrupt(PB7, enc_int, CHANGE);//прерывания энкодера
   adc_enable_single_swstart(ADC1);//запуск АЦП
   ADC1->regs->CR2 |= ADC_CR2_TSVREFE; // Enable VREFINT conversion
  ADC1->regs->SMPR1=3<<21;  //ADC (vrefint) Sample time = 28.5 cycles 
 ADC1->regs->SMPR2=3<<27; //ADC (channel 9) Sample time = 28.5 cycles 
bkp_init();  bkp_enable_writes();           
//если что-то есть в bkp регистрах сохранённой частоты, то восстановить последнюю частоту , режим и шаг
 if ( bkp_read(1) || bkp_read(2) ) {freq_restore(); mode_restore(); }
// иначе загрузить частоту и режим  по-умолчанию
   else { mode=1; freq=FREQDEFAULT;  freq_save(); mode_save(); }
   si5351.set_freq(   (bkp_read(4)|(bkp_read(5)<< 16)) * 10ULL, SI5351_CLK1); //  восттановленная частота с выхода1 
 #undef F_CPU
#define F_CPU 100000000 //новая тактовая частота, Герц
  enc_mode(0);// запустить режим соответсвующий переменной mode
} //end setup


void loop() {
// в режиме DDS sinus дополнительно измерять скв напряжение
   if (mode==4 && SHOWVRMS){
                Vcc=(double) Mn * ((uint32_t)(my_sq_adcread(9) *3300 )/4096); 
                mon_out(); 
        }

 // вольтметр и частотометр запускаются циклически, в отличии от других режимов
     if (mode==9) {mon_out(); freq_meter();  }//сначала вывести картинку, потом измерять
   if (mode==10) {volt_meter();}
 if (mon_flag) { mon_out();} //в остальных ситуациях при наличии флага вывода на дисплей 
}
  


///////////////////////////////////////////////////////////////////////////
/////////*********** ВЫВОД НА ДИСПЛЕЙ************//////////////////////////
///////////////////////////////////////////////////////////////////////////
void mon_out(){
char mybuf[15];
if (mon_flag&(1<<1)){ //если была смена режимов 
       tft.fillScreen(paper);   //чистить полностью экран только при смене режимов
//************** Вывод первой строчки*****************************
  tft.setCursor(0, 0); //  вперёд, вниз
   tft.setTextColor(ST7735_GREEN, paper);
    tft.setTextSize(2);
    switch(mode){ 
       case 0: tft.print("  Clock Gen  ");  break;       
        case 1: tft.print("  PWM Mode   "); break;
          case 2: tft.print("  Duty Mode  "); break;
           case 3: tft.print(" Impuls Mode "); break;
           case 4: tft.print("  Sinus DDS  "); break;
            case 5: tft.print(" Triangle DDS"); break;
           case 6: tft.print("  Pila1 DDS  "); break;
          case 7: tft.print("  Pila2 DDS  "); break;
         case 8: tft.print("  Noise DDS "); break;
       case 9: tft.print(" Freq. meter "); break;
      case 10: tft.print(" Volt. meter "); break;
       }
  }  //КОНЕЦ если была смена режимов  

 //*****************Вывод второй строчки*****************************
if (mon_flag&((1<<1)|(1<<2)) ){ //если была смена режимов или смена частоты 
tft.setTextColor(ST7735_WHITE, paper); 
tft.setCursor(0, 19); tft.setTextSize(3);
if (mode !=3) { // в одновибраторе не использовать стандартный вывод 
 if (freq>=1E8) {tft.print("         ");   tft.setTextSize(2);tft.setCursor(0, 21);}    
     if (freq<10) {sprintf(mybuf,"   0,%ld   ", freq );}                //9 -> 0,9
else if (freq<100){sprintf(mybuf,"   %ld,%ld   ", freq/10, freq%10 );}   //99 -> 9,9                
else if (freq<1E3){sprintf(mybuf,"   %ld,%ld  ", freq/10, freq%10 );}    //999 -> 99,9           
else if (freq<1E4){sprintf(mybuf,"  %ld,%ld  ", freq/10, freq%10 );}    //9999 -> 999,9             
else if (freq<1E5){sprintf(mybuf,"  %ld %03ld  ", freq/10000, (freq/10)%1000 );} //99999 -> 9.999               
else if (freq<1E6){sprintf(mybuf,"  %ld %03ld ", freq/10000, (freq/10)%1000 );}  //999999 -> 99.999                       
else if (freq<1E7){sprintf(mybuf," %ld %03ld ", freq/10000, (freq/10)%1000 );} //999999 -> 999.999                       
else if (freq<1E8){sprintf(mybuf,"%ld %03ld %03ld", freq/10000000, (freq%10000000)/10000, (freq%10000)/10  );} //9999999 -> 9.999.999                       
else              {sprintf(mybuf,"%3ld %03ld %03ld", freq/10000000, (freq%10000000)/10000, (freq%10000)/10  );} //99999999 -> 99.999.999                       
} //end if (mode !=3)
// вывод в режиме одновибратора
if (mode==3) { sprintf(mybuf,"   %3ld   ", freq/10 );  if (imp_mode_menu == 0) {tft.setTextColor(ST7735_BLACK,ST7735_WHITE);} }
tft.print(mybuf);    //вывод частоты

}// Конец если была смена режима или частоты для второй строки
  
  //********************Вывод третьей строчки*****************************
               tft.setTextColor(ST7735_RED,paper); //красный цет строки для всех вариантов              
              
              if (mode==10){ //если вольтметр
                tft.setTextSize(3); //крупно
               tft.setCursor(50, 43);
                tft.print(" mV"); }              

              else if (mon_flag&((1<<1)|(1<<10))  && mode==9 ) { //если частотометр
               tft.setTextSize(2);
                tft.setCursor(0, 43);
                tft.print(" Hertz ");
                tft.setTextSize(1);
                infreqpsc? tft.print("max 266MHz") : tft.print("max 33MHz ") ;
                 }

               else if (mode==3) { //если одновибратор
                if (imp_mode_menu == 1) {tft.setTextColor(ST7735_RED,ST7735_WHITE);}
               tft.setTextSize(2); 
                tft.setCursor(50, 43);
                   switch (imp_mode) { 
                   case 0: tft.print("  mS  "); break;
                   case 1: tft.print("  uS  "); break;
                   case 2: tft.print(" Takt "); break;
                }}             
               else if (mode<9 && mon_flag&(1<<1) ) { //если режим генераторов и  менялся режим, то выводить
                tft.setTextSize(3); 
                tft.setCursor(35, 43);//x,y
               tft.print("Hertz");  
                }

               
  //********************* "осциллограммы"******************************
if (mon_flag&((1<<1)|(1<<4)) ){ //если была смена режима или  дьюти
     if (mode!=10){ tft.fillRect(5,90, 100,38,paper); }// зачистка пяточка (вправо, вниз, ширина вправо, длина вниз)
     tft.drawRect(0,67, 160,61,ST7735_MAGENTA);//рамка: вправо, вниз, ширина вправо, длина вниз
      if (mode==1 ||mode==2 || mode==9){
        tft.drawFastVLine(5, 90, 30, ST7735_CYAN); // восход фронта статическая вер линия
         tft.drawFastHLine(5, 91, duty, ST7735_YELLOW);//длина единицы
          tft.drawFastHLine(5, 90, duty, ST7735_YELLOW);//паралельная линия для выделения
           tft.drawFastVLine(duty+5, 91, 30, ST7735_YELLOW);// спад
            tft.drawFastVLine(duty+4, 90, 30, ST7735_YELLOW);//паралельная линия для выделения
             tft.drawFastVLine(105, 90, 30, ST7735_YELLOW);//спад конец такта статическая вер. линия
              tft.drawFastVLine(104, 90, 30, ST7735_YELLOW);//паралельная линия для выделения
               tft.drawFastHLine(duty+5, 120, (100-duty), ST7735_YELLOW);//линия единицы 2-го такта
                tft.drawFastHLine(duty+5, 119, (100-duty), ST7735_YELLOW);//паралельная линия для выделения
                 }
                 }//Конец если была смена режима или  дьюти

                 if (mon_flag&(1<<1)){ //вывод псевдоосциллограмм в разных режимах толко при смене режима
                        if (mode==3){ //логотип одновибратора емли менялся режим
                         tft.drawFastHLine(5,123,28,ST7735_YELLOW);// смещ вправо, смещ вниз, длина вправо                           
                          tft.drawFastHLine(5,122,26,ST7735_YELLOW);// паралельная линия для выделения                                                   
                           tft.drawFastVLine(32,73,50,ST7735_YELLOW); // смещ вправо, смещ вниз, высота вниз                           
                            tft.drawFastVLine(31,73,50,ST7735_YELLOW);// паралельная линия для выделения                             
                             tft.drawFastHLine(31,73,30,ST7735_YELLOW);// смещ вправо, смещ вниз, длина вправо 
                             tft.drawFastHLine(31,74,30,ST7735_YELLOW);                             
                               tft.drawFastVLine(61,73,50,ST7735_YELLOW);
                               tft.drawFastVLine(60,73,50,ST7735_YELLOW);                               
                                 tft.drawFastHLine(61,123,32,ST7735_YELLOW);
                                tft.drawFastHLine(61,122,32,ST7735_YELLOW);
                                }

                                
                       if (mode==4){ // логотип синуса если менялся режим 5пкс вправо и 78пкс вниз
                    for(uint8_t n=0; n<100; n++){tft.drawPixel(5+n, 78+ sine_logo[n],ST7735_YELLOW);
                    } //END  for
                 } // END if (mode==4)
                       else if (mode==5){// логотип треугольника                         
                      tft.drawLine(5,98,30,73,ST7735_YELLOW);
                     tft.drawLine(30,73,80,123,ST7735_YELLOW);
                    tft.drawLine(80,123,105,98,ST7735_YELLOW); 
                  } //END  mode==5
                         else if (mode==6){ //логотип пилы1
                           tft.drawLine(5,123,105,73,ST7735_YELLOW);
                           tft.drawFastVLine(105, 73, 50, ST7735_YELLOW);//спад конец такта статическая вер. линия
                           } //END  if (mode==6)
                            else if (mode==7){//логотип пилы2
                             tft.drawFastVLine(5, 73, 50, ST7735_YELLOW); // восход фронта статическая вер линия 
                             tft.drawLine(5,73,105,123,ST7735_YELLOW);
                              }// END  if (mode==7)
                                else if (mode==0){ //логотип меандра
                                  tft.drawFastVLine(5,73,25,ST7735_YELLOW);
                                  tft.drawFastHLine(5,73,50,ST7735_YELLOW);
                                  tft.drawFastVLine(55,73,50,ST7735_YELLOW);
                                  tft.drawFastHLine(55,123,50,ST7735_YELLOW);
                                  tft.drawFastVLine(105,98,25,ST7735_YELLOW);
                                }

     else if (mode==8){// логотип шума если менялся 
                    for(uint8_t n=0; n<100; n++){ uint8_t y=random(0,44);
                      tft.drawFastVLine(5+n,123-y,y ,ST7735_YELLOW);
                    } //END  for
                 } // END if (mode==8)

                     
                                
                 }//КОНЕЦ вывод псевдоосциллограмм в разных режимах только при смене режима
                                
                   //*********************** характеристики сигнала****************************************
                  tft.setCursor(5, 70); //  вперёд, вниз
                 tft.setTextColor(ST7735_WHITE, paper);
                tft.setTextSize(1);
                 if (mode==1 ||mode==2 || mode==9){ 
               tft.print("+Width="); if (t_hi<1E3) {tft.print(t_hi); tft.print(" uS  ");} else {tft.print(t_hi/1000); tft.print(" mS  ");}  
              tft.setCursor(5, 80); //  вперёд, вниз
            tft.print("-Width="); if (t_low<1E3) {tft.print(t_low); tft.print(" uS  ");} else {tft.print(t_low/1000); tft.print(" mS  ");}  
           tft.setCursor(114, 70); tft.print("Duty=");
          tft.setCursor(114, 80); tft.print(duty);tft.print(" %   ");
          } //END if (mode < 2 || mode==9)
   if (mode==10) { tft.print("Vcc=");tft.print(Vcc); tft.print(" mV   ");   }
   if (mode==4&&SHOWVRMS) { tft.print("Vrms=");tft.print(Vcc); tft.print(" mV   "); }
//  if (mode==9){ return;} // в режиме  частотометра выводить на экран больше ничего не нужно.

  /////////// установка курсора и вывод шага в разных режимах ///////////////   
              
                if (mon_flag&((1<<1)|(1<<3))) {// выводить Step  если менялся режим  или шаг             
                if (mode==3) { // в режиме одновибратора    
                              if (imp_mode_menu==2) { tft.setTextColor(ST7735_BLACK,ST7735_WHITE);}                     
                              else { tft.setTextColor(ST7735_WHITE, paper);}  
                                  tft.setCursor(114, 70); tft.print("Step=");  
                                   tft.setCursor(114, 80);//курсор в поле  значения шага
                               }
                else if (mode<9) { tft.setCursor(114, 95); tft.print("Step="); tft.setCursor(114, 105);} 
                 else if (mode==10)  {tft.setCursor(100, 70); tft.print("Step=");} //только в вольтметре
               
                   switch (encstep) { 
                    case 0: tft.print(" 0,1"); break;
                    case 1: tft.print("   1"); break;
                    case 2: tft.print("  10"); break;
                    case 3: tft.print(" 100");break;
                    case 4: tft.print(" 1E3");break;
                    case 5:  tft.print(" 1E4");break;
                    case 6:  tft.print(" 1E5");break;
                    case 7:  tft.print(" 1E6");break;
                    case 8:  tft.print(" 1E7");break;
                   }// END switch case          
                  }// Конец выводить  Step  если менялся режим  или шаг   
                    
   // вывод прочей информации
                 if (mode==3) {// вывод меню запуска импульса
                              if (imp_mode_menu==3) { tft.setTextColor(ST7735_RED,ST7735_WHITE );  }                                                                                                 
                                else { tft.setTextColor(ST7735_RED, paper );        }
                              tft.setTextSize(3);
                              tft.setCursor(100, 95);
                              tft.print("Run");
                            }


/// вывод пределов для вольтметра
if (mode==10) {
 tft.setCursor(5, 80); //  вперёд, вниз
    tft.setTextSize(2); 
     tft.setTextColor(modevolt? ST7735_YELLOW : ST7735_WHITE , paper);//выбрать жёлтый цвет если активен
      sprintf(mybuf,"Low_mv=%5d", Vin_low);//выводить 5 символов
      tft.print(mybuf);    //вывод нижнего предела
      tft.setTextColor(modevolt? ST7735_WHITE : ST7735_YELLOW , paper);
    tft.setCursor(5, 100); //  вперёд, вниз
  sprintf(mybuf," Hi_mv=%5d", Vin_hi);
tft.print(mybuf); //вывод верхнего предела 
 }
mon_flag=0;
}//END mon_out




//обработчик прерываний энкодера
void enc_int(){   
static char EncPrev=0;      //предыдущее состояние энкодера
 static char EncPrevPrev=0;  //пред-предыдущее состояние энкодера
  char EncCur = 0;
   if(!(  GPIOB_BASE->IDR&64  )){EncCur  = 1;} //опрос фазы 1 энкодера
    if(!(  GPIOB_BASE->IDR&128 )){ EncCur |= 2;} //опрос фазы 2 энкодера
    if(EncCur != EncPrev)             //если состояние изменилось,
    {
    if(EncPrev == 3 &&        //если предыдущее состояние 3
       EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
    {
      if(EncCur == 2)          //если текущее состояние 2,
        enc_mode(-1);            //шаг вверх
      else                          //иначе
        enc_mode(1);            //шаг вниз
    }
    EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
    EncPrev = EncCur;               //сохранение предыдущего состояния
  }
 }// END VOID


// ФУНКЦИЯ конфигурации режимов 
void enc_mode(int8_t in){
  modebit= digitalRead(PB5); //состояние кнопки PB5. 0-нажата 
   if (!modebit) {// если сейчас идёт переключение режимов (кнопка нажата)
   mytone(880,30); //звук переключения режимов
     mode+=in; 
     if(mode>10){mode=10; modevolt=!modevolt; } //вместо переключения режима переключить текущую регулировку границ вольтметра
      if(mode<0){mode=0;}//ограничение смены режима
        if (mode==0){freq_si5351_restore();  clock_gen();} //если выбран si5351
        if (mode==1 || mode==2 ){freq_restore(); timer_set();}  // PWM&Duty      
        if (mode==3) { TIMER1_BASE->BDTR=0;  freq=100;}//настройки в при входе в режим одновибратора 
        if (mode >3 && mode <9) {freq_restore();  dds_set(); }  //dds
                                else {DMA1_BASE->CCR5&= ~DMA_CCR_EN;}  //DDS_dma_disable
        if (mode==9) {freq=0;}// сбросить в ноль freq в режиме частотометра
         comm(); mon_flag|=(1<<1); enc_step_control();
         mode_save();
         return; 
          } // END if !modebit
          
          //сюда попадает при изменении частоты (вращение энкодера без нажатия)
         mytone(4400,7); //звук изменения частоты
       switch(mode){ //если сейчас идёт изменение частоты
     case 0: freq_si5351_restore(); set_freq(in); clock_gen(); freq_si5351_save() ;  break;
     case 1:  freq_restore(); set_freq(in);  timer_set(); freq_save();  break;
     case 2:   duty+=in; timer_set();  break;  //в duty ничего не сохраняю.
     case 3:  if (imp_mode_menu==0){ set_freq(in); if (freq<10) freq=10; if (freq> 500000) {freq=500000;}   }  //переключение длительности импульса    
              else if (imp_mode_menu==1){ imp_mode++;  if (imp_mode >2){imp_mode=0;} }//переключение 0-мс, 1-мкс, 2 -такт           
              else if (imp_mode_menu==2){    encstep++; if (encstep>6) {encstep=0;}  enc_step_control();} //переключение шага
              else if (imp_mode_menu==3){ impuls(); } //генерация импульса
             break;
      case 4 ... 8: set_freq(in);  dds_set(); freq_save();  break;   //  DDS режимы
    case 9:   break; // в частотометре не реагировать на вращение энкодера 
   case 10:   modevolt?  Vin_low+=( pow(10,encstep)*in/10) : Vin_hi+=( pow(10,encstep)*in/10); //регулировка пределов вольтметра
   if (Vin_low<0||Vin_low>99999 ){Vin_low=0;} if (Vin_hi<0||Vin_hi >99999){Vin_hi=0;} break; //ограничения не менее ноля и не более 4х символов 
 } //end switch case
mon_flag|=(1<<2);//флаг смены частоты 
comm();
}//end enc_mode


void set_freq(int8_t in){
uint32_t freq_temp = freq+( pow(10,encstep)*in);
if (in==-1) { 
              if (!freq_temp) {if (encstep>1){encstep--; } mon_flag|=1<<3 ;} 
              else {freq= freq_temp;} //если не уменьшилось, то присвоить новое значение
              }
//при увеличении проблем быть не должно
else {freq= freq_temp;}
}




// обработчик кнопки энкодера:
void key_enc_int(){//сюда должно попадать только при отжимании кнопки (Rising Edge)
if(!modebit){ // если до этого менялся режим то выдержать паузу (низкий звук в спикер) и выйти
      mytone(30,150); //150ms примерно соответсвует времени отпускания кнопки после вращения
      while( (TIMER2_BASE->SR)==0);//подождать пока пропищит
      modebit=1; return; //и выйти
     }  
  
  //сменить режим и выйти если были в duty mode:
if (mode==2) {  mode=1; mon_flag|=(1<<1); enc_step_control() ; mode_save(); mytone(880,30); while( (TIMER2_BASE->SR)==0); return;} 
// иначе было переключение шага
mytone(160,100); //выдать звук переключения шага
 while( (TIMER2_BASE->SR)==0);//подождать пока пропищит
  if (mode==9) {infreqpsc=!infreqpsc; mon_flag|=(1<<10); return;} //включать/отключать делитель в режиме частотометра
  if (mode==3) {  imp_mode_menu++;  mon_flag|=(1<<2)|(1<<3); if(imp_mode_menu >3){imp_mode_menu=0 ;}   }                  
  else {   encstep++;  enc_step_control(); }
   mode_save(); 
}//end 

 /////////////ограничение шага в зависимости от режимов и частот/////////////////////////////////
void enc_step_control(){
// для CLOCK режима если  шаг более 1 МГц то шаг сбросить на 0,1 или 1 Герц (зацикливание переключений)
if (mode==0 &&  encstep >8) {encstep=1;} // Для CLOCK режима макс шаг 10МГц, минимальный 1 Гц
                            //если кнопка нажата(lOW)  значит сейчас переключался режим, и обнулять шаг не надо.   
if ( mode==1 && encstep >6) {modebit? encstep=0 :encstep=6 ;} //для PWM макс шаг 100 000 Гц, минимальный 0,1Гц
if ( mode==3 ) { if (encstep >4) {encstep=1;}}// для одновибратора макс 10000 единиц минимум 1
if (mode>3 && mode<9 && encstep >6) {modebit? encstep=0 :encstep=6 ;} //для DDS  макс шаг 100 000 Гц
if (encstep==0 && freq >=10000  ) encstep=1;// менять шаг 0,1 Гц -> 1Гц  на частотах выше 1кГц для всех режимов
if (mode==10 && (encstep >4 || encstep ==0)) {encstep=1;} //для вольтметра макс 1000 мв
mon_flag|=(1<<3); //флаг вывода на дисплей (обновить шаг) 
}



////////////////НАСТРОЙКА ТАЙМЕРА-ГЕНЕРАТОРА/////////////////////////////////////////////
void timer_set(){ //
if (freq > PWMFREQMAX) {freq=PWMFREQMAX; freq_save(); }
uint32_t divider=1;
uint64_t cpu_tic=F_CPU*10ULL /freq;
while ( (cpu_tic/divider) > 65536) {divider++;} 
uint32_t arr=cpu_tic/divider;
fcpu=(uint64_t)freq *arr * divider;   //fcpu - вычисленная необходимая тактовая частота МК (*10)
GPIOA_BASE->CRL=0xB4444444; //PA7 alt_output PA0-PA6 input
 if ( (GPIOA_BASE->CRH&0xf) != 0xB) {GPIOA_BASE->CRH&=~(0xf<<0);// clear_bits_PA8
GPIOA_BASE->CRH|=0xB; //PA8 Alternate function output Push-pull
 }
TIMER1_BASE->CR1|=(1<<7); // ARPE: ARR preload enable  
TIMER1_BASE->CCER=(1<<0)|(1<<2)|(pwm2_polar<<3);//cc1e/cc1ne enable 
TIMER1_BASE->BDTR=(1<<15);// Main output enable ,
TIMER1_BASE->CCMR1=(6<<4)|(1<<3)|(1<<2);//PWM mode 1, CCR1 preload enable, OC1FE fast enable
TIMER1_BASE->PSC=divider-1;
TIMER1_BASE->ARR=arr-1;
     // установка заданного DUTY
if(duty>99){duty=99;} if(duty<1){duty=1;} 
        TIMER1_BASE->CCR1= (float) (TIMER1_BASE->ARR+1)* duty/100.0 ;
  static int old_duty =duty; if (old_duty !=duty){ old_duty =duty; mon_flag|=(1<<4);}
       uint32_t  imp_long=(uint32_t) (arr*divider); //длина периода в тактах
     uint32_t  imp_hi=(uint32_t)  ((TIMER1_BASE->CCR1)*divider); // длина импульса в тактах
     t_low= (imp_long-imp_hi) /(fcpu/1E7) ; //время LOW /1E6 И /10 т.к. fcpu*10
   t_hi=  imp_hi /(fcpu/1E7); //время HI
 
if (TIMER1_BASE->CNT > arr-1) {TIMER1_BASE->CNT =0;}//на всякий случай 
TIMER1_BASE->CR1&=~((1<<1)|(1<<3));  //Update enable + clear impuls if activ
TIMER1_BASE->CR1|=(1<<0); // tim1 EN,  
TIMER1_BASE->EGR=1<<0;// Update  ARR, PSC, CCR
 // коррекция тактовой частоты для мк
 si5351.set_freq( (fcpu/4)*10ULL , SI5351_CLK0);
mon_flag|=(1<<2);
}//end timer_set
 

// КОНФИГУРАЦИЯ DDS РЕЖИМОВ
void dds_set(){
if (freq > DDSFREQMAX) {freq=DDSFREQMAX; freq_save();  }
TIMER1_BASE->CCER=0;//Отключить аппартаную ногу таймера
GPIOA_BASE->CRH&=~(0xf<<0);// отключить ногу PA8
GPIOA_BASE->CRL = 0x33333333;// pa0-pa7  выход
static uint16_t oldSM=0;//прошлый размер массива
static uint8_t oldMODE=255;// прошлый режим
uint16_t x;//временная переменная для расчётов таблицы

//подгонка размера массива под максимальный SampleRate
uint16_t SM = 512; while (((uint64_t)freq * SM) > (F_CPU*10LL /13) ) {SM--; }
uint16_t psc=1, arr; 
// расчёт делителя для таймера
while ( ((uint64_t)F_CPU*10ULL / psc / (freq*SM)) >65536  ){psc++;}
//расчёт регистра перезагрузки
arr= (F_CPU*10ULL/psc) / (freq*SM);
TIMER1_BASE->PSC=psc-1;    //коррекция тактирования при смене частоты.
TIMER1_BASE->ARR= arr-1; //коррекция тактирования при смене частоты.
TIMER1_BASE->DIER=(1<<8); //тактировать DMA при событии: Update timer
TIMER1_BASE->CNT=0;
TIMER1_BASE->CR1=1;

//если изменился размер массива или режим или если DMA выключен, то
if (oldSM != SM || oldMODE !=mode || !(DMA1_BASE->CCR5&1) ) {// не прерывать понапрасну DMA
    oldSM=SM; oldMODE=mode;
    if (mode==4) { for(uint16_t n=0; n<SM; n++){wave[n]=255*(sin(TWO_PI*float(n)/SM)+1)/2 ;} }
    else if (mode==5)  {  for( uint16_t n=0;  n<SM; n++){if (n<(SM/2)){ x=  (n*255)/(SM/2) ;} else {x= ((SM-n)* 255)/(SM/2);}
    (x>255)?  (wave[n]=255) : wave[n]=x ;
    } }//треугольник  
    else if (mode==6) { for(uint16_t n=0; n<SM; n++){  wave[n]=n * 256/SM ; 
      } }//пила1
    else if (mode==7){  for(uint16_t n=0; n<SM; n++){  wave[n]=  ~(n* 256/SM) ; 
     } }//пила2
    else if (mode==8){ for(uint16_t n=0; n<SM; n++){ wave[n]=random(0, 255); }}//шум 
DMA1_BASE->CCR5&= ~DMA_CCR_EN; //dma_disable
DMA1_BASE->CCR5= DMA_CCR_PL_HIGH | DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_DIR_FROM_MEM;
DMA1_BASE->CPAR5= (uint32_t)&(GPIOA->regs->ODR);
DMA1_BASE->CMAR5=(uint32_t)wave;
DMA1_BASE->CNDTR5=SM;
DMA1_BASE->CCR5|= DMA_CCR_EN;// DMA start
}//конец  if (oldSM != SM ||
fcpu=freq*SM*psc*arr;  // новая тактовая частота рассчитана
 si5351.set_freq( (fcpu/4)*10ULL , SI5351_CLK0);
mon_flag|=(1<<2);
}//END DDS set()


  void mytone(int frq, int ms ){
 if (mode==9){return;} //таймер в режиме частотометра занят
 uint16_t psc=1; uint32_t tim_arr;
 // настройка генератора звука на таймере3
  tim_arr = (fcpu/20)/frq;// fcpu/10/2
  while ( (tim_arr/psc) > 65535) {psc++;} 
  __asm volatile( "cpsid i" ); 
   TIMER2_BASE->SMCR=0;
    TIMER3_BASE->CCR3=0; //обнулить регистр соответсвующий используемому выходу
     TIMER3_BASE->PSC=psc-1;
      TIMER3_BASE->ARR=(tim_arr/psc)-1;
       TIMER3_BASE->CCMR2=(1<<5)|(1<<4);// OC3M:011 Toggle
        TIMER3_BASE->CCER=3<<8;//cc3e  подключить аппаратную ногу
         TIMER3_BASE->SMCR=(1<<2)|(1<<0)|(1<<4);//SMS:101 && TS:001  строб от 2-го таймера  
          TIMER3_BASE->EGR=1; //перечитать регистры.
           TIMER3_BASE->CR1=1;
           /// настройка выдержки времени на таймере2
          psc=1;
        tim_arr = (fcpu/10000) * ms;// fcpu /1000 /10
       while ( (tim_arr/psc) > 65536) {psc++;} 
      TIMER2_BASE->CCMR2=0;
     TIMER2_BASE->CR2=0;
    TIMER2_BASE->CR1=(1<<3)|(1<<2);//один импульс, без прерываний
   TIMER2_BASE->CNT=0;
  TIMER2_BASE->CR2=(1<<4);  //MMS:001 сигнал разрешения работы другим таймерам
 TIMER2_BASE->PSC=psc-1;
TIMER2_BASE->ARR=(tim_arr/psc)-1;
TIMER2_BASE->EGR=1; //перечитать регистры.
TIMER2_BASE->SR=0;//отчистить флаги
TIMER2_BASE->CR1|=(1<<0);
  __asm volatile( "cpsie i" );
}

void clock_gen(){ //функция работа с синтезатором si5351
GPIOA_BASE->CRH&=~(0xf<<0);// отключить PA8
GPIOA_BASE->CRL=0x44444444; //отключить PA0-PA7 (input)
fcpu=1000000000;  // на всякий случай сделать тактовую стандартной
si5351.set_freq( (fcpu/4)*10ULL , SI5351_CLK0);
if (freq <40000){freq=40000;} if (freq>225E7){ freq=225E7;} //допустимые рамки частот 4кГц - 225МГц
si5351.set_freq(freq * 10ULL, SI5351_CLK1); //домножить на 10, т.к. нужна частота в сотых герца, а freq в десятых долях.
mon_flag|=(1<<2);//и флажок на отображение частоты.
}

void comm(){ //коммутация выходов через мультиплексор
if (mode>0 && mode<4 ) {digitalWrite(PB3,LOW); digitalWrite(PB4,LOW);} //выход таймера
  else  if (mode>3 && mode<9 ) {digitalWrite(PB3,HIGH); digitalWrite(PB4,LOW);}//выход DDS
  else if (mode==0 ) {digitalWrite(PB3,LOW); digitalWrite(PB4,HIGH);} //выход_1 Si5351  
 else if (mode==9) {digitalWrite(PB3,HIGH); digitalWrite(PB4,HIGH);} //вход А15 
}

void volt_meter() {
static boolean alarm=0;
 //измерение напряжения питания МК
 Vcc = (VrefINT <<12) / my_sq_adcread(17);
//измерение напряжения на входе ADC9(PB1)
   for (int n=0; n<=65535; n++ ) {asm volatile("nop"); } //Типа delay
  freq = (double) Mn * ((uint32_t)(my_sq_adcread(9) * Vcc *10)/4096);
   // если напряжение не удовлетворяет условиям, и буззер не работает -то включить
 if      (freq < ((uint32_t)Vin_low*10)) { alarm =1;  if (TIMER2_BASE->SR!=0) {mytone (200, 10000);} }
  else if (freq >  ((uint32_t)Vin_hi*10)) { alarm =1;  if  (TIMER2_BASE->SR!=0) {mytone (1000, 10000);} }
   else alarm=0;
    //если всё ок, а буззер работает, то выключить.
     if (!alarm && (!TIMER2_BASE->SR) ) {mytone (0, 0);}
  mon_flag|=(1<<2);
  }

uint32_t my_sq_adcread(byte adc_in) {
 uint64_t akkum=0;

  for (int n=0; n<=32767; n++ ) {//собирать 16384 выборок 
    akkum += sq(adc_read(ADC1,adc_in)); //суммировать квадраты
    if( mon_flag) return 0;
    } //END собирать 16384 выборок 
     return (sqrt(akkum>>15));

}


///////////////////// ФУНКЦИЯ ОДНОВИБРАТОРА///////////////////////
void impuls(){ 
if (fcpu != 1000000000){fcpu = 1000000000; si5351.set_freq( (fcpu/4)*10ULL , SI5351_CLK0); }
uint32_t tim_arr=0, div_imp_mode=0; 
GPIOA_BASE->CRL=0xB4444444; //PA7 alt_output PA0-PA6 input
 if ( (GPIOA_BASE->CRH&0xf) != 0xB) {GPIOA_BASE->CRH&=~(0xf<<0);// clear_bits_PA8
GPIOA_BASE->CRH|=0xB; //PA8 Alternate function output Push-pull
 }
__asm volatile( "cpsid i" );
  TIMER1_BASE->BDTR= 1<<14; //Automatic output enable
    TIMER1_BASE->CCMR1=(7<<4);//PWM2 Mode
     TIMER1_BASE->CCER=(1<<0)|(1<<2)|(pwm2_polar<<3);//cc1e/cc1ne enable 
      TIMER1_BASE->CCR1=1; // поднять ногу на этом такте
      TIMER1_BASE->CR1=(1<<3);//режим "один импульс"     
   if (imp_mode<2){ // кроме такта
  switch(imp_mode){// 0-мс, 1-мкс, 2 -такт
 case 0:  div_imp_mode=1000;  break; // делитель для миллисекунд
case 1:  div_imp_mode=1000000;  break;// делитель для микросекунд
 }
 tim_arr =  (freq/10) * (uint32_t)(F_CPU/div_imp_mode) ; 
  uint32_t divider=1; 
   while ( (tim_arr/divider) > 65535) {divider++;} 
    TIMER1_BASE->PSC=divider-1; // Прескалер
     TIMER1_BASE->ARR=(tim_arr/divider)-1; //длина импульса
      TIMER1_BASE->CCR4= TIMER1_BASE->ARR;//повесить флаг по окончании импульса
      }
      else {  TIMER1_BASE->ARR = (freq/10);} //если imp_mode == такт,
      TIMER1_BASE->EGR=1; 
      mytone(2200,100);
     TIMER1_BASE->CR1|=(1<<0);
  while( (TIMER1_BASE->SR&(1<<4))==0 )   ;//ждать подождать пока закончится импульс
  __asm volatile( "cpsie i" );
}

  void freq_meter(){
/////////////////////счётчик импульсов
si5351.set_freq(2500000000, SI5351_CLK0);//  тактовая частота по умолчанию с выхода 1
pinMode(PA15,INPUT_PULLDOWN); // вход частотометра
 uint32_t imp_long,imp_hi;//переменные измерения длины такта
   __asm volatile( "cpsid i" );
   /// Timer2 счёт младших 16 бит
RCC_BASE->APB2RSTR |= 1<<11; //reset timer 1
  RCC_BASE->APB2RSTR&= ~(1<<11); 
RCC_BASE->APB1RSTR |=  (1<<0) |(1<<1) ; //сброс таймера2,3
 RCC_BASE->APB1RSTR &= ~((1<<0)|(1<<1)); // сброс таймера2,3
  TIMER2_BASE->CR2=1<<5; //MMS:010 управление подчинённым в режиме "Update" 
    TIMER2_BASE->SMCR= (1<<14)|(5<<0)|(infreqpsc<<13)|(infreqpsc<<12);// режим 2 внешнего тактирования + делитель/8 + разрешение работы от таймера1 
     TIMER2_BASE->ARR=65535; //считать до максимума
       TIMER2_BASE->EGR=1; //перечитать регистры.
       TIMER2_BASE->CR1|=(1<<0);//start timer2
      /// Timer3 счёт старших 16 бит
 TIMER3_BASE->SMCR=(1<<2)|(1<<1)|(1<<0)|(1<<4);//SMS:111 && TS:001  такт брать от 2-го таймера  
  TIMER3_BASE->ARR=65535; //считать до 
   TIMER3_BASE->EGR=1; //перечитать регистры.
    TIMER3_BASE->CR1|=(1<<0);//start timer3
    /// настройка времени разрешения на таймере1 для таймера2
        TIMER1_BASE->CR1=0;  TIMER1_BASE->CNT=0;
        TIMER1_BASE->CCER=0;// отключить выходы таймера на физ ноги
        uint16_t      psc=1;
         uint32_t    tim_arr = F_CPU;// чтобы измерять менее 1 секунды добавить делитель
          while ( (tim_arr/psc) > 65536) {psc++;} 
          TIMER1_BASE->PSC=psc-1;//
           TIMER1_BASE->ARR=(tim_arr/psc)-1;
           TIMER1_BASE->EGR=1; //перечитать регистры.
           TIMER1_BASE->CR1=(1<<3)|(1<<2);//один импульс, без прерываний
           TIMER1_BASE->CR2=(1<<4);  //MMS:001 сигнал разрешения работы другим таймерам
         TIMER1_BASE->CR1|=(1<<0);
       __asm volatile( "cpsie i" );
      while (TIMER1_BASE->CR1&1) {asm volatile("nop"); if(mon_flag) {return;}  }
     freq=  TIMER3_BASE->CNT<<16  | TIMER2_BASE->CNT; //частота (не удесятерённая)
    if (infreqpsc) {freq*=8;}// если включен делитель на 8 то результат умножить на 8
    if (freq>1E5){freq*=10; t_low=0;t_hi=0; duty=0; mon_flag|=(1<<2)|(1<<4); return;} //выйти если freq больше 100кГц
    
    // Перенастройка таймера 2 в режии измерения длительности импульса и скважности для частот менее 100 кГц
 uint32_t divider=1;                                  
while ((F_CPU/divider/((freq>0)? freq : 1 )) > 65000) {divider++;}
 __asm volatile( "cpsid i" );
RCC_BASE->APB1RSTR |=  1<<0; //сброс таймера2
 RCC_BASE->APB1RSTR &= ~(1<<0); // запуск таймера 2
  TIMER2_BASE->CR1=0;//стоп таймер
    TIMER2_BASE->PSC= divider-1;
      TIMER2_BASE->SMCR=(1<<4)|(1<<6)|(1<<2);// TS:101 SMS:100  вход TI1FP1  , Режим сброса
        TIMER2_BASE->CCMR1=(1<<0)|(1<<9);//CC1 input,mapped on TI1, CC2 input,mapped on TI1
         TIMER2_BASE->CCER=(1<<5)|(1<<0)|(1<<4);//cc1-Hi,cc2-lo 
        TIMER2_BASE->EGR=1; //перечитать регистры.
   /// настройка таймера1 для счёта  тайм-аута при измерения PWM 
     TIMER1_BASE->CR1=(1<<3);//один импульс, без прерываний
      TIMER1_BASE->CNT=0; TIMER1_BASE->CR2=0;  TIMER1_BASE->CCER=0;
         TIMER1_BASE->PSC=F_CPU/15625 -1; // тактовая таймера 15625 Герц 
          TIMER1_BASE->ARR=31250;//считать до 31250 (2 секунды) 
          TIMER1_BASE->EGR=1; //перечитать регистры.
          timer_attach_interrupt(TIMER1, TIMER_UPDATE_INTERRUPT, myint);
         TIMER1_BASE->CR1|=(1<<0);// старт счёта 2х секунд      
      __asm volatile( "cpsie i" );
       TIMER2_BASE->CR1=(1<<0);// старт захвата PWM
     while( (TIMER2_BASE->SR&0x65F)!=0x65F) {// 
      asm volatile("nop"); if(mon_flag) {timer_detach_interrupt(TIMER1, TIMER_UPDATE_INTERRUPT); return;} }
    TIMER2_BASE->CR1=0;// стоп таймер
   timer_detach_interrupt(TIMER1, TIMER_UPDATE_INTERRUPT);
   imp_long=(uint32_t) ((TIMER2_BASE->CCR1)*divider);
  imp_hi=(uint32_t)  ((TIMER2_BASE->CCR2)*divider);
 if (freq <1000){ freq= F_CPU*10 /imp_long ;
} //если freq Менее 1кГц то использовать данные второго НЧ-измерения частоты (*10)

 else {freq*=10; } //иначе просто удесятерить результат для корректного вывода информации. 
duty=  (float) imp_hi / (imp_long / 100.0) ;
if (duty > 100 || duty < 0) {duty=0;} // на всякий случай ограничение
 t_low= (double)(imp_long-imp_hi) / (F_CPU/1E6) ;
  t_hi=  (double) imp_hi /(F_CPU/1E6);
   mon_flag|=(1<<2)|(1<<4);
   } //END freq meter


  // прерывание тайм-аута при отсутствиии сигнала на входе при измерении PWM 
void myint(){ 
    mon_flag|=((1<<2)|(1<<4));  t_low=0; t_hi=0; duty=0;  freq=0; 
timer_detach_interrupt(TIMER1, TIMER_UPDATE_INTERRUPT);
} 
 

Убедительная просьба не использовать кнопку "Цитировать" под этим постом, т.к. у меня пропадёт возможность редактировать ошибки, да и просто засирать тему повторной информацией не стоит.

 
 
venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

снял старую плату, без варварства не обошлось, хотя с виду осталась живой. поставил 128Kb, все прошилось и запустилось. осцилом только завтра потыкаю, посмотреть, насколько все у меня плохо. :) потому как все не по феншую - питание от импульсника, выход через коммутатор, после цапа регулятор на ad8052.

пока есть ссылки, где какие платы покупал - здесь 128kb, здесь 64kb. ссылки не реферальные, может кому пригодится.

240265
240265 аватар
Offline
Зарегистрирован: 12.08.2015

Dimax , на входе частотомера можно избавиться от одного резистора. Нужно включить внутреннюю подтяжку, а снаружи оставить только противоположный резистор 39К. Я на Ф303 так сделал.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

dimax пишет:

нужен полноценный усилитель-формирователь с встроенным делителем частоты. А они трудоёмкие и капризные. Поэтому я и забил на это дело :)

Формирователь - да, от 0 до мегагерц 80-100 не сразу, но работает, а делителей полно, хоть на 2 хоть на 256, частота от 1 ГГц и выше, у них еще и "чуйство" загрублять приходится, чтобы на пролетающую мимо муху не реагировали :-) Только после делителя надо и частотомер соответствующим образом подстроить.

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

Рабочаяя схема

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

man_200 пишет:

Спасибо. Учту пожелания. Завалялась парочка делителей на SAB и понравилось исполнение частотомера. Не мог бы скинуть полную его схему и пошивку или ссылку на проект, чтобы тему не засорять?

Cхема и прошивка http://wdfiles.ru/noRT

Сделано "по мотивам" FCL-метра, только выбросил все лишнее (Микеланжело, мля :-) )

http://www.cqham.ru/forum/showthread.php?11744-FCL-meter-FAQ-%C2%EE%EF%F0%EE%F1%FB-%E8-%EE%F2%E2%E5%F2%FB-2

Silver_D
Offline
Зарегистрирован: 21.04.2020

Всем привет. Вот наконец пришли платки с Китая и собрал приборчик. Спасибо dimax за отличный проект.

       

Silver_D
Offline
Зарегистрирован: 21.04.2020

Двополярки ОС любят, тем более что копеешная микруха много места не занимает.

https://drive.google.com/file/d/1tszNU8_aaFPRSW5sGpb5sQTYfDZTMXqD/view?u...

man_200
Offline
Зарегистрирован: 29.04.2016

А что, просто, со вкусом и из доступных деталей, а главное рассыпью. Только СИшки не вижу. Видимо первый вариант генератора.

В качестве вишенки на этом торте не хватает печатки в LAY, для полноты проекта.

Два диода не будут защищать 34063 и 7806 в случае встречного большого напряжения по цепи 12-и вольтовой нагрузки.

 Достаточно поставить один диод только на этот провод, рядом с L3, мощный Шотки.

Кстати, 7805 вместо 34063 не проще было поставить? Он мощнее и точно батарею зарядит.

И последнее, с 34063, поставив еще один диод, можно получить и отрицательное напряжение -5В, что позволит исключить 7660, а усилитель питать +/- 5В

Главное что аппарат работает, применю твой усилитель и спасибо за проект!

Silver_D
Offline
Зарегистрирован: 21.04.2020

Вариант то первый, только программа и распиновка версии 3,5

А мощности там и не нужно, 250 - 350мА достаточно, да и не греется.

Отрицательное напряжение с 34063 как то не хочется брать, он помехи большие делает, да и развязка питания аналога от цифры лучше.

Добавлю архив в диск, лай и герберы, может кто захочет заказать.

https://drive.google.com/drive/folders/1CCySKNDxiA8S2Vq3ZmepnDKEk5bZh2Qw...

User MTU
Offline
Зарегистрирован: 24.03.2012

Спасибо за схемы и печатку!

Тем не менее вопрос по энкодеру - а критично количество импульсов на оборот ручки и фазировка каналов? В исходнике генератора на STM версии 3.6 вроде не обнаружилось ничего на эту тему...

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

User MTU пишет:

Тем не менее вопрос по энкодеру - а критично количество импульсов на оборот ручки и фазировка каналов? В исходнике генератора на STM версии 3.6 вроде не обнаружилось ничего на эту тему...

Крайне желательно, что б один щелчок энкодера формировал один полный импульс, подробности были в описании версии 3.0  .

venus пишет:
 
режим impulse у меня работает странно. при переходе в него из duty изначальное состояние то нулевое, то единичное. если в нем сделать run, то при переходе назад в duty/pwm, генерация там отсутствует полностью. для запуска достаточно сходить в любой режим dds. я в принципе импульсом не пользуюсь, но проверял и не понял, что с ним.
 
 
Исправил, скетч обновил.
 
venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

dimax пишет:
Исправил, скетч обновил.

да, теперь вроде все логично. спасибо.

User MTU
Offline
Зарегистрирован: 24.03.2012

С энкодером понятно, спасибо.

Еще вопрос - фильтр-усилитель имеет смысл прикручивать только на выход DDS, а на PWM не надо, а то получится вселенское зло. Тем более что микросхема усилителя тянет 3 МГц всего (такое в коробочке лежит в столе).

 

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

достаточно на dds, pwm сигнал там все равно присутствует в инвертированном виде. а быстрые операционники (>100MHz) стоят рублей по десять.

man_200
Offline
Зарегистрирован: 29.04.2016

3.5 работает и нет желания его раскидывать

Начал собирать 3.6, благо почти все железо есть, но мелькнула шальная мысль - видимо скоро будет версия 3.7 с добавкой ADF4350 (4351) на борт и полосой частот от 0.1Гц до 4400МГц

Подобную сборку (SI4351 + ADF4350) применили в антенном анализаторе VNA, а вот генератора с такой полосой не встречал.

Хотелось бы надеяться

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

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

Black2008
Offline
Зарегистрирован: 09.12.2016

Спасибо. Только мусор на экране присутствует. Можно как то пофиксить? https://yadi.sk/i/P6Y0KOuKPcm8nw

man_200
Offline
Зарегистрирован: 29.04.2016

Заливал файлы в bin, не хочет запускаться с СИ. Хотел прошить через IDE, плату устанавливал STM32F103C6/fake STM32F103C8. Частоту выставил 72МГц. IDE ругается на плату

Сбрось пож. скрин своих установок

Изменил плату на STM32F103C_HSI series Загрузка прошла, но бестолку

Чешу репу

MAG-N
MAG-N аватар
Offline
Зарегистрирован: 05.06.2017

В посте #130 русским по белому написано:

Может у Вас плата с 64К памяти?

man_200
Offline
Зарегистрирован: 29.04.2016

Сейчас именно такие установки

Плату перед монтажом проверял - 128к, светодиоды моргали значит был рабочий порт кварца. Питание 5.01В, вся периферия подключена, буду пробовать менять СИшку, благо две заказывал.