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

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Таймеры, ШИМ и все про них » Как зделать более точную задержку чем Wait?


Как зделать более точную задержку чем Wait?

Сообщений 31 страница 57 из 57

31

bulat943 написал(а):

я дал человеку (автору этой темы) 2 варианта -задержка 1 сек на ассемблере

СерьЁзно?
А какая точность у твоей задержке в одну СЕКУНДУ???
Ты уверен в своём ассемблерном коде? Могу "вставить" глюк, и твой код не будет давать задержку в одну СЕКУНДУ, не изменяя твоего кода ВООБЩЕ.  :flag:

-1

32

Niya написал(а):

Советами, знаниями тут ребята делятся(пишу по своему опыту).

Конечно делятся, на то он и форум.  А вот конкретных ПОПРОШАЕК я лично терпеть ненавижу. Так шо.......... кто на что учился, там и пригодился    :flag:

-1

33

bulat943 написал(а):

автор ответа не дал-помогло или нет

от же с..ка неблагодарная...  :(

-1

34

Всех с Новым годом!!!
В коде на ассемблере ничего не понял. Сильно наворочено. :tired:

0

35

rom-i написал(а):

В коде на ассемблере ничего не понял. Сильно наворочено.

Да не так уж и "наворочено"... ;)
Про какой конкретно "код на ассемблере" идет речь ?
Давайте попробуем разобраться...

PS. Открываем даташит на нужный МК, ищем раздел Instruction Set Summary, находим интересующую мнемонику и складываем паззлы... ;)

Отредактировано Nord (2019-01-04 12:20:25)

0

36

PS. Открываем даташит на нужный МК, ищем раздел Instruction Set Summary, находим интересующую мнемонику и складываем паззлы... ;)

От одного этого предложения уже крышу снесло.

-1

37

rom-i написал(а):

От одного этого предложения уже крышу снесло.

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

Где-то на форуме кидали ссылочку на учебник по Ассемблеру.
Если не найдете, кину, если нужен.

+1

38

На баском не всегда понятно. Много чего незнаю. Напимер предложение изпользовать захват(измерение периода).
Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising
On Capture1 Captmr
Enable Capture1
На вход (ICP1) без перерыва идут импульсы. Идет измерение Т тоже без конца. Как остановить прерывание Captmr?
Для дальнейшей работы программы. В самом прерывании можно делать F=1/T, пересчитывать период самого таймера, выводить на индикатор.
Пробовал Disable Capture1, Stop TIMER1. Прерывание не останавливается.
Только по этому решил мерить количество импульсов за заданное время. Для высоких частот этот метод лучше.
Для звуковых, и ниже, конечно точнее период мерить.

Отредактировано rom-i (2019-01-04 17:43:03)

-1

39

rom-i написал(а):

Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising
On Capture1 Captmr
Enable Capture1

Как остановить прерывание Captmr?

Пробовал Disable Capture1, Stop TIMER1. Прерывание не останавливается.

Для начала добавить Enable Interrupt после (или перед) Enable Capture1, если таковой нет...
Без этой строчки прерывания не разрешены, я уже наступал на эти грабли... ;)
Тогда уже можно играться с Disable и пр...

Отредактировано Nord (2019-01-04 17:53:02)

0

40

Nord
Enable Interrupt прерывания включены, это все прописано. Отключать нельзя, TIMER0 работает на динамическую индикацию. Нужно остановить именно  Capture Edge = Rising(захват), и включить снова когда это необходимо.

0

41

Перевод (не правленный) из даташита (вроде, Мега8, не помню уже)

