| таймеры | 
| 
				
			 | 
| 
| seny | Дата: Вторник, 05.06.2012, 21:19 | Сообщение # 1 |  |   Группа: Проверенные Сообщений: 45 
 Статус: Offline | Доброе время суток. Организавалась такая задача необходимо передать данные с мк atmega в другое устройство с определенными интервалами времени. Т.Е. алгоритм стартовый импульс 10 ms данные 30 ms стоп 10 ms . И при этом надо соблюдать весь временной интервал. Понятно что надо по прерыванию от таймера но как?
 Если кто занимался этим вопросом покажите кусочек кода.
 
 
 |  
 |  |  |  | 
| 
| exersizze | Дата: Среда, 06.06.2012, 08:36 | Сообщение # 2 |  |   Группа: Администраторы Сообщений: 720 
 Статус: Offline | Если нужно чтобы прерывания происходили через разные промежутки времени, просто меняем в обработчике значение счетного регистра с которого начинает отсчитывать таймер. 
 
 |  
 |  |  |  | 
| 
| exersizze | Дата: Среда, 06.06.2012, 08:42 | Сообщение # 3 |  |   Группа: Администраторы Сообщений: 720 
 Статус: Offline | Поясню на примере настроили прерывание через 10мс, в обработчике этого прерывания изменяем значение счетного регистра чтобы следующее прерывание пришло позже, и в следующем прерывании меняем все обратно. 
 
 |  
 |  |  |  | 
| 
| seny | Дата: Четверг, 07.06.2012, 21:12 | Сообщение # 4 |  |   Группа: Проверенные Сообщений: 45 
 Статус: Offline | Если честно то возможно это и правильно а как это сделать в барсике. Возможно есть статья по работе таймера в таком режиме. Честно говоря я так и не понял куда чего настраиваем и как в обработчике изменяем регистр.   
 
 |  
 |  |  |  | 
| 
| exersizze | Дата: Пятница, 08.06.2012, 11:08 | Сообщение # 5 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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 |  |   Группа: Администраторы Сообщений: 720 
 Статус: Offline | да с этими таймерами сам черт ногу сломит)) если использовать кварц на 16Мгц и делитель на 1024 то таймер Timer0 будет переполняться каждые 16мс. Слишком мало.. При техже условиях таймер Timer1 будет переполняться уже через 4 сек. слишком много...
 Поэтому я бы не стал использовать кварц на 16МГц.
 
 
 |  
 |  |  |  | 
| 
| trim | Дата: Понедельник, 18.06.2012, 20:25 | Сообщение # 8 |  | Группа: Проверенные Сообщений: 105 
 Статус: Offline | ребят в тему ,проблема нужно с конфигурировать один порт на постоянные прерывания а другой на их отлов как это реализовать не подскажите нужно чтоб это было независимо а то не хочет работать 
 
 |  
 |  |  |  | 
| 
| exersizze | Дата: Вторник, 19.06.2012, 08:30 | Сообщение # 9 |  |   Группа: Администраторы Сообщений: 720 
 Статус: Offline | Не понял что значит на постоянные прерывания и их отлов. Тоесть один генерирует импульсы а другой их ловит? 
 
 |  
 |  |  |  | 
| 
| trim | Дата: Вторник, 19.06.2012, 22:24 | Сообщение # 10 |  | Группа: Проверенные Сообщений: 105 
 Статус: Offline | да ,простите за неясность тут такое дело ,нужно на меге 16 с конфигурировать прерывания один порт дает зажикает ик диод и другой с приемником его ловит и вся фишка в том что чем быстрее пришел отраженный импульс тем быстрее моргает ик диод тоесть прямая зависимость от растояния все завернуто на ик дальномере ловить получается от пульта телека а вот чтоб он с ик светодиода ловил отражонный импульс невыходит вот есть еще куча вопросов но ето в другой теме 
 
 |  
 |  |  |  | 
| 
| exersizze | Дата: Среда, 20.06.2012, 12:05 | Сообщение # 11 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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 |  |   Группа: Администраторы Сообщений: 720 
 Статус: 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
 
 |  
 |  |  |  |