Доброго времени суток уважаемые форумчане!
Возникла необходимость в генераторе прямоугольных импульсов, обшарив нет я ненашел генераторов частотой выше 500 килогерц (вернее есть один до 4 мегагерц но там регулировка идет ступенями - 31 ступень (джамперами выставляется двоичный код)). Поэксперементировал с таймерами (прочитал с примерами на "Декаде"), по ихним примерам получить частоту больше 490 герц несмог (кварц на тиньке стоит 12 мегагерц)
Сабж хочу собрать на тиньке 2313, регулировка частоты энкодером в обе стороны, частота-ну хотябы до 4 мегагерц, дискретность - пока нерешил(эксперементально).
Поковыряв фьюзы выставил на порт PD2 частоту кварца (12 мегагерц) померял частотомером все в норме есть все 12.
Теперь собственно вопрос - можно ли использовав частоту кварца на порту перехватывать ее и делить получив тем самым нужную мне частоту или всетаки есть какой либо способ получить верхний предел (4 мегагерца) используя таймеры и имея при этом возможность плавной регулировки частоты?
Энкодер думаю поставить на прерывания int0, int1 и обрабатывая прерывания получать в переменные коэффициент деления исходной частоты.
Если есть какие либо мысли помогите пожалуйста (если можно то и код), если что не так прошу не пинать-я только учусь.
Регулируемый генератор импульсов
Сообщений 1 страница 30 из 36
Поделиться12012-01-19 22:32:24
Поделиться22012-01-20 09:30:28
http://www.530.ru/electronics/projects.php?do=p072. Генератор прямоугольных импульсов на AVR. Ридико Л.И. Правда на ассемблере, но идея готовая. AT90S2313 та же тинька 2313.
Поделиться32012-01-24 00:04:29
Посмотрел я этот генератор, честно говоря я непонял какой у него верхний предел
Да и к тому же хочется своими руками и мозгами (конечно же и с вашей помощью) дойти к этому и понять как это работает.
Пока вот только удалось получить частоту в 749,9 килогерц на тиньке с 12 мегагерцовым кварцем.
Если вообще без паузы тогда 1 мегагерц но без регулировки.
Вот собственно код.
$crystal = 12000000
$regfile = "attiny2313.dat"
$hwstack = 32
$swstack = 8
$framesize = 32
Config Pind.6 = Output
Do
Toggle Portd.6
Waitus 0.1
Loop
Честно говоря я недоволен результатом.
Меняя паузу с шагом в 0,1 всеравно получается большая дискретность.
Пробовал на таймре сделать, так чтобы таймер считал не от нуля (записую в него значение (чем больше тем быстрее переполнение)) и по переполнению переключаю порт-результат еще хуже.
Максимальное чего я добился от таймера 5 килогерц - смех.
Пока ума не приложу как выдавить из тиньки хотябы 4 мегагерца с приемлемой дискретностью 
Мажет на асме какую нить вставочку можно притулить чтобы пошустрее бегала тинька?
Помогите плис, всю голову уже сломал, мыслей пока никаких . 
Отредактировано lan44 (2012-01-24 00:11:02)
Поделиться42012-01-25 09:18:44
Вот ссылочка http://radioparty.ru/index.php/device-a … attiny2313 это генератор до 4 мегагерц, исходники на баскоме,
я пока недостаточно квалифицирован для переделки исходника (пока еще не все понял), посмотрите плис может это поможет.
Поделиться52012-01-25 22:23:32
Если добавить к ATMEGE88 две микросхемы 74HC4046A(генератор до 20 МГц с фаз.детектором) и 74Hc74 (2 триггера - делитель на 4),
то можно получить генератор до 16 МГц с разрешающей около способностью 20 Гц (1.2*10^-6).
Как:
1 программный DDS регулируемую формирует опорную частоту до 16.00000 кГц. Тактовая частота 200 кГц (5 мкс) формируется таймером 2. Сумматор и частотное число 24 битное.
2 Частота DDS с помощью с ФАПЧ умножается на 1000 = 4(74hc74 в первом каскаде) * 250(на таймер 0)
Еще масса вариантов
Поделиться62012-01-26 20:17:00
Спасибо, поковырял даташиты - перевариваю. С одной стороны - высокий вехний предел это хорошо но многовато микросхем да и ехать за ними нужно а это в ближайшее время не предвидится.
С другой стороны - есть микроконтролер и исходники которые (я так думаю) можно довести до ума, и плюс к этому выучить баском.
Я вот с этими исходниками сижу и немогу понять, каким образом осуществляется выборка нужного значения из таблицы данных, до этого я невидел примеров в баскоме по работе с таблицами.
Вот весь код
$crystal = 8000000
$regfile = "attiny2313.dat"
$hwstack = 32
$swstack = 8
$framesize = 32
Dim F As Byte , F_input As Byte , Clkpr_prescale As Byte
Dim Ocr1a_value As Word , Ocr0a_value As Byte
Dim Clock_prescale As Word
Config Pinb.2 = Output
Config Pinb.3 = Output
Config Portd = Input
Portd = &HFF
F = 255
Do
F_input = Pind And &H1F 'check switch combination
If F <> F_input Then 'if changed,
F = F_input
Gosub Set_f 'set new frequency
End If
Loop
Set_f:
Stop Timer0
Stop Timer1
Timer0 = 0
Timer1 = 0
Ocr0a_value = Lookup(f , Ocr0a_table)
Ocr1a_value = Lookup(f , Ocr1a_table)
Clock_prescale = Lookup(f , Clock_prescale_table)
Clkpr_prescale = 0
While Clock_prescale > 1
Shift Clock_prescale , Right
Incr Clkpr_prescale
Wend
Clkpr = &B10000000
Clkpr = Clkpr_prescale
If F < 31 Then 'f <= table_entries #
If Ocr0a_value = 0 Then
Gosub Set_high_f
Else
Gosub Set_low_f
End If
Else
Set Portb.3
End If
Return
Set_high_f: '4MHz-1Hz
Decr Ocr1a_value
Compare1a = Ocr1a_value
Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1 'start Timer1
Return
Set_low_f: '0.8Hz-0.1Hz
Decr Ocr0a_value
Ocr0a = Ocr0a_value
Config Timer0 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1 'start Timer0
Decr Ocr1a_value
Compare1a = Ocr1a_value
Config Timer1 = Counter , Edge = Falling , Compare A = Toggle , Clear Timer = 1 'start Timer1
Return
'for $crystal = 8MHz & table_entry 0-26:
'f = 8000000 / (2*clock_prescale*(1+ocr1a_value))
'for $crystal = 8MHz & table_entry 27-30:
'f = 8000000 / (2*clock_prescale*(1+ocr1a_value)) / (2*(1+ocr0a_value))
Clock_prescale_table: '[1-256]
Data 1% '0: 4 MHz
Data 2% '1: 2 MHz
Data 4% '2: 1 MHz
Data 1% '3: 800 kHz
Data 2% '4: 400 kHz
Data 4% '5: 200 kHz
Data 8% '6: 100 kHz
Data 2% '7: 80 kHz
Data 4% '8: 40 kHz
Data 8% '9: 20 kHz
Data 16% '10: 10 kHz
Data 4% '11: 8 kHz
Data 8% '12: 4 kHz
Data 16% '13: 2 kHz
Data 32% '14: 1 kHz
Data 8% '15: 800 Hz
Data 16% '16: 400 Hz
Data 32% '17: 200 Hz
Data 64% '18: 100 Hz
Data 16% '19: 80 Hz
Data 32% '20: 40 Hz
Data 64% '21: 20 Hz
Data 128% '22: 10 Hz
Data 32% '23: 8 Hz
Data 64% '24: 4 Hz
Data 128% '25: 2 Hz
Data 256% '26: 1 Hz
Data 32% '27: 0.8 Hz
Data 64% '28: 0.4 Hz
Data 128% '29: 0.2 Hz
Data 256% '30: 0.1 Hz
Data 256% '31: stop
Ocr1a_table: '[1-65535], Ocr1a = Ocr1a_table_entry - 1
Data 1% '0: 4 MHz
Data 1% '1: 2 MHz
Data 1% '2: 1 MHz
Data 5% '3: 800 kHz
Data 5% '4: 400 kHz
Data 5% '5: 200 kHz
Data 5% '6: 100 kHz
Data 25% '7: 80 kHz
Data 25% '8: 40 kHz
Data 25% '9: 20 kHz
Data 25% '10: 10 kHz
Data 125% '11: 8 kHz
Data 125% '12: 4 kHz
Data 125% '13: 2 kHz
Data 125% '14: 1 kHz
Data 625% '15: 800 Hz
Data 625% '16: 400 Hz
Data 625% '17: 200 Hz
Data 625% '18: 100 Hz
Data 3125% '19: 80 Hz
Data 3125% '20: 40 Hz
Data 3125% '21: 20 Hz
Data 3125% '22: 10 Hz
Data 15625% '23: 8 Hz
Data 15625% '24: 4 Hz
Data 15625% '25: 2 Hz
Data 15625% '26: 1 Hz
Data 15625% '23: 0.8 Hz
Data 15625% '24: 0.4 Hz
Data 15625% '25: 0.2 Hz
Data 15625% '26: 0.1 Hz
Data 0% '31: stop
Ocr0a_table: '[1-255, 0=not used], Ocr0a = Ocr0a_table_entry - 1
Data 0 '0: 4 MHz
Data 0 '1: 2 MHz
Data 0 '2: 1 MHz
Data 0 '3: 800 kHz
Data 0 '4: 400 kHz
Data 0 '5: 200 kHz
Data 0 '6: 100 kHz
Data 0 '7: 80 kHz
Data 0 '8: 40 kHz
Data 0 '9: 20 kHz
Data 0 '10: 10 kHz
Data 0 '11: 8 kHz
Data 0 '12: 4 kHz
Data 0 '13: 2 kHz
Data 0 '14: 1 kHz
Data 0 '15: 800 Hz
Data 0 '16: 400 Hz
Data 0 '17: 200 Hz
Data 0 '18: 100 Hz
Data 0 '19: 80 Hz
Data 0 '20: 40 Hz
Data 0 '21: 20 Hz
Data 0 '22: 10 Hz
Data 0 '23: 8 Hz
Data 0 '24: 4 Hz
Data 0 '25: 2 Hz
Data 0 '26: 1 Hz
Data 5 '27: 0.8 Hz
Data 5 '28: 0.4 Hz
Data 5 '29: 0.2 Hz
Data 5 '30: 0.1 Hz
Data 0 '31: stopНа первый взгляд код небольшой (большую часть занимают таблицы), вот если бы можно было бы переделать его так чтобы выборка значений шла не из таблиц а из переменной и отучить контролер смотреть на конфигурацию входных пинов.
Поделиться72012-01-26 21:15:41
Это программа - просто шарманка.
Максимум, что можно добиться на этом принципе - делить кварц на 2, на 3, на 4 и т.д. до 65535. На 1 получается убогий пичек
Поделиться82012-01-26 22:12:43
Просматривал форумы по поводу генератора Ридико Л.И. стало ясно - каждая операция занимает такт, чем больше процедур (соответственно длинна программы) тем меньше шансов получить
более высокую частоту на выходе, возникает вопрос - можно ли вообще на баскоме написать достойный генератор меандра (скажем при кварце 20 мегагерц на тиньке) частотой хотябы до 2 мегагерц?
Может это можно реализовать только на асме?
Одного только немогу понять, таймеры, все вроди бы должно было бы работать, сокращай себе время заполнения и получай то что хотел но, чет неработает
Может я чет делаю не так? Кто нить пробовал на таймерах выжать максимум?
Поделиться92012-02-01 00:51:06
Сколько не пробовал - пока немогу получить желаемого.
Вопрос к уважаемому dmm - учитывая ваш профессионализм и знания в асме скажите плис, можно ли добится от этого генератора частоты в 2 мегагерца написав код на асме? Можно ли это организовать в баскоме? Если можно то как?
Я помню ваше высказывание о том что нужно не просто спрашивать а и что либо делать самому, поверьте, в силу своих знаний в баскоме испробовал все что знал (знаю немного) пока не получил результата, надеюсь на вашу помощь.
Я не прошу готовый код, просто небольшой пример который можно развить дальше.
Отредактировано lan44 (2012-02-01 00:54:32)
Поделиться102012-02-01 17:27:50
Генератор аппаратный, на таймере 0, 1 или 2. Режим FAST PWM. программа его только загружает
Поделиться112012-02-01 22:56:31
Порыл информацию о режимах, при работе таймера в режиме Fast PWM меняется скважность (отношение периода импульса к его длительности) тоесть ШИМ.
Каким образом можно менять частоту в этом режиме если мне к примеру нужно получить симетричный меандр?
Поделиться122012-02-02 12:56:20
В режиме FAST PWM (MODE 14) можно регулировать и длительность периода, и длительность импульса. Например, период - ICR1, длительность - OCR1A, выход - OC1A. Выдерживай соотношение их 1/2 - это меандр.
Поделиться132012-08-09 09:02:47
Здравствуйте, нужен генератор с регулировкой от 1 до 50 Гц и регулировкой скважности от 25 до 75%, может у кого то есть? Схему (как я её вижу) прилагаю http://s1.uploads.ru/i/26jU1.png
Поделиться142013-01-27 16:14:22
У меня есть на меге48.
Поделиться152013-04-08 22:17:50
$regfile = "attiny45.DAT"
$crystal = 1000000
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Dim V As Word
Dim W As Single
Dim R As Byte
Dim V1 As Word
Dim W1 As Single
Dim R1 As Byte
Clkpr = &H80
Clkpr = &H8 'делит частоту
Tccr0a = &HB1
Tccr0b = &H09
Tcnt0 = 0
Config Portb = Output
Start Adc
Do
V = Getadc(2)
W = V / 4
R = Round(w)
V1 = Getadc(3)
W1 = V1 / 4
R1 = Round(w1)
Ocr0a = R
Ocr0b = R1 'всё, на выходе оcr0b выход генератора Значение Ocr0a должно быть больше Ocr0b .
' "В эти значения загоняем число от 0 до 255 и получаем частоту."
'выводим числовое значение переменной
Loop
End
Поделиться162013-04-09 09:22:53
Получение сигнала произвольной скважности
Чтобы получить на выходе генератора сигнал произвольной скважности, т.е. сигнал, для которого длительности импульса и промежутка между импульсами не равны, необходимо производить перезагрузку регистра сравнения два раза за период. Это уже требует некоторых действий от программы. Главным здесь является то, что формирование сигнала по-прежнему происходит на аппаратном уровне. Программа лишь загружает нужные значения длительностей, от нее просто требуется успеть это сделать вовремя. 
Метод получения такого сигнала проиллюстрирован на рисунке. Для примера рассматривается режим генерации положительных импульсов. В момент возникновения события совпадения переключается состояние выхода OC1, который настроен на переключение по совпадению (режим «toggle»). В данном примере он переключается с нуля в единицу. Перезагрузка регистра сравнения OCR1A осуществляется в обработчике прерывания, который вызывается с некоторой задержкой (эта задержка называется interrupt latency). Перезагрузка должна быть произведена обязательно до того момента, когда должно произойти новое совпадение. Именно время выполнения обработчика прерывания ограничивает минимальную длительность импульсов в данном режиме. Поэтому принят ряд мер для уменьшения этого времени. Перезагрузка осуществляется величиной, которая определяет длительность единицы, в данном примере это длительность импульса d. При следующем совпадении выход OC1 переключается из единицы в ноль и осуществляется перезагрузка регистра сравнения длительностью нуля, в данном примере это разность периода и длительности P-d. Никаких вычислений в прерывании не производится, длительности нуля и единицы основная программа передает сразу «готовыми к употреблению».
Взято отсюда http://www.530.ru/electronics/projects.php?do=p072. Сам использовал такой метод для формирования импульсов. Правда НЧ, но мне так нужно было.
Отредактировано sva-don (2013-04-09 09:25:43)
Поделиться172019-12-07 16:42:09
Здравствуйте, у меня появилась подобная потребность в генераторе, я его реализовал таким образом, работает, но есть одно но, таймер иногда переполняется по кругу (при малых значениях АЦП) самостоятельно, судя по выводу в терминал, может кто подскажет,в чем проблема?
$regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600
dim set_time as Word
Config Adc = Single , Prescaler = auto , Reference = avcc
Enable Interrupts
Enable Timer1
start adc
Do
set_time = Getadc(0)
Compare1a = set_time
Config Timer1 = Timer , Prescale = 1024 , Compare A = Toggle , Clear Timer = 1
print Timer1; " "; set_time
loop
end
Отредактировано stas732 (2019-12-07 19:47:09)
Поделиться182019-12-07 20:59:14
таймер иногда переполняется по кругу (при малых значениях АЦП) самостоятельно
Если я правильно понял, то у вас таймер заскакивает выше значения set_time. Было у меня такое на Меге8, когда делал MP3 плеер. Победить не смог, пришлось программно игнорировать эти значения.
А зачем вы в главном цикле постоянно конфигурируете таймер? Достаточно сделать это один раз в начале программы.
Поделиться192019-12-07 21:39:53
Конфигурацию делал по одному из примеров, перенес в начало,при инициализации, эффект тот же
Поделиться202019-12-07 21:41:37
Пока ограничил с помощью
if timer1 > set_time then timer1= set_time
но это костыль
Поделиться212019-12-07 22:22:51
if timer1 > set_time then goto подпрограмма
А в этой подпрограмме производите измерение АЦП. У меня так все работает четко.
Поделиться222019-12-08 20:06:12
То есть перенести
set_time = Getadc(0)
в подпрограмму при переходе goto ?
Поделиться232019-12-08 20:44:33
Ну, я не знаю, как у вас код устроен. GOSUB подразумевает выход из п/п по RETURN'у. А у вас есть куда выходить?
У меня так сделано:
Main:
Stop Timer1
Track_number = Timer1
If Track_number = 0 Or Track_number > All_tracks Then ' если значение = 0 или больше максимального
Start Timer1
Goto Main
End if
Поделиться242019-12-09 11:29:51
Попробуйте "FREE" режим в АЦП, ибо если сингл, то в режиме "авто" быстрее 1 мс работать скорее всего не будет (1КГц).
Поделиться252019-12-09 18:04:46
К сожалению ,этот фокус не работает, таймер продолжает заказываться за "горизонт" моей уставки переполнения
Поделиться262019-12-09 20:17:18
Вы бы выложили весь код, так проще было бы.
Поделиться272019-12-09 20:21:50
Выложу еще раз,немного изменив
$regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600
dim set_time as Word
Config Portd.7 = Output:Portd.7 =0
Config Adc = free , Prescaler = auto , Reference = avcc
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Timer , Prescale = 1024 , Compare A = Toggle , Clear Timer = 1
Enable Interrupts
Enable Timer0
Enable Timer1
On Timer0 button
start adc
main:
set_time = Getadc(0)
Compare1a = set_time
goto main
end
button:
print Timer1; " ";set_time
returnОтредактировано stas732 (2019-12-09 20:23:04)
Поделиться282019-12-09 20:55:18
Если указать размер переполнения вручную, в основном цикле, то все в порядке, таймер не переполняется, все работает отлично
Поделиться292019-12-09 21:17:32
А если так:
Do main: set_time = Getadc(0) Compare1a = set_time if Timer1 > set_time then goto main print Timer1; " ";set_time loop
Поделиться302019-12-09 21:25:29
У вас после отсчета таймера, на каждом цикле выполняется "print" (да ещё в прерывании и вешает всю систему), если он работает не через буфер, а напрямую, то происходит как раз задержка и сбивка. Таймер т.к. аппаратный, он успевает за время софтовой отправки данных насчитать.
Выводить данные лучше один раз и в основном теле программы, а как раз в таймер поместить "Compare1a = set_time". Второй таймер можно не использовать. Что-то вроде:
Config Timer1 = Timer , Prescale = 1024 , Compare A = Toggle , Clear Timer = 1
Dim Mem_time as Word
Enable Interrupts
Enable Timer1
On Timer1 L00
start adc
Do
set_time = Getadc(0)
If Mem_time<>set_time Then
Mem_time=set_time
print Timer1; " ";set_time
End If
Loop
End
L00:
Compare1a = set_time
return
Впрочем по идеи можно и ещё проще:
Config Timer1 = Timer , Prescale = 1024 , Compare A = Toggle , Clear Timer = 1
Dim Mem_time as Word
Enable Interrupts
Enable Timer1
start adc
Do
set_time = Getadc(0)
If Mem_time<>set_time Then
Mem_time=set_time
Compare1a = set_time
print Timer1; " ";set_time
End If
Loop
End
В общем, на время изменения параметра сравнения, надо останавливать таймер, иначе он сравнивать будем скажем с числом 15, а таймер уже пролетел это число и получается пропуск (полный цикл). Конечно первый вариант кода более синхронный, т.к. загрузка изменения происходит на новом цикле.