Ножка ICP1
Когда изменение логического уровня (события) происходит на Pin ввода захвата (ICP1), в качестве альтернативы на выходе аналогового компаратора (ACO), и это изменение подтверждает настройку краевого детектора, будет запущен захват. При срабатывании захвата 16-разрядное значение счетчика (TCNT1) записывается в регистр ввода данных (ICR1). Флаг ввода входного сигнала (ICF1) установлен на одни и те же системные часы, так как значение TCNT1 копируется в регистр ICR1. Если включено (TICIE1 = 1), флаг захвата ввода генерирует прерывание ввода. Флаг ICF1 автоматически очищается при выполнении прерывания. В качестве альтернативы, флаг ICF1 можно очистить программным обеспечением, записав логический бит в его местоположение бит ввода-вывода.
Чтение 16-битного значения в регистре захвата ввода (ICR1) выполняется путем первого чтения младшего байта (ICR1L), а затем старшего байта (ICR1H). Когда считывается младший байт, старший байт копируется в временный регистр с высоким байтом (TEMP). Когда CPU считывает местоположение ввода / вывода ICR1H, он будет обращаться к регистру TEMP.
Регистр ICR1 может быть записан только при использовании режима генерации формы волны, который использует регистр ICR1 для определения TOP-значения счетчика. В этих случаях биты режима генерации формы (WGM13: 0) должны быть установлены до того, как значение TOP может быть записано в регистр ICR1. При записи регистра ICR1 старший байт должен быть записан в местоположение ввода / вывода ICR1H до того, как младший байт будет записан в ICR1L.
Основным источником триггера для блока Input Capture является Pin ввода данных (ICP1). Таймер / счетчик 1 могут альтернативно использовать выход аналогового компаратора в качестве источника триггера для блока ввода. Аналоговый компаратор выбран в качестве источника запуска, установив бит Analog Comparator Input Capture (ACIC) в Analog Controlator Control и Status Register (ACSR). Имейте в виду, что изменение источника триггера может вызвать захват. Поэтому после изменения должен быть сброшен флажок Input Capture Flag.
Входные входы ввода-вывода (ICP1) и входы аналогового компаратора (ACO) отбираются с использованием той же методики, что и для вывода T1 (рис. 30 на стр. 74). Кромковый детектор также идентичен. Однако, когда включен шумоподавитель, перед детектором кромок вставлена дополнительная логика, которая увеличивает задержку на четыре тактовых цикла системы. Обратите внимание, что вход шумоподавителя и краевого детектора всегда включен, если таймер / счетчик не установлен в режиме генерации формы волны, который использует ICR1 для определения TOP.
Захват входа может быть инициирован программным обеспечением, управляя портом выводов ICP1.
Основная проблема при использовании блока ввода-вывода - назначить достаточную емкость процессора для обработки входящих событий. Время между двумя событиями имеет решающее значение. Если процессор не прочитал зафиксированное значение в регистре ICR1 до появления следующего события, ICR1 будет перезаписан новым значением. В этом случае результат захвата будет неправильным.

И, таки...
Сначала Timer1, потом Timer0...
Конкретно...?

Отредактировано Nord (2019-01-04 18:39:31)

0

42

Вот, нашел...
Пользовался как-то этим шаблоном...
При работе программы Disable/Enable Capture1 отрабатывается нормально.

Код:
config TIMER1 = TIMER , PRESCALE = 64 , Capture Edge = Rising       'коэфф.деления 64,импульс по фронту
 
dim Wtime as Byte                                           'объявление переменных
dim Timcount as Word
 
on Capture1 Capt                                            'подпрог. обработки прерывания
 
Wtime = 100
Timcount = 0
 
enable INTERRUPTS                                           'разрешение прерываний
enable Capture1                                             'разрешение  прерываний по захвату
 
Do
Waitms Wtime
Cls
Lcd "Timer:" ; " " ; Timcount
Loop
 
Capt:                                                       'обработка прерывания
Timcount = capture1                                         'считывание из регистра захвата
Timer1 = 0                                                  'сброс таймера
return
 
End                                                         'end program

В подпрограмме  обработки прерывания  информация  Timer1, сброшенная  в  регистр  захвата  capture1  копируется  в  Timcount, затем  таймер  очищается. При  последующем  импульсе  на  ICP  входе  цикл  повторяется, следовательно  Timcount  считает  время  между  импульсами на  ICP.

Отредактировано Nord (2019-01-04 18:49:14)

0

43

Nord
С этого, и начинал. Эту статью брал за основу. Захват идет отлично.
Но:
Capt:                                                       'обработка прерывания
Timcount = capture1                                         'считывание из регистра захвата
Timer1 = 0                                                  'сброс таймера
Disable Capture1              'Не отключило прерывание.
return
Завтра на работе проверю. Мож где накосячил (((.

-1

44

Ножка ICP1
Когда изменение логического уровня (события) происходит на Pin ввода захвата (ICP1), в качестве альтернативы на выходе аналогового компаратора (ACO), и это изменение подтверждает настройку краевого детектора, будет запущен захват. При срабатывании захвата 16-разрядное значение счетчика (TCNT1) записывается в регистр ввода данных (ICR1). Флаг ввода входного сигнала (ICF1) установлен на одни и те же системные часы, так как значение TCNT1 копируется в регистр ICR1. Если включено (TICIE1 = 1), флаг захвата ввода генерирует прерывание ввода. Флаг ICF1 автоматически очищается при выполнении прерывания. В качестве альтернативы, флаг ICF1 можно очистить программным обеспечением, записав логический бит в его местоположение бит ввода-вывода.

Просто стараюсь направить на правильный путь изучения вопроса, а не давать готовое решение... ;)
Да и не я один тут такой... ;)

Отредактировано Nord (2019-01-04 21:03:10)

0

45

rom-i написал(а):

Timer1 = 0                                                  'сброс таймера
Disable Capture1              'Не отключило прерывание.

странно тут поступаете...В подпрограмме прерывание отключаете само прерывание.

Ссылка

......В семействе AVR в процедурах обработки прерываний глобальные прерывания автоматически запрещаются, и процедура обработки прерывания не может быть прервана......

Попробуйте поднять какой-нибудь флаг и после выхода из прерывания по этому флагу запретить захват.
Или вместо  Disable Capture1
остановить Stop Timer1, потом по необходимости  Start Timer1

+1

46

Извиняюсь за свою недолугость. Нашел свою программу где TIMER1 в режиме захвата. Даже макетка еще не разобрана. Здесь все работает отлично. Просто позже решил измерять внешнюю частоту входами Тx(Counter x). На больших частотах это правильнее. По этому тему открыл по поводу более точных задержек чем Wait. А здесь начали снова предлогать захват(Capture1). Только запутался. Ни каких Disable Capture1 нужно небыло. Вспомнил, что это протеус отказался работать на больших частотах. Вот про бесконечное прерывание мысли, и были.
По этой теме все понятно. Ассемблера мне не понять. Но практически тоже самое если задержку считать таймером с предделителем = 1. Те же тики.

+1

47

Нужно измерить количество оборотов вентилятора. Так получилось, что есть только свободный TIMER0. Вход таходатчика на PORTD.4. Таходатчик два импульса на оборот. Решил делать так.

Код:
 $regfile = "m328pdef.dat"
 $crystal = 16000000
 $baud = 4800
 $hwstack = 160
 $swstack = 160
 $framesize = 64

Config Timer0 = Timer , Prescale = 1024
On Timer0 Uphigh
Stop Timer0

 Dim Freq As Word
 Dim Freq_timer As Byte
 Dim Oboroti As Word
 Dim Oboroti_str As String * 4
 Dim Overcounter As Word 
 
 Config Pind.4 = Input
 Enable Interrupts
 Enable Timer0
'***************************************************************************
Do
  Gosub Frequensy 
    Freq = Overcounter
    Shift Freq , Left , 8
    Freq = Freq + Freq_timer   'Количество тиков таймера за четверть оборота
    Oboroti = 15625 / Freq      'Обратная величина где 15625 = 16000000 \ 1024
    Oboroti = Oboroti * 240     ' Количество целых оборотов за минуту
Loop
'*******************************************************************************
Frequensy:
  If Chim >= 50 Then      'Если вентилятор начал вращаться
    Bitwait Pind.4 , Set
    Overcounter = 0                                  
    Start Timer0
    Bitwait Pind.4 , Reset
    Stop Timer0
    Freq_timer = Tcnt0                                          '
    Tcnt0 = 0
  End If
Return
'-------------------------------------------------------------------------------
Uphigh:
  Incr Overcounter
Return

Получается не совсем удачно. Может кто нормальное решение предложит?

0

48

Это не подходит?: https://bascom.at.ua/publ/1-1-0-8

0

49

max
Хозяин статьи не измеряет полученное количество оборотов. Он индицирует заданное.
В данном вопросе, и теме. Измерение длительности, или количества импульсов с помощью таймеров.
Когда накидал схему, сделал печатку. Думал буду мерить с помощью T0(PD4) количество импульсов за промежуток времени. Оказалось частота маленькая, и нужно мерить период количеством тиков таймера. Таймер остался только TIMER0, порт привязан уже в печатке к PD4.
Вот на грабли, и наступил.

Отредактировано rom-i (2019-06-28 23:01:12)

0

50

rom-i написал(а):

Получается не совсем удачно. Может кто нормальное решение предложит?

я бы оставил как есть, только Prescale = 1 сделал и полученное значение разделил на 1024
точнее измерять будет

0

51

IDok написал(а):

от же с..ка неблагодарная...

в смысле?
Например в  пик16ф84 один таймер и там частотомер делают именно таким способом-задержка на основе подсчета тактов встроенного генератора

Отредактировано bulat943 (2019-06-29 21:23:22)

0

52

andreypav
Думал уменьшать прескаллер, но побоялся выйти за значение переменной Word.
Какие именно вентиляторы стоять будут вопрос не решенный. То, что два импульса на оборот точно. Вот с максимальной частотой неизвестно. Пока вычисляю из того, что есть. Вентили от охлаждения процев, и от видях.
В реале стоять будут на потдуве дровяного котла отопления.

0

53

Если подход бм реален возникает еще вопрос.
Как сделать выход из подпрограммы если нет импульсов на входе?
Вентилятор сдох, и больше не крутится. МК остановиться на Bitwait Pind.4 , Set , или Bitwait Pind.4 , Reset .
Будет ждать изменения уровня на входе. Такую сетуацию делал, и получал висяк. (((

0

54

rom-i написал(а):

Как сделать выход из подпрограммы если нет импульсов на входе?

Нужно делать по нормальному с выходом по таймауту.

0

55

Пётр

Нужно делать по нормальному с выходом по таймауту.

Дык первокласснику объясни как. Дай образец кода.
Как сделать таймаут?
Вообще в Баском есть команда Taimout. Пишется в самом начале подпрограммы. Уже использовал при приеме по USART. Не могу найти как это правильно писать нужно. Вроде Taimoutms *** если в ms. Но так не работает. Как правильно? Потерялась тема во времени. Мож кто знае?

Отредактировано rom-i (2019-06-30 16:00:32)

0

56

rom-i написал(а):

Дык первокласснику объясни как.

По моему все элементарно и даже первоклассник может догадаться как это сделать.
Bitwait в цикле проверяет указанный бит пока условие не совпадет. Ничего не мешает написать его аналог с выходом по таймауту.
Что-то типа.

Код:
Dim TimeOut As Dword
TimeOut = 1000000

Do
  Decr TimeOut
Loop Until Pind.4 = 0 Or TimeOut = 0

If TimeOut = 0 Then
 ' Выход по таймауту.
Else
 ' Выход по условию.
End If

Число в переменной TimeOut нужно подобрать экспериментально чтобы произошел выход из цикла если определенное время требуемый бит в 0 или в 1. Если есть свободный таймер можно его использовать.
Или сделать на задержках.

Код:
Dim TimeOut As Dword
TimeOut = 1000

Do
  Decr TimeOut
  Waitus 100
Loop Until Pind.4 = 0 Or TimeOut = 0

If TimeOut = 0 Then
 ' Выход по таймауту.
Else
 ' Выход по условию.
End If

0

57

bulat943
Вначале так, и хотел делать. По этому взял порт D4(T0). Только мерить не 1 сек, а например 100мсек. Получается точность ну очень примерная. Даже при 1 сек +-1 тик, это +-10 оборотов. Для индикации нормально. Сейчас доделываю в железе. Как эта секунда на все остальное повлияет посмотрю в реале.
По полной программе МК принимает по UART значение температуры от другого МК. По значению температыры шаговый движка откр\закр саслонку поддувала, и ШИМ на таймере1 управляет вентилятором. Обороты чисто индикация.
Единственно непонимаю почему данные по UART иногда принимаються коряво. Но это было, и без измерения оборотов. Пришлось даже контрольную сумму передавать. Терминал показывает нормальные данные на входе RX, а МК если передавать, что принял коверкает строку. Скорость уменьшил до 4800. Лучьше, но все равно проскоки бывают.

0


Вы здесь » Программирование ATMEL в BASCOM. » Таймеры, ШИМ и все про них » Как зделать более точную задержку чем Wait?