Перейти к содержанию
    

=GM=

Свой
  • Постов

    1 590
  • Зарегистрирован

  • Посещение

Весь контент =GM=


  1. У вас много ошибок и неточностей в коде. Основные: 1) Мастер после подачи старт-условия должен дождаться появления флага SB, вдруг шина занята... 2) Мастер после передачи адреса слейва+0, должен дождаться появления флага ADDR=1. 3) Чтобы передать байт от мастера к слейву, надо дождаться флага TxE=1, и только потом передавать байт. 4) Чтобы принять байт от слейва, надо дождаться флага RxNE=1, и только после этого принять байт. 5) После каждого ивента надо чистить флаги. Учтите слейв передаёт столько байт, сколько требует мастер, не больше, не меньше.
  2. Попробуйте сделать так. 1) Программируете один таймер1 на несимметричный шим с fШИМ=33 кГц с заполнением 50%. Для примера, если системная частота 56 МГц, то таймер должен считать до 56000/33=1697. Соответственно, регистр сравнения равен 848. Пока запускать в работу не надо. Примерный код настройки таймера1 ниже. Не забываем его включить и ноги настроить. TIM1->CCMR2=0x0068; //OC3S output TIM1->CCER=0x0400; //CC3N enable on PB1 TIM1->CNT=0x0000; //to be on the safe side TIM1->PSC=0; //48000/1=48MHz TIM1->ARR=1919; //48000/1920=25kHz TIM1->EGR=0x0001; //UG=1 TIM1->BDTR=0xD800; //moe=aoe=1 TIM1->CCR3=768; //value to compare-duty TIM1->CR1=0x0081; //APRE=1,CEN=1 2) Программируете таймер2 на 5 мс (200 Гц). Запускаете таймер2 по прерыванию. В первом прерывании запускаете таймер1 (после запуска таймер1 начнет генерить частоту 33 кГц) и начинаете подсчитывать прерывания. 3) При каждом следующем прерывании добавляете к таймеру1 половину периода таймера1 (естественно, по модулю 1697), если нужна инверсия частоты, и ничего не добавляете (для симметрии можно добавлять 0), если не нужна инверсия. 4) На последнем прерывании останавливаете таймер1, ну и таймер2.
  3. На входе детектора кажется R4 стоит, а не R1? Уравнять токи смещения через R4 и R3 не пробовали? Поставьте, скажем R4=10кОм. Ещё можно поиграться напряжением смещения через R4, оно должно быть такое же, как и через R3.
  4. 1) AT25DF081A, 1 Mбайт, 5 мкА в глубокой спячке 2) M24M02-DR, 256 Кбайт, 3 мкА в спячке.
  5. Ну прямо в лоб-то считать не надо. Ваша таблица по рядам (и по столбцам) будет многократно повторяться. Лучше составьте таблицу одного периода синуса на N=500 точек (для двоичного ЦПУ практичнее брать число N степени двойки, например N=512). Для первой палки считаете МАКи, беря синусы: 0,1,2,..,499 (всего 500), для второй палки берете каждый второй: 0,2,4,..,498,0,2,4,..,498 (всего 500). Для третьей палки берете каждый третий:0,3,6,.. (всего 500) и так далее. Ну и не надо считать компоненты спектра (пресловутые "палки") выше частоты Найквиста, поскольку амплитудный спектр симметричен.
  6. Ну так, заранее вычислите эти коэффициенты и разместите их в таблице. У меня на 100 МГц ДСП двойной МАК для преобразования Фурье вычисляется за 10 нс. Т.о., для 200-500 точек время счёта Re/Im одной палки составит порядка 2-5 мкс. Для 30 частот время счета составит 60-150 мкс. Но это прикид для 100 МГц тактовой, а у вас 168 МГц тактовая, так что о каких секундах может идти речь?
  7. ZX Spectrum на AVR

    Ну вообще-то, при вашем подходе к эмуляции можно легко поднять частоту до примерно 5 МГц. Ещё несколько вопросов. 1) Почему отказались от эмулятора звука? 2) Выдача меандров вместо гармонического сигнала (отрезок синуса) не напрягает? 3) А неустранимая разница частот меандра и гармонического ряда устраивает?
  8. ZX Spectrum на AVR

    Да, речь не идёт о Z80, речь идёт о тактах (машинных циклах-МЦ) эмулятора. Тут на форуме уже было обсуждение протокола XMEM применительно к чипу памяти, надо поискать. А как насчёт микроконтроллера эмулятора? Давайте поглядим попристальнее, где показан цикл выборки команды. Например, выполняется команда чтения LD R16,Z, где Z указывает на ячейку внутреннего озу, команда выполняется за 2 МЦ. Во время первого цикла выбирается команда, во время второго читается байт из внутреннего озу, есть соответствующие рисунки (документ 2467X-AVR-06/11, стр.20, рис. 10). Теперь как будет выглядеть та же команда, когда Z указывает на внешнее озу? Опять должна быть выборка кода команды и его расшифровка (1 цикл), затем выдача ALE, это Т1 на картинке XMEM (с.331, рис.157), возможно, это ещё один цикл, затем 3 цикла на чтение озу, итого набегает 4-5 циклов...Ну не 3 цикла, по крайней мере.
  9. ZX Spectrum на AVR

    Василий, позвольте задать пару вопросов. 1) Какова эффективная частота сэмулированного проца? Где-то прочитал, что 2.33 МГц, это верно? 2) Можно ли поднять частоту эмулирования до 4-6-8-10 МГц, и где и какие могут быть ограничения? 3) В описании авр зх спектрум вы пишете, что цикл обращения к озу составляет 3 такта, хотя вроде бы должно быть 4 такта, где правда?
  10. Преобразование Фурье обоих сигналов должно помочь
  11. Обычно, в начале сообщения передают синхрослово (СС) определенной длины. Вашего байта 0x55 маловато будет для синхронизации. В своё время я использовал СС длиной 32 бита (на фидерной линии), причем программа допускала приём несколько неверных бит в любом месте СС, и то, на шумах каждые 18 минут появлялось ложное СС. Да, добавлю, что 32 битная последовательность имела хорошую АКФ, ну не как у кодов Баркера, а как у М-последовательностей... В вашем случае последовательность будет состоять из N*32 точек, вот с ней и сравнивать. Можно и определенный процент искажений допустить. Для современных процов легко делается в реале.
  12. Варианты есть, можно получить частоты 48 МГц, 24 МГц, 12 МГц и 6 МГц только средствами STM32F103RB6 следующим образом. Выставляем тактовую частоту 48 МГц и выдаём её на пин МСО. Далее, берём TIM1 (или TIM8), ставим три его канала в режим COMPARE, ремапим соответствующие выходы TIM1_CH1, TIM1_CH2, TIM1_CH3. Затем записываем в регистры TIM1_CCR1, TIM1_CCR2 и TIM1_CCR3 значения 2, 4 и 8. Ву а ля. Само собой разумеется, надо настроить пины на выход, всё что надо и где надо разрешить и т.д.
  13. Ну, если у вас от 3,3 вольта всё работало, то единственное объяснение - это a five-volt tolerant I/O port bit. Там прямо на входе ножки стоят два диода, тот который подключен анодом, катодом подключен к спецсхеме, которая сливает излишки выше 3.3 + падение на диоде. Бороться трудно. Как вариант, если скорости вкл/выкл небольшие, можно поставить фотовольтаическую оптопару, например, PVI5033. PC817X тоже может подойти.
  14. Всё можно сделать проще. В качестве ключа переменного тока поставьте встречно два мосфета. Для управления используйте фотовольтаическую оптопару, например, PVI5033, там две пары в корпусе. Чтобы поднять напряжение выхода, соедините пары последовательно. Само собой, включать ключ лучше в нуле. Как-то так.
  15. 1000/19/10 = 5.26 мкс,что соответствует 190 кбит/с. Это что ж у вас за скорость такая нестандартная? Что ж, пора взглянуть на вашу программу. Интересно, как вы буфера переполняете.
  16. Вообще-то, уарт предназначен для работы один-на-один. Поподробнее расскажите, как вы переключаете датчики, какая скорость передачи етц...
  17. Можно ещё попробовать скользящее преобразование Фурье. Если скажем, частота выборок АЦП 1000 Гц, то есть выборка каждые 1 мс, то для получения полосы 25 Гц достаточно 40 точек. Алгоритм такой. 1) Накапливаете 40 точек 2) Вычисляете действительную А и мнимую В части для 50 Гц спектальной линии, получаете амплитуду SQRT(А**2+В**2). 3) Сдвигаетесь на одну точку, повторяете п.2 В процессе циклического вычисления (п.2-п.3) получаете последовательность амплитудных значений. Данную последовательность можно обработать далее, например, для очистки от импульсных помех. Это если делать программно. Можно и аппаратно. Вырабатываете синус 50 Гц и косинус 50 Гц, подаете на два синхронных детектора с фильтрами порядка 20 Гц. Выходы синхронных детекторов приблизительно будут соответствовать действительной А и мнимой В частям выходного сигнала. Далее с помощью МК получаете последовательность амплитудных значений, как и в программном случае.
  18. Ну раз так, то не надо его называть "capture event" Нет ничего проще, как засинхронизировать. В один таймер пишете 0, в другой 1. Запускаете первый, потом второй.
  19. Ничего не сработает. Вы спутали ICR с ICP. Внешнее событие никогда не наступит, поскольку InputCapturePin отключен в режиме 14/15. Ерунду говорите. Таймеры работают от одного источника, поэтому всегда "засинхронизированы". Если ICP1 словит входное событие, то текущее значение счетчика перепишется в ICP1, а таймер1 как считал, так и будет продолжать считать.
  20. Не пойдет, ICP1 отключена и прерывание TIMER1_CAPT_vect никогда не сработает. Ещё один путь - взять МК с двумя ICP1 и ICP3 модулями, таймеры пусть работают синхронно, один модуль будет срабатывать от входного события, а второй будет выдавать fast pwm (14/15). Как-то так.
  21. Ну, насчёт дельности это вы погорячились. Вас легко спасет режим WGM=14 (или 15)
  22. Всё давно придумано до нас. Повнимательнее посмотрите пример приведенного мною кода. В программе на си организованы секции для данных, так что сишная программа знает их адреса и знает про контекст, а ассемблерная может использовать данные адреса. Также все переменные, используемые в ассемблерной (под)программе как глобальные, определены в сишной программе. Например, 64-битная переменная re0, используемая в подпрограмме. Далее, я не призываю писать весь код на ассемблере, в настоящее время генерируемый си-код, как правило, всего на 10-50% объемнее ассемблерного кода. Я призываю крепко подумать, прежде чем использовать асм п\п. Лично я не представляю себе как на си перемножить вышеупомянутую 64-битную переменную re0 на другую 64-битную переменную с получением 128-битного результата. Чем биться с сишными извращениями, мне проще написать подпрограмму на ассемблере. Вот это и есть реалистический подход. Может быть пример и не показателен, это просто пример автору темы, как можно решить вставшую перед ним проблему.
  23. Ерунда на постном масле, причём здесь стек? Ну вызвали вы подпрограмму, ну взяли вы адрес ячеек, который сгенерила сишная программа, ну вызвали вы из си ассемблерную программу, ну так сохраните регистры, которые она использует. Тем более, что вызов подпрограммы можно оформить отдельной строкой (отдельным оператором), а сишная программа вроде бы не "пересекает" регистры разных операторов (без учёта оптимизации, конечно). Ниже приведен обещанный пример объединения по третьему варианту. Вырвано из рабочего проекта, кое-что удалено, кое-что подправлено. // File: example.c // Title: Example // Version: 1.4 // Last updated: 09.03.13 // Author: GM //Target: ATmega324PA (16MHz operating frequency) // // Support E-mail: [email protected] // // DESCRIPTION // The routine measures #define F_CPU 16000000UL //16MHz #define PI 3.14159265359L #include <avr/io.h> #include <avr/sfr_defs.h> #include <avr/pgmspace.h> extern void mactest(void); extern void asmroutine(void); long long volatile re0=0; long long volatile uval; long volts[20] __attribute__ ((section (".block80"))); int ptra,ptrb; unsigned char tab10k/ / __attribute__ ((section (".gentable"))); unsigned char tab10k/380/ = { 128,137,147,157,167,176,185,194, 202,210,217,224,230,236,241,245, 248,251,253,254,255,254,253,251, 248,245,241,236,230,224,217,210 }; int main (void) { double num,R0; int i,j; mactest(); while(1) //loop forever { asmroutine(); re1=0; im1=im1+(((long long)volts[j++])*((long long)sin10[i])); } } ;File: asmroutine.ASM ;Title: asm subroutine example ;Version: 1.1 ;Last updated: 01.06.11 ;Author: GM ;Target: ATmega324PA (16MHz operating frequency) ; ;Support E-mail: [email protected] ; ;DESCRIPTION ; ----------------------- .nolist #include <avr/io.h> // Include device specific definitions .list ;#define tmp1 r16; ;#define rs 0 ;#define rw 1 ;#define e 2 ;#define rst 6; ;#define cs 5; ;#define sclk 4; ;#define sda 3; #define c0 r8 #define c1 r9 #define c2 r10 #define c3 r11 #define d0 r12 #define d1 r13 #define d2 r14 #define d3 r15 #define zl r30 #define zh r31 .global tab25k .global re0 .global im0 .global asmroutine .func asmroutine asmroutine: ldi ZL,lo8(tab25k) ldi ZH,hi8(tab25k) clr c0 clr c1 clr d1 asm1: lpm r0,Z+ lds c0,re0+0 lds c1,re0+1 add c0,d0 adc c1,d1 adc c2,d2 sts re0+1,c1 sts re0+2,c2 sts re0+3,c3 ; rjmp asm1 ret .endfunc
  24. Да ладно :-) С какой стати она будет портить си-контекст, который находится в пзу? Конечно, многое зависит от функциональности данной подпрограммы, и как она связана со всем остальным. Возьмём какой-нибудь пример, скажем, надо сделать два мака над 1000000 выборок и результат положить в две 8-байтные ячейки. Ассемблерная программа берет данные с АЦП, перемножает с синусом и косинусом из таблицы, кладёт результат в определенное место в озу и завершает работу. Сишная программа знает откуда взять результат, там место зарезервировано, и берет его. Вот и всё.
×
×
  • Создать...