Делаю частотомер. Остановился на измерении количества импульсов с помощью Counter на портах Т0(1).
Часть кода:
Start Counter0
Waitms Wtime
Stop Counter0
Считает нормально. Но Wait не точное время, соответственно измерения не точные. Пробовал запускать TIMER1, и считать по переполнению.
Frequensy:
Counter0 = 0
Timer1 = 65286 '$crystal = 16000000, Prescale = 64, задержка 1mS - 250 тиков таймера.
Overcounter = 0
Start Counter0 : Start Timer1
Waitms 300 'Время для ожидания прерывания. Мне нужно максимальное время измерения 256 mS.
Return
'----------------
Schet: 'Прерывание TIMER1
Stop Counter0
Stop Timer1
Timercounter = Counter0 'Частота на входе Т0, без подсчета переполнений.
Return
Подсказали, что таймер стартует тоже с задержкой.
Какие способы создания задержек еще существуют?
Как зделать более точную задержку чем Wait?
Сообщений 1 страница 30 из 57
Поделиться12018-12-12 09:55:05
Поделиться22018-12-12 10:48:20
$regfile = "m8adef.dat" $crystal = 4000000 $hwstack = 12 $swstack = 12 $framesize = 32 Dim Znach_timer1 As Word Config Timer1 = Timer , Prescale = 1 Stop Timer1 Timer1 = Znach_timer1 On Timer1 Puls Start Timer1 Enable Interrupts Enable Timer1 'Получаемый интервал (65536-Znach_timer1)/4000000=0,008384 секунд 'Изменяя значение Znach_timer1 до 65535 можете задать интервал с точностью до 0,00000025 секунд 'для получение других интервалов можно менять прескализацию, частоту МК, выбрать др. таймеры Do Znach_timer1 = 32000 ' Loop Puls: Stop Timer1 Timer1 = Znach_timer1 Start Timer1 Return End
Отредактировано Niya (2018-12-12 10:53:15)
Поделиться32018-12-12 11:15:03
Пользовался таким способом (ассемблер).
delay14: ' п/п задержки LDI R18, 14 ' в регистр R18 значение SPEED delay14loop: DEC R18 ' уменьшение на 1 содержимого R18 BRNE delay14loop ' переход, пока флаг Z не будет равен 0 ret ' выход из п/п задержки после выполнения 14 тактов
В данном случае - задержка на 14 тактов МК.
Можно "растянуть" до 255... 
Отредактировано Nord (2018-12-12 14:04:03)
Поделиться42018-12-12 11:45:10
Чот я не понял, зачем вообще частотомеру иметь задержку. Обычно меряют не количество импульсов за время, а интервал.
Это быстрее работает (считай чисто аппаратно, минимум кода) и позволяет сократить время измерения.
Поделиться52018-12-12 11:49:10
Nord
Понимаю этой частью кода можно заменить Wait. Но в (ассемблер) полный "0".
Если МК работает на частоте 16мГц, такт 1/16000000 = 4 mkS, 0.004 Ms.
Мне нужно 256 mS, это 256/0.004 = 64000 тактов.
Правильно понимаю? Если это так, значит то, что надо.
В моем случае перед МК стоит ВЧ делитель на 64, или 256(переключается). Если придется мерить без делителя, то 1кГц, 100mS.
Настораживает этот коммент:' выход из п/п задержки после выполнения ~14 тактов. Именно значек примерно. 
Поделиться62018-12-12 12:05:12
RDW
С этого начал. Захват импульса по порту ICP1. В Меге8 PB0. Столкнулся с вечным прерыванием если на входе нет импульсов, и как остановить прерывание после подсчета периода сигнала для продолжения работы основной программы.
Поделиться72018-12-12 12:53:24
Столкнулся с вечным прерыванием если на входе нет импульсов, и как остановить прерывание после подсчета периода сигнала для продолжения работы основной программы.
Значит алгоритм неправильный.
Берём таймер, который считает время.
Берём любой тип прерывания, например INT0.
Вариант 1:
- Если счет ещё не запускался, то по приходу на INT импульса, сбрасывается таймер (счет) и запускается (хотя правильнее его сбрасывать после подсчета, на завершении).
- Если счет запущен, то приход импульса на INT останавливает счёт и ведётся подсчет времени работы таймера (чтение из него значения).
Недостатки данного варианта: требуется два импульса "старт/стоп", т.е. как бы два такта, меньше производительность. Если такой подход точный ненужен, то делаем вторым вариантом.
Вариант 2:
- Запускаем таймер и ждём, когда сработает прерывание по INT.
- Если придет импульс по INT, то сразу читаем значения из счетчика таймера и сбрасываем его (сам счет).
Недостаток алгоритма: если долго нет импульсов, то таймер/счетчик переполняется, для этого можно предусмотреть механизм вывода макс значения счета, что будет говорить об отсутствии импульсов на входе прерывания.
Оба алгоритма используют аппаратный таймер (что не влияет на погрешность счета) и прерывание, которое очень быстро отрабатывает. В итоге на основной код выполнения программы МК это всё не влияет.
Таймер лучше сразу использовать 16 разрядный.
Я этот алгоритм даже использовал для подсчета скорости выполнения кода программы с разным набором данных/алгоритма. Типа бэнчмарк, только результат был в мс.
Единственное, есть общая проблема, подобрать правильно делитель для таймера, чтобы не выходить за разрешающую способность таймера/счетчика. Мне такое было ненужно, но можно и это предусмотреть, динамическое изменение параметров пред делителя таймера.
Поделиться82018-12-12 14:01:15
Понимаю этой частью кода можно заменить Wait. Но в (ассемблер) полный "0". Если МК работает на частоте 16мГц, такт 1/16000000 = 4 mkS, 0.004 Ms.Мне нужно 256 mS, это 256/0.004 = 64000 тактов.Правильно понимаю?
Можно сделать вложенный цикл: 250 отсчетов по 255.
Только если известна длительность задержки, то зачем такой компот ?
На проще ли использовать Waitms 256 ? 
При использовании кварца погрешности минимальны...
Недостаток, что программа "замрет" на 256 mS...
Поделиться92018-12-12 14:03:48
Настораживает этот коммент:' выход из п/п задержки после выполнения ~14 тактов. Именно значек примерно.
Остался от экспериментов... 
Убрал.
Поделиться102018-12-12 14:12:23
rom-i,
Вы как будто не слышите что говорят. Спросили как получить разные интервалы, вроде, накидал код....А Вы все с эти wait-ом возитесь. Я Вам в другой ветке ответил , как можно избавиться от
Столкнулся с вечным прерыванием если на входе нет импульсов,
Тут RDW Вам разжевал этот алгоритм. Вот Вам переделанный выше код по
Берём таймер, который считает время.
Берём любой тип прерывания, например INT0.
Вариант 1:
- Если счет ещё не запускался, то по приходу на INT импульса, сбрасывается таймер (счет) и запускается (хотя правильнее его сбрасывать после подсчета, на завершении).
- Если счет запущен, то приход импульса на INT останавливает счёт и ведётся подсчет времени работы таймера (чтение из него значения).
.
$regfile = "m8adef.dat"
$crystal = 4000000
$hwstack = 12
$swstack = 12
$framesize = 32
Dim Flag_int0 As Boolean , Flag_net_impulsov As Boolean
Dim Znach_timer1 As Word
Dim Sledim_za_vrem As Word
Config Timer1 = Timer , Prescale = 1
Enable Timer1
On Timer1 Perepolnenie
Config Int0 = Rising
Enable Int0
On Int0 Puls
Enable Interrupts
Do
'если нет импульсов в течении 8 сек останавливаем таймер
If Flag_net_impulsov = 1 Then
Flag_net_impulsov = 0
Sledim_za_vrem = 0
Stop Timer1
Timer1 = 0
end if
'тут делаем с Znach_timer1 что хотим '
Loop
End
Puls:
Sledim_za_vrem=0
Toggle Flag_int0
If Flag_int0 = 1 Then Start Timer1
If Flag_int0 = 0 Then
Stop Timer1
Znach_timer1 = Timer1
Timer1 = 0
End If
Return
'--------Прерывания от переполнения таймера-----------------------------
'Если был запушен таймер от INT0, но
'не было следующего импульса, чтобы остановить таймер
',то будем следить за переполненияи от таймер
Perepolnenie:
Incr Sledim_za_vrem
If Sledim_za_vrem > 500 Then Flag_net_impulsov = 1 ' ~8 секунд
Return
Отредактировано Niya (2018-12-12 14:50:38)
Поделиться112018-12-12 17:48:25
Niya
Код Ваш вполне понятен. Первое прерывание по INT сбрасывает таймер счета, второе начинает. Третье сбрасыват, четвертое начинает. И так с частотой 5мГц. Прерывание ни кто не отменял. Когда программе работать? Измерение частоты у мну занимает 7% Мега8 общей программы. Вся пока занимает 87%. Да, и точность измерения Т количеством тиков таймера не сильно точен.
Спасибо за предложение, но тема задана именно про создание точных задержек.
Поделиться122018-12-12 18:05:41
Можно сделать вложенный цикл: 250 отсчетов по 255.
Только если известна длительность задержки, то зачем такой компот ?
На проще ли использовать Waitms 256 ?
При использовании кварца погрешности минимальны...
Недостаток, что программа "замрет" на 256 mS...
Программа по любому замрет на время измерения. Это нормально, и не хуже. Иначе будет мельтешить цифрами. Тем более основная часть программы, измерение напряженности поля. Здесь работает АЦП. Тоже есть дрейф, и эфирные шумы.
Этот компот нужен для точности. Waitms 256, далеко не 256 мСек. Даже протеус это показывает.
Вот как реализовать Ваш подход(тоесть заменить Wait на Ваше предложение)?
ИП+ частотомер
Отредактировано rom-i (2018-12-12 18:07:25)
Поделиться132018-12-12 18:46:32
конкретно это как?
Зная входную частоту и информацию о пред делители, можно подсчитать с определенной точностью период входного сигнала:

