iiv 29 20 августа Опубликовано 20 августа · Жалоба Может чтобы обойти проблему со считыванием из флеша длинного кода попробовать по-другому: взять два цикла с одним и с двумя НОПами, и в зависимости от величины задержки крутить оба цикла с разной длиной параметров. Я попробовал это на другой архитектуре (esp32), не могу сказать, что стоит как вкопанное, так как много другого дергается попутно, но у Вас может и будет с точностью до такта получаться. Сам код: #pragma GCC push_options #pragma GCC optimize ("Ofast") #include <stdio.h> #include <math.h> #include <Arduino.h> static int NOP_Param_1=6; static int NOP_Param_2=6; void nop_delay1(unsigned int t1, unsigned int t2) { unsigned int i; i=t1; while(i>0) { asm("nop"); i--; } i=t2; while(i>0) { asm("nop"); asm("nop"); i--; } return; } // total time is: t1*C1 + t2*(C1+1) + C2, where NOP_Param_1 = C1, NOP_Param_2 = C2. // (t1+t2)*C1 + t2 = time - C2; void nop_delay(unsigned int time) { unsigned int q = time - NOP_Param_2; unsigned int q2 = q/NOP_Param_1; unsigned int q1 = q - q2*NOP_Param_1; nop_delay1(q1, q2-q1); } unsigned int nop_delay_ini1(unsigned int time) { unsigned int begin, end; RSR(CCOUNT, begin); nop_delay(time); RSR(CCOUNT, end); return end-begin-1; } void test() { unsigned int TestVal[]={1000, 10000, 20000, 1999, 8999, 12345}; for(int j=0; j<3; j++) for(int i=0; i<sizeof(TestVal)/sizeof(TestVal[0]); i++) Serial.printf("%d %d\n", TestVal[i], nop_delay_ini1(TestVal[i])); } void setup() { Serial.begin(115200); Serial.printf("Starting ini\n"); } int count=0; void loop() { test(); Serial.printf("count=%d\n", count++); delay(2000); } #pragma GCC pop_options В коде два важных параметра (NOP_Param_1, NOP_Param_2) которые надо подобрать под ваш контроллер - первый - длительность в тактах цикла с одним НОПом, второй - общая задержка. Также замечу, что код не сможет работать если надо отмерить только несколько тактов и примерно работает от 30-40 тактов задержек (если NOP_Param_1/2 как у меня). 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 20 августа Опубликовано 20 августа · Жалоба 46 minutes ago, iiv said: Я попробовал это на другой архитектуре Любое while моментально увеличивает шаг до 30кгц, это описано в самом первом моем посте, тут счет идет на единичные такты, для более низкой частоты while может и пройдет но на 500кгц нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 20 августа Опубликовано 20 августа · Жалоба 3 minutes ago, whale said: Любое while моментально увеличивает шаг до 30кгц, это описано в самом первом моем посте, тут счет идет на единичные такты, вы все-таки хотя бы немного задумайтесь что именно я вам советую. Я же не зря специально для вашего случая пару часов кодил и тестировался. У меня точность в один такт разрешение моего таймера получается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 20 августа Опубликовано 20 августа · Жалоба Just now, iiv said: в один такт разрешение моего таймера получается. где тут один такт ? while(i>0) { asm("nop"); i--; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 20 августа Опубликовано 20 августа · Жалоба 1 hour ago, whale said: где тут один такт ? Прочитайте внимательно что я вам посоветовал не выдирая из всего кода кусочки, и вам обязательно откроется тайна одного такта 🙂 Для тех, кто совсем в танке, повторяю: два цикла с длительностью (С) первого на один такт меньше, чем второй (С+1). Для любой величины задержки T>C^2 всегда можно выбрать такие два числа t1, t2, так, что C*t1 + (C+1)*t2 = T. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 20 августа Опубликовано 20 августа · Жалоба Неполное. Впрочем, перевести 39 страниц - дня на 2 работы... Можно я гугл-транслэйтом? Мандаринский учить пока не стану (((-8Ж Разве она чем-то отличается от SI5351 ? https://eax.me/stm32-si5351/ Ну как-бы похожа, но что там "чайные" добавили-выкинули сходу не скажу. SiLabs доку не отдаёт, пришлось брать на стороне. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 85 21 августа Опубликовано 21 августа · Жалоба А то, что микроконтроллер помимо генерации импульсов, должен еще чето делать, про это как бы вроде бы и забывают, да? Вообще, чето это попытка натянуть сову на глобус. Можно же взять другой МК, с более высокой тактовой частотой. У новых МК есть HRTIM, например. Или вообще даже попробовать микросхему-синтезатор сетки частот. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 21 августа Опубликовано 21 августа · Жалоба 2 часа назад, EdgeAligned сказал: А то, что микроконтроллер помимо генерации импульсов, должен еще чето делать, про это как бы вроде бы и забывают, да? Автор сам с этим не определился еще: В 19.08.2024 в 15:33, whale сказал: Вы думаете процессор все это время отдыхает ? Вы заблуждаетесь. В 19.08.2024 в 15:58, whale сказал: На период вывода все запрещено. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 21 августа Опубликовано 21 августа (изменено) · Жалоба 8 hours ago, iiv said: t1, t2, так, что C*t1 + (C+1)*t2 = T. Видно не понимаем друг друга, мне нужно генерировать меандр с временем между изменениями порта = одному такту, двум тактам, трем тактам итд а не с точностью один такт + 100500 тактов Кто нить может объяснить как загнать функция в ram в iar а потом ее исполнить в коде, хочу попробовать. Просто __ramfunc void (int){nop;nop; .....} а потом вызывам delay(1); или еще что то нужно указать линкеру ? Изменено 21 августа пользователем whale Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 85 21 августа Опубликовано 21 августа · Жалоба Технически это возможно, если написать РАЗНЫЕ функции генерации, и желательно без циклов. То есть, где нужно быстро дергать ногой, там напрямую импульсы без циклов и условий. А там, где процессорного времени будет достаточно, там можно и циклы, и условия перехода. Только все это нужно проверять и подгонять. Вообще, следует выбрать другой вариант решения, а не натягивать совв на глобус. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 21 августа Опубликовано 21 августа · Жалоба 16 minutes ago, whale said: Видно не понимаем друг друга, мне нужно генерировать меандр с временем между изменениями порта = одному такту, двум тактам, трем тактам итд а не с точностью один такт + 100500 тактов сделаю еще одну попытку прояснить вам мою идею. У вас stm32g070, у которого такт - 64МГц и вам нужен ногодрыг на 500кГц, то есть между переключениями у вас есть как минимум 64 такта. То, что я предлагаю, позволяет дозировать задержку с точностью до одного такта в диапазоне от 36 тактов до бесконечности. То есть вы с легкостью получите 500кГц, выставив 64 такта задержку, и 64/65/2*1000=492.3кГц, а если согласитесь на слегка не 50% форму сигнала, то и 64/129*1000=496.12кГц. Больше с этого дохлого контроллера взять не получится. ЗЫ: хоть и мое решение занимает меньше страницы уже отлаженного кода, считаю, что ТС надо при таких хотелках задуматься о более жирном процессоре, а лучше плиске. Не рекламы ради, очень советую взять мелкий GoWin - на нем с легкостью можно сделать шаг в районе 500кГц вплоть до единиц Герцев, если конечно еще подавать слегка не равномерные длины окон тактовой. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 21 августа Опубликовано 21 августа (изменено) · Жалоба Just now, iiv said: 500кГц 500 +-150 те 650 кгц минимум а лучше полосу 300-700 кгц. Могу для эксперимента запрогать ваш вариант и он все покажет. Ого а __ramfunc то работает без всяких бубнов, пропала неравномерность, можно считать задача решена. Изменено 21 августа пользователем whale Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
whale 6 21 августа Опубликовано 21 августа (изменено) · Жалоба Just now, iiv said: сделаю еще одну попытку Даже если ваш код заработает все равно он значительно больше чем текущий, и не факт что хватит до 650кгц так что до следующего раза, может кому нить еще пригодиться ) Изменено 21 августа пользователем whale Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 21 августа Опубликовано 21 августа · Жалоба 27 minutes ago, whale said: 300-700 кгц. 700кГц по идее должно потянуть, вернее если на вашем процессоре первый цикл тоже как у меня 6 тактов, то 888кГц и ниже все должно охватить. 2 minutes ago, whale said: Даже если ваш код заработает все равно он значительно больше чем текущий а чем он больше-то? У меня в страницу поместилось все со всеми тестами. Если говорить о том, что вам конкретно надо, так это только nop_delay1 и nop_delay2, которые займут примерно 50 байт в бинарнике. Я сомневаюсь, что простыня нопов и скачки по ним будут лучше, а то, что ваш метод дает вольность контроллеру не закачивать часть нопов из флеша, даст вам сказочные неприятности, у вас то будет работать, то не будет работать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
firstvald 24 21 августа Опубликовано 21 августа · Жалоба 5 hours ago, EdgeAligned said: А то, что микроконтроллер помимо генерации импульсов, должен еще чето делать, про это как бы вроде бы и забывают, да? Вообще, чето это попытка натянуть сову на глобус. Можно же взять другой МК, с более высокой тактовой частотой. У новых МК есть HRTIM, например. Или вообще даже попробовать микросхему-синтезатор сетки частот. можно перемычками снаружи Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться