таймеры
|
|
seny | Дата: Вторник, 05.06.2012, 21:19 | Сообщение # 1 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| Доброе время суток. Организавалась такая задача необходимо передать данные с мк atmega в другое устройство с определенными интервалами времени. Т.Е. алгоритм стартовый импульс 10 ms данные 30 ms стоп 10 ms . И при этом надо соблюдать весь временной интервал. Понятно что надо по прерыванию от таймера но как? Если кто занимался этим вопросом покажите кусочек кода.
|
|
| |
exersizze | Дата: Среда, 06.06.2012, 08:36 | Сообщение # 2 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Если нужно чтобы прерывания происходили через разные промежутки времени, просто меняем в обработчике значение счетного регистра с которого начинает отсчитывать таймер.
|
|
| |
exersizze | Дата: Среда, 06.06.2012, 08:42 | Сообщение # 3 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Поясню на примере настроили прерывание через 10мс, в обработчике этого прерывания изменяем значение счетного регистра чтобы следующее прерывание пришло позже, и в следующем прерывании меняем все обратно.
|
|
| |
seny | Дата: Четверг, 07.06.2012, 21:12 | Сообщение # 4 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| Если честно то возможно это и правильно а как это сделать в барсике. Возможно есть статья по работе таймера в таком режиме. Честно говоря я так и не понял куда чего настраиваем и как в обработчике изменяем регистр.
|
|
| |
exersizze | Дата: Пятница, 08.06.2012, 11:08 | Сообщение # 5 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Оно и понятно Вот набросал пример
Code $regfile = "2313def.dat" $crystal = 8000000
Dim A As Byte
'настройка прерывания по таймеру через каждые 0,032 сек Config Timer0 = Timer , Prescale = 1024 On Timer0 Impulse:
'кладем в счетчик стартовое значение, чтобы прерывание пришло раньше (через 10мсек) 'т.е. таймер начнет считать с этого значения и переполнится раньше Timer0 = 78
Enable Interrupts Enable Timer0 Start Timer0
Do
'цикл программы
Loop
'обработка прерывания Impulse:
Incr A 'считаем какой по счету вызов обработчика
'если заход в обработчик уже третий по счету следующее прерывание снова через 10 мсек If A = 3 Then Timer0 = 78 End If
Return
End
первое прерывание наступит раньше, ваккурат через 10 мс после запуска программы. Следующее, второе по счету, наступит как и положено через 30 мс, а третье снова через 10 мс.
|
|
| |
seny | Дата: Пятница, 08.06.2012, 19:57 | Сообщение # 6 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| Спасибо за пример. Из выше прочитанного следует что: при конфигурации 16 000 000 и делителем 1024 1 мс=15,4 10 мс=154 Если я правильно считаю то чтобы сработало прерывание таймера от числа (255 - 154)=101(предположим 10 мс) поставить timer0=101 отправляем в обработчик прерываний и так всегда присваиваем значение таймера timer0=255-необходимое время. Каша в голове с этими таймерами.
А чтобы получить число (Максимум таймер может отсчитать 16 мс) 60 надо переменной A из вашего примера присвоить число 3 и timer0= 70. if a=3 then timer0=70. Во наворочил ,эти выводы и подсчеты правильны ? %) %)
Сообщение отредактировал seny - Пятница, 08.06.2012, 19:59 |
|
| |
exersizze | Дата: Суббота, 09.06.2012, 01:08 | Сообщение # 7 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| да с этими таймерами сам черт ногу сломит)) если использовать кварц на 16Мгц и делитель на 1024 то таймер Timer0 будет переполняться каждые 16мс. Слишком мало.. При техже условиях таймер Timer1 будет переполняться уже через 4 сек. слишком много... Поэтому я бы не стал использовать кварц на 16МГц.
|
|
| |
trim | Дата: Понедельник, 18.06.2012, 20:25 | Сообщение # 8 |
Группа: Проверенные
Сообщений: 105
Статус: Offline
| ребят в тему ,проблема нужно с конфигурировать один порт на постоянные прерывания а другой на их отлов как это реализовать не подскажите нужно чтоб это было независимо а то не хочет работать
|
|
| |
exersizze | Дата: Вторник, 19.06.2012, 08:30 | Сообщение # 9 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Не понял что значит на постоянные прерывания и их отлов. Тоесть один генерирует импульсы а другой их ловит?
|
|
| |
trim | Дата: Вторник, 19.06.2012, 22:24 | Сообщение # 10 |
Группа: Проверенные
Сообщений: 105
Статус: Offline
| да ,простите за неясность тут такое дело ,нужно на меге 16 с конфигурировать прерывания один порт дает зажикает ик диод и другой с приемником его ловит и вся фишка в том что чем быстрее пришел отраженный импульс тем быстрее моргает ик диод тоесть прямая зависимость от растояния все завернуто на ик дальномере ловить получается от пульта телека а вот чтоб он с ик светодиода ловил отражонный импульс невыходит вот есть еще куча вопросов но ето в другой теме
|
|
| |
exersizze | Дата: Среда, 20.06.2012, 12:05 | Сообщение # 11 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Попробуй поставить задержку в обработчике прерываний или перед тем как снова зажечь светодиод.
|
|
| |
seny | Дата: Среда, 20.06.2012, 19:17 | Сообщение # 12 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| В продолжении темы расчета таймера. Толком информации нет. Возможно кто то уже разбирался, подскажите. ЗАДАЧА. Есть attiny2313 8 мГц кварц и Timer0 делитель на 1024 1.сколько таймер переполнится раз в секунду. 2. Как считали. P/S/ T=(1/F)*n тут Т-константа, n-предделитель, F-частота работы камня . Попытался найти обоснование этой формулы но увы. то что нашел я из примеров частотомеров это 1024\8000000*256=32768 ms на имульс 1000000\32768=30,52 переполнение в секунду предделитель = 1024 8000000 - импульсов в секунду 256 счет таймера0 это все равно 0,032768 сек на один тик таймера в секунде 1000000 милисекунд из этого следует что переполнение таймера будет приблизительно 30 раз в секунду. Где подвох и как считать?
|
|
| |
exersizze | Дата: Среда, 20.06.2012, 23:36 | Сообщение # 13 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Так оно и будет - переполнится за секунду примерно 30 раз. Считается (256/8000000)*1204=0,032 время одного переполнения.
|
|
| |
seny | Дата: Четверг, 21.06.2012, 09:16 | Сообщение # 14 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| Тоесть мы потом 1/0,032 и получаем 31,25 тик в секунду это у нас single. Тогда вопрос как к переменной long +single чтоб получилось целое число секунд и десятичной долей секунд. Для чего это мне необходимо -измерять время между импульсами. В приборе импульс может приходить пару раз в секунду а может прийти 1 раз в 10 секунд.
|
|
| |
exersizze | Дата: Четверг, 21.06.2012, 09:59 | Сообщение # 15 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| если нужен результат с десятыми долями, заведи еще одну переменную типа Singlе. В которой складываешь результат single(resultat)=long+single а затем командой Fusing форматируешь как необходимо.
Code Dim A As Single Dim B As Long Dim S As Single 'результат для вывода на индикатор
B = -123 A = 0.251
S = A + B 'S = -122,749 Lcd Fusing(s , "#.##") 'S = -123,45 результат округляется
|
|
| |
seny | Дата: Пятница, 22.06.2012, 15:37 | Сообщение # 16 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| Продолжение темы таймеров. Так как эта тема для меня уж слишком запутана то прошу спецов проверить данный код. Он должен отсчитывать секунды. А доли секунд по прерыванию. И все это складывать. Затем передавать по КОМ .Т.К ком занят сделал програмный ком.
Code $regfile = "2313def.dat" $crystal = 8000000 $baud = 19200
Config Timer1 = Timer , Prescale = 64 , Capture Edge = Rising Config Portd.6 = Input 'прерывания Config Portb.2 = Output 'светодиод
Open "comb.0:9600,8,n,1" For Output As #1 Open "comb.1:9600,8,n,1" For Input As #2
'Так как предделитель 64 то 64/8000000*65535=0.52428 переполнений в секунду 'тобиш приблизительно 2 раза 2 Гц. Dim Timercounter As Word ' Dim Period As Single Dim Secund As Single Dim Flag As Bit 'T=(1/F)*n тут Т-константа, n-предделитель, F-частота работы камня 'T=(1/8000000)*64=0.000008 'каждое значение таймера1 = 0.000008 сек. Const T = 0.000008 Flag = 0 On Capture1 Zaxvat
Timercounter = 0 Flag = 0 Waitms 50 'разрешаем прерывания Enable Interrupts Enable Capture1
Set Portb.2
Do ' главный цикл программы '0.52428 время переполнения таймера If Timer1 = 65535 Then 'так как он переполняется каждые 0.52428 секунды то их и складываем Secund = Secund + 0.52428 'больше 255 думаю не понадобится If Secund > 255 Then Secund = 0 End If
If Flag = 1 Then
'секунды и то что насчитал таймер в сек. Period = Timercounter * T Secund = Period + Secund
Print #1 , "Secund :" Print #1 , Secund
Flag = 0 Secund = 0 End If Loop
'отрабатывает по прерыванию portd.6 Zaxvat: Timercounter = Timer1 ' копируем значение таймера в переменную Flag = 1 Timer1 = 0 ' обнуляем таймер Return
Сообщение отредактировал seny - Пятница, 22.06.2012, 16:09 |
|
| |
exersizze | Дата: Суббота, 23.06.2012, 09:17 | Сообщение # 17 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Таймер посчитан правильно, а вот в основном цикле лишнее условие. Перенеси прибавление 0,5 сек в обработчик прерывания таймера. Тоесть таймер переполнился - прибавили 0,5 сек - вышли и считаем дальше
|
|
| |
seny | Дата: Суббота, 23.06.2012, 10:30 | Сообщение # 18 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| Спасибо. Перенесу. После того как выложил код на форуме еще долго эксперементировал с ним. Внешний импульс по расчетам должен приходить через каждые11,25 секунды, я склонен доверять этой цифре т.к это промышленно изготовленный прибор и прибор поверен. Но почему то мой код(на самом деле данный код выложен на этом сайте,только немного пересчитанный и дополненый под мои нужды) отсчитывает всегда меньше на 11%.????????????? Попробую перенести отсчет секунд в прерывания надеюсь это исправить 11% погрешность.
|
|
| |
exersizze | Дата: Суббота, 23.06.2012, 12:02 | Сообщение # 19 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| А от чего тактируется микроконтроллер? Если от внутреннего генератора то там RC цепочка и соответственно частота не точная и может отличаться от 8МГц. Ну и учитывай то что при расчете таймера получаются не круглые цифры а с сотыми и тысячными долями. Вот погрешность и набегает.
|
|
| |
seny | Дата: Суббота, 23.06.2012, 13:34 | Сообщение # 20 |
Группа: Проверенные
Сообщений: 45
Статус: Offline
| Тактируется от внешнего кварца 8000000, фьюзы в понипрог SUT0 CKSEL0 с галочками.
Сообщение отредактировал seny - Суббота, 23.06.2012, 13:41 |
|
| |
qewin | Дата: Суббота, 05.10.2013, 02:40 | Сообщение # 21 |
Группа: Пользователи
Сообщений: 51
Статус: Offline
| Подскажите как сделать временной интервал (переменная 30 сек) после которого будет меняться порт 1-0? atmega8 кварц 16мгц.Всю голову сломал что на что делится .
Config Timer1 = Timer , Prescale = 256 (при 16мгц = 1сек.?) и что на что поделить чтобы призошла инверсия порта по заданной переменой?
Сообщение отредактировал qewin - Суббота, 05.10.2013, 02:41 |
|
| |
exersizze | Дата: Суббота, 05.10.2013, 07:42 | Сообщение # 22 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| Таймер увеличивается на каждый "тик" генератора, от нуля до 65535. И поэтому переполнение будет каждые 0,004 сек. (65535/16000000) Даже если применить делитель на 1024, получим интервал 4,19 сек.
|
|
| |
qewin | Дата: Суббота, 05.10.2013, 18:51 | Сообщение # 23 |
Группа: Пользователи
Сообщений: 51
Статус: Offline
| exersizze ни чего не пойму. Prescale 256 - делитель, делит на 256 ( 256:16 000 000 *65535 =1.04сек.).!? Есть переменная "a"=30 как сделать чтобы она приравнивалась к 30сек. которую можно бало бы управлять то есть +\- 1 Подскажи какой нибудь код или алгоритм.и где что писать в основной проге или за программой. Спасибо.
|
|
| |
exersizze | Дата: Воскресенье, 06.10.2013, 15:35 | Сообщение # 24 |
Группа: Администраторы
Сообщений: 723
Статус: Offline
| на каждое переполнение таймера увеличиваешь переменную a на 1 (incr a) а при достижении условия a=30 выполняешь свою задачу. как-то так:
Код $regfile = "m32def.dat" $crystal = 16000000
Dim A As Byte
Config Timer1 = Timer , Prescale = 1024
On Timer1 Perepolnenie:
Start Timer1 Enable Interrupts
Do
If A = 30 Then 'выполнение своей программы End If
Loop
End
Perepolnenie: 'переполнение таймера Incr A Return
|
|
| |