Заполнение периода более высокой частотой с дальнейшим подсчетом количеством импульсов. Понятно, что: чем ближе частота входного сигнала к заполняемому - тем больше погрешность и меньше точность измерения.
В нашем случае, роль "заполнителя" выступает таймер.
Сильнее некуда уже разжевывать. 
По этому:
допустим измеряем в 1 случае 1_000_000 гц а во втором случае 1_000_010 гц?
Чтобы суметь оценить такую разницу, частота заполнения должна быть явно в разы выше входной (тут даже можно вспомнить теорему Котельникова).
Слабое звено является 16 разрядный таймер, у которого всего лишь 65536 значений для счета. Может не получится сразу считать в одном диапазоне 1МГц и 10 Гц, я об этом писал выше.
Можно конечно сделать свой счетчик вместо таймера с большей разрядностью, но т.к. это будет уже программная составляющая (не аппаратная), то результаты могут быть немного не линейными и доп нагрузка на производительность МК (и как следствие, невозможность реализовать измерение высоких частот).
Отредактировано RDW (2018-12-12 19:04:04)
Поделиться142018-12-12 22:50:30
Waitms 256, далеко не 256 мСек. Даже протеус это показывает.
Протеус правду показывает только в одном случае - после нажатия "Стоп"... 
Это - симулятор, а не анализатор... 
Вот как реализовать Ваш подход (тоесть заменить Wait на Ваше предложение)?
bulat943 в #17 расписал.
Осталось вам только свои (нужные) значения подставить... 
Поделиться152018-12-13 00:27:16
Да, и точность измерения Т количеством тиков таймера не сильно точен.
Это кто такое сказал? Вроде, во всех книжках написано, что точное время надо получать таймерами. Одной из функцией таймеров и есть получение точных интервалов времени. При частоте 8 МГц(прескал =1) можете получить интервалы с точностью до 1/8*10^6=0.125мкс! Этого мало?
Что составляет ~0,000049% от Ваших 256мс.
Простым кодом ,на родном Bascom типа этого ( при 8Мгц)
Config Timer1 = Timer , Prescale = 64
Enable Timer1
Zaderzka:
Start Timer1
Do
'
Loop Until Timer1 = 31910
Stop Timer1
Timer1 = 0
получите свои 256мс с точностью в микросекундах (Bascom показывает 256,0498 мс)
Или можете пойти путем предложенным товарищем bulat943.Но там надо вычислять количество циклов, их перевести в кол-во тактов(за сколько тактов выполняется каждая команда Ассамблера) , такты на время....
Отредактировано Niya (2018-12-13 00:58:25)
Поделиться162018-12-13 08:05:20
Niya
Вот мне, и ненравиться считать задержку TIMER1. Частоту поднял до 16мГц. Что бы получить 256мС, нужно в таймере выставить Prescale = 64. Не меньше. Даже при предделителе 64, 1 тик в моей схеме это 6.5кГц. 8 таймер будет переполняться.
Хочу попробовать как предлогает bulat943
Но там ничего не понимаю. В Баском на уровне первого класса, в асемблере "-0".
Как с этим кодом общаться, и как его вставить вместо Wait.
Start Counter0
Wait
Stop Counter0
Отредактировано rom-i (2018-12-13 08:09:13)
Поделиться172018-12-13 09:34:58
Частоту поднял до 16мГц.
Наоборот надо уменьшать, а не увеличивать. Например при 1 Мгц выставив колчество тиков =250 , прескализацию 1024 для Timer0 вы получите :
250*1024/1_000_000=0,256 с
свои желанные 256 мс
Config Timer0 = Timer , Prescale = 1024
Enable Timer0
Zaderzka:
Start Timer0
Do
'
Loop Until Timer0 = 250
Stop Timer0
Timer0 = 0и можете обратиться к этой метке Zaderzka когда требуется. Если не хотите уменьшить частоту , то при тех же конфигурациях , но при частоте 8Мгц получите 32 мс . Прогнав его через цикл 8 раз , опять получите свои 256 мс. Так что, вариантов много.........
Отредактировано Niya (2018-12-13 09:43:39)
Поделиться182018-12-13 10:21:13
Niya
Тогда начинается парадокс.
Нелзя уменьшать частоту посколько, CounterX может правильно считать только <40% от тактовой.
Решил сделать так:
$crystal = 16000000
Config Timer1 = Timer , Prescale = 1
On Timer1 Schet
'***************************
Frequensy:
Overtime = 0
Overcounter = 0
Counter0 = 0
Timer1 = 32768
Start Counter0 : Start Timer1
Waitms 300
Return
'------------------------------------
Schet:
Incr Overtime
If Overtime = 63 Then
Stop Counter0 : Stop Timer1
Timercounter = Counter0
End If
Return
В железе нечем проверить(нет частотомера). Протеус? Врет, или нет...... завышает.
На вход подаю 1мГц, на индикаторе 256.013мГц вместо 256.000мГц.
Поделиться192018-12-13 21:34:33
bulat943
Не затруднит комменты добавить к этим строкам кода. Попробовать делать разное время задержек.
ldi r18, 82
ldi r19, 43
ldi r20, 0
L1: dec r20
brne L1
dec r19
brne L1
dec r18
brne L1
lpm
nop
Правда, говорил мой батя: пробуют девочьки, а потом рожают.)))
Отредактировано rom-i (2018-12-13 21:34:50)
Поделиться202018-12-13 22:36:57
Для МК 8 Мгц, прескализация=1
'Такты: nop -1,Push-2,ldi-1,Dec-1,brne-1/2,breq-1/2,pop-2,rjmp-2
Vremja:
$asm
Push r16 'Cохраняем содержимое регистра r16
push r17 'Cохраняем содержимое регистра r17
push r18 'Cохраняем содержимое регистра r18
ldi r18,10 'Записываем в r18 константу задержки
Wt1:
Dec R18 'Уменьшаем значение регистра r18
breq wt4 'если содержимое r18=0,то переходим на wt4
ldi r17,255
Wt2:
dec r17
breq wt1
ldi r16,255
Wt3:
Dec R16
brne wt3 'Если не ноль , то продолжаем цикл
rjmp wt2
Wt4:
pop r18 'Восстанавливаем содержимое регистров
pop r17
pop r16
$end Asm
как определить временные интервалы
Например Wt3: цикл выполняется 255 раз.
КомандаDec-выполняется за 1 такт
Команда Brne - за 1 такт.если не вызывает перехода;за 2 такта , если вызывает
Значит всего тактов 3, а в цикле 3*255=765. Время на цикл 765*(1/8*10^6)=95.625 мкс
Wt2 крутить этот цикл Wt3 255 раз значит получаем время 24,384375 мс
+255 раз выполняется rjmp - 2 такта 255*2= 510*0,125мкс=0,06375 мс
Общее время двух циклов Wt2,Wt3 =24,448125 мс
Wt1 прогоняет все это дело еще 10 раз получаем 244,48125 мс
У нас 16 -ая строка выполняется 1 раз -это 1 такт, 20-255 раз, 24-255*255= 65025
65 281*0,125мкс=8,160125 мс
3раза Push, 3 раза Pop - 12 тактов*0,125мкс=0,0015 мс
Итого получаем:244,48125+8,160125+ 0,0015=252,642875 мс
Могу ошибится где-то, пусть товарищи поправять
.....все это нудно .............но надеюсь смысл понятен
Отредактировано Niya (2018-12-13 22:42:11)
Поделиться212018-12-13 23:02:41
bulat943
И не только здесь. Оказывается в МК идут аппаратные задержки. Не может он быть таким быстрым. Нашел статью про это. Старт порта для захвата импульса, уже задержка в 2 такта. И ТД. Но хорошо, что эта задержка не плавает. Ее можно(нужно) корректировать. В моей пруге она составила 77 тактов TIMER1, с Prescale = 1. При любых временных задержках. 256, 64, 1. Даже со временем измерения 1мС, все равно 77 тактов. Это радует, что все стабильно.
Поделиться222018-12-14 14:33:44
$regfile = "2313def.dat" ' Частотомер 50.00 Герц
$crystal = 4000000 ' компилятор BASCOM
In_hertz Alias Pind.6
Declare Sub Byte2led(data_2byte As Word)
Dim Tempb As Byte , Data_2byte As Word , Tempw As Word
Dim Data_1 As Byte , Data_2 As Byte , Data_3 As Byte , Data_4 As Byte
Dim Tyscha As Byte , Sotka As Byte , Desaytka As Byte , Edinica As Byte , Timercounter As Single
Config Portb = Output : Portb = 255
Config Pind.6 = Input
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.0 , Rs = Portb.1
Config Lcd = 16 * 2 'configure lcd screen
Config Timer1 = Timer , Prescale = 8 , Capture Edge = Rising
On Capture1 Captmr
Enable Capture1
Enable Interrupts ' разрешаем прерывания и включаем таймер
Lcd "Start..."
' ======================= С Т А Р Т =========================
Start_main_prog:
Cls
Timercounter = 25000000 \ Timercounter ' на входе - частота в 2 раза выше, чем от генератора сигнала!
Tempw = Timercounter
Lcd Tempw
Goto Start_main_prog
' =========================================================
Captmr: ' Считаем импульсы, как-бы наполняем пачками между импульсами
Timercounter = Capture1
Timer1 = 0
Return
Поделиться232018-12-15 18:51:30
удалил свои посты,надо уходить отсюда-толку здесь ноль
Непонятно....Прочитал всю ветку.Вроде, вы выступаете консультирующей стороной. Какой толк должен быть? Должны прислушываться?
Отредактировано Niya (2018-12-15 18:53:36)
Поделиться242018-12-15 21:50:37
Да у меня самого уйма вопросов но вроде как спросить не у кого...не в обиду
Поделиться252018-12-15 22:45:24
уйма вопросов но вроде как спросить не у кого
Сначала НАУЧИСЬ их ПРАВИЛЬНО задавать, а уж потом констатировать тех, кто тебе на них СОИЗВОЛИТ ответить!
И ещё, запомни главное - здесь тебе НИКТО и НИЧЕГО не должен, посему веди себя скромно, проси МАЛО и уходи БЫСТРО (Пётр I)
Поделиться262018-12-16 07:46:06
Да у меня самого уйма вопросов но вроде как спросить не у кого...не в обиду
Как сказал товарищ NMi тут никто ничего никому не должен. И заходят, наверное, когда есть свободное время. Советами, знаниями тут ребята делятся(пишу по своему опыту). Главное, чтобы маякнули, а решение должен найти сам. Не должны же тебе тут готовый код писать? Так что, думаю не стоит так категорически рассуждать .
ЗЫ: Ладно, пофлудили мы тут уже знатно...
Поделиться272018-12-16 08:41:23
Да у меня самого уйма вопросов но вроде как спросить не у кого...не в обиду
Так надо озвучить эту "уйму" - коллективный разум пока не запретили... 
Для того и форум.
А уходить...
ИМХО - самый адекватный русскоязычный форум по Bascom.
Есть и другие, но они полузамороженные...
Поделиться282018-12-16 09:08:14
Nord, почему у вас тут 14 тактов?
delay14: ' п/п задержки
LDI R18, 14 ' в регистр R18 значение SPEED
delay14loop:
DEC R18 ' уменьшение на 1 содержимого R18
BRNE delay14loop ' переход, пока флаг Z не будет равен 0
ret ' выход из п/п задержки после выполнения 14 тактов
LDI- 1 такт
DEC -1 такт
BRNE- 1/2 такта
ret-4 такта
+вызвать подпрограмму , это еще 3 такта(если RCALL)
Получам:
1+14x(1+2)+4+3=50, 50-1=49тактов , потому что BRNE один раз вызывает переход- выполнятся за 1 такт
Итого -49 тактов. Может, вы имели ввиду 14 циклов?
Отредактировано Niya (2018-12-16 09:11:27)
Поделиться292018-12-16 09:36:36
Nord, почему у вас тут 14 тактов?
Может, вы имели ввиду 14 циклов?
Код не мой, возможно, его автор это и имел в виду... 
Это фрагмент кода отсюда: Кириллица на китайских OLED дисплеях
Я стараюсь использовать уже имеющиеся свои и сторонние наработки (кирпичики), если они мне полезны.
Не вижу смысла ломать голову над тем, что уже имеет решение.
Разобраться в чужом и правильно собрать "кирпичики" - вот где порой "головоломка"... 
Поделиться302018-12-16 10:30:50
Спасибо, я понял.