[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
таймеры
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
Если честно то возможно это и правильно а как это сделать в барсике. Возможно есть статья по работе таймера в таком режиме. Честно говоря я так и не понял куда чего настраиваем и как в обработчике изменяем регистр. smile

 
exersizzeДата: Пятница, 08.06.2012, 11:08 | Сообщение # 5
Группа: Администраторы
Сообщений: 723

Статус: Offline
Оно и понятно biggrin Вот набросал пример

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-необходимое время. wacko Каша в голове с этими таймерами.

А чтобы получить число (Максимум таймер может отсчитать 16 мс) 60 надо переменной A из вашего примера присвоить число 3 и timer0= 70. if a=3 then timer0=70.
Во наворочил ,эти выводы и подсчеты правильны ? wacko %) wacko %)




Сообщение отредактировал 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мгц.Всю голову сломал что на что делится  wacko .

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


 
  • Страница 1 из 1
  • 1
Поиск: