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

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

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

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


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


изменение частоты импульсов на AVR

Сообщений 1 страница 23 из 23

1

Доброго времени суток!
Возникла задача:
есть постоянно изменяемые прямоугольные импульсы с частотой от нуля до 1кГц
требуется произвести пересчет таким образом, чтобы выходная частота импульсов была равна 0,81 от входной частоты.
за основу взял следующий исходник:

$regfile = "2313def.dat"
$crystal = 4000000

Config Timer1 = Timer , Prescale = 64 , Capture Edge = Rising
Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5 , E = Portb.1 , Rs = Portb.0
Dim Wtime As Byte
Dim Timercounter As Single
Config Portb.7 = Output
On Capture1 Captmr

Wtime = 200
Timercounter = 0

Enable Interrupts
Enable Capture1

Do

Cls
Lcd Timercounter
Lowerline
Timercounter = Timercounter * 64
Timercounter = 1 / Timercounter
Lcd Timercounter
Waitms 100

'Idle
'Toggle Portb.7
'Pulseout Portb , 7 , 600
'Waitus Timercounter
Loop

Captmr:
  Timercounter = Capture1
  Timer1 = 0
Return

End

в протеусе подцепил LCD, частоту показывает четко
но что-то я запутался.
допустим, входная частота 100Гц,
Время между импульсами, которое захватывает таймер1  равно 622, но, учитывая, что предделитель 64,
622/64=9,71875мс - время между импульсами
теперь я создаю выходные импульсы с помошью переключения порта в противоположное состояние с помощью toggle, но, учитывая, что порт переключится на 0 одним импульсом, а на 1 - вторым, время 9,71875 делю пополам, получаю: 4,859375мс

следовательно, после toggle нужно поставить задержку в 4мс + 859мкс, я прав?
waitms 4
waitus 859

в протеусе все работает, подключив к ноге частотомер, получил 102Гц

Do
'Cls
' Lcd Timercounter
' Lowerline
' Timercounter = Timercounter * 64
' T = Timercounter \ 1000
' Timercounter = 1 / Timercounter
' Lcd Timercounter
   Waitms 4
   Waitus 859
Toggle Portb.7
'Pulseout Portb , 7 , 600
'Waitus Timercounter

Loop

пересчитать, написать формулу, откидывающую ms от us - тоже не проблема

вопрос собственно один, как мне усыпить контроллер, если импульсы резко оборвались?
ибо он продолжает выдавать с последней частотой.
если в тело основного цикла внести idle, то на это тратится время и показания плывут.

Отредактировано demonizer (2010-09-22 23:28:52)

0

2

может, по таймеру импульс выдавать? как грамотнее это реализовать?

0

3

один таймер считает частоту
другой генерирует необходимую

пришел импульс - разрешил таймер2 -считал таймер1 -  обнулил таймер1 - посчитал частоту пересчитал в число которое надо записать в таймер2 - записал
а) пришел второй импульс сделал тоже самое
б) не пришел импульс до момента переполнения таймера1 - остановил или запретил таймер2, - присвоил выходу 0 или 1 (че ттам уже хош)

0

4

не совсем пойму, ведь таймер1 и таймер2 - они оба на timer1?
т.е. нужно переключать режим работы таймера в подпрограмме обработки прерывания?

Отредактировано demonizer (2010-09-24 21:37:24)

0

5

вот конфигурация внешнего прерывания и двух таймеров, можно точно также еще таймер 0 сконфигурировать

Код:
Config Int0 = Falling : On Int0 Impuls : Enable Int0
Config Timer1 = Timer , Prescale = 32 : Enable Timer1 : On Timer1 Zamer
Config Timer2 = Timer , Prescale = 32 : Enable Timer2 : On Timer2 Pause : Enable Interrupts

Impuls:
return

Zamer:
return

Pause:
return

Я попробовал, но сразу не получилось, но моя идея была такая вот:

Код:
$regfile = "m8def.dat"                                      ' мега8
$crystal = 8000000
Ddrb = 1
Config Int0 = Falling : On Int0 Impuls : Enable Int0
Config Timer1 = Timer , Prescale = 32 : Enable Timer1 : On Timer1 Zamer
Config Timer2 = Timer , Prescale = 32 : Enable Timer2 : On Timer2 Pause : Enable Interrupts
Dim T As Integer , I As Integer , P As Bit : Set P

Do
'If P = 1 Then Bitwait Pind.2 , Set
For I = 1 To T
Waitus 1
Next
Toggle Portb.0
'Reset P
Loop


Impuls:
T = Timer2 / 2
Timer2 = 0
Return

Pause:
Set P
Return

Может тебя на мысли натолкнет

Отредактировано Pasha (2010-09-25 00:35:27)

0

6

Pasha
thanks ща попробую
Ddrb = 1 - енто что?

Отредактировано demonizer (2010-09-25 00:40:08)

0

7

только я не понял, что есть timer2?
если у mega8 два таймера 8 бит и 1 - 16 бит

приведенный код - это делитель частоты надвое?

Отредактировано demonizer (2010-09-25 00:58:45)

0

8

ну поидее 0 и 1 это 8мибитные, а 2 - 16ти
Ddrb = 1 - енто что? это = config portb.0 = output

Отредактировано Pasha (2010-09-25 01:02:14)

0

9

нижняя граница у меня - полгерца

0

10

блин, нало 8-битного таймера, нужно 2 16-битных, либо дейсвительно считать кол-во переполнений таймера

Отредактировано demonizer (2010-09-25 12:46:44)

0

11

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

один таймер считает частоту
другой генерирует необходимую
пришел импульс - разрешил таймер2 -считал таймер1 -  обнулил таймер1 - посчитал частоту пересчитал в число которое надо записать в таймер2 - записал
а) пришел второй импульс сделал тоже самое
б) не пришел импульс до момента переполнения таймера1 - остановил или запретил таймер2, - присвоил выходу 0 или 1 (че ттам уже хош)

но тольео делит пополам и все((( зато во всем диапазоне

$regfile = "m8def.dat"
$crystal = 4000000
Config Timer1 = Timer , Prescale = 64
Config Timer2 = Timer , Prescale = 64
Config Portb.7 = Output
Config Int0 = Rising
On Int0 Captmr
On Timer2 Pulse
Enable Interrupts
Enable Int0
Enable Timer2
Dim Capture As Integer
Do
Loop

Captmr:
Enable Timer2
   Capture = 65535 - Timer1
   Timer1 = 0
   Timer2 = Capture
Return

Pulse:
  Toggle Portb.7
  Disable Timer2
Return

Отредактировано demonizer (2010-09-26 13:32:37)

0

12

Mrshilov
ок, попробую

0

13

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

$regfile = "m8def.dat"
$crystal = 8000000
Config Timer1 = Timer , Prescale = 64
Config Timer2 = Timer , Prescale = 64
Config Portb.7 = Output
Config Int0 = Rising
On Int0 Captmr
On Timer2 T2
Enable Interrupts
Enable Int0
Enable Timer2
Enable Compare1a
On Compare1a Pulse
Dim Capture As Integer
Do
Loop

Captmr:
Capture = Capture + Timer2
Capture = Capture * 0.81
Compare1a = Capture
Return

T2:
   Capture = Capture + 256

Return

Pulse:
  Toggle Portb.7
  timer2=0
Return

Отредактировано demonizer (2010-09-27 09:58:23)

0

14

Работает, таймеры начинают работать с момента конфигурации. (config timer бла-бла-бла...)
спасибо, попробую. c Compare A = Toggle тоже игрался, работает синхронно с toggle bortb.7

0

15

Во, в протеусе какую-то фигню генерит)))
я меня уже моск вспух)

$regfile = "m8def.dat"
$crystal = 8000000

Config Timer1 = Timer , Prescale = 64 , Compare A = Toggle , Clear Timer = 1
Config Timer2 = Timer , Prescale = 64
Config Portb.7 = Output
Config Int0 = Rising

On Int0 Captmr
On Timer2 T2

Enable Interrupts
Enable Int0
Enable Timer1
Enable Timer2

Dim Capture As Word

Start Timer1
Start Timer2

Captmr:
   Capture = Capture + Timer2
   Stop Timer2
   Timer2 = 0
   Start Timer2
   Compare1a = Capture
Return

T2:
   Capture = Capture + 256
Return

end

0

16

Mrshilov
do
loop
-стер, сорри, невнимательность. а коэффициент пока не ставил, пробую для начала 1:1

но все равно ерунда получается

$regfile = "m8def.dat"
$crystal = 8000000

Config Timer1 = Timer , Prescale = 64 , Compare A = Toggle , Clear Timer = 1
Config Timer2 = Timer , Prescale = 64
Config Portb.7 = Output
Config Int0 = Rising

On Int0 Captmr
On Timer2 T2

Enable Interrupts
Enable Int0
Enable Timer1
Enable Timer2

Dim Capture As Word

Start Timer1
Start Timer2
Do
Loop
Captmr:
   Capture = Capture + Timer2
   Capture = Capture * 0.81
  Timer2 = 0

   Compare1a = Capture
Return

T2:
   Capture = Capture + 256
Return

End

Отредактировано demonizer (2010-09-28 12:29:45)

0

17

все хорошо, только все равно toggle генерит импульсы, если их резко оборвать.
а если при включении импульсов входных нет - генерит максимальную частоту

Отредактировано demonizer (2010-09-28 21:20:20)

0

18

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

Я за тебя практически всю программу написал, это уже не помощь, а работа

не вопрос, кинул
с твоим алгоритмом периодически пропадают выходные импульсы на 2 секунды при входной частоте > 200Гц,
а          Capture = Capture * 0.81 - округляется до целого таким образом, что          Capture = Capture
и еще вопрос, зачем проверять условие If Capture < 62500, если Stop_T1=1 только при Capture > 62500
заранее, спасибо

Отредактировано demonizer (2010-09-29 09:00:04)

0

19

1) а куда ж тут подается входная частота?
2) как это на одном таймере организован перемножитель частоты?
3) какая ж может быть постоянная задержка, если частота все время меняется?
4) если частота изменяется от нуля, то как понять, что она оборвалась?

было так:
1)- на t1 и icp
2)-таймер 1 в режиме capture считает время между двумя импульсами
3)задержка не постоянная, я написал для примера. на деле 64 делим на 4 (Мгц), и умножаем на capture1 получаем время в мкс, далее делим нацело на 1000 - записываем результат в waitms, остаток от деления записываем в waitus
4) тем же if - then проверяем capture1, если > 65500 - гасим toggle

мой вспухший моск тут остался) я с компаратором ни разу не сталкивался(

Отредактировано demonizer (2010-09-29 09:27:44)

0

20

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

не вопрос, кинул

раз кинул, то держи)

Код:
'P-a-h-a@yandex.ru
'преобразуем входную частоту и на выходе выдаем о,81 от того че на входе. Пробовал 0,1Гц ставить - нормально работает!
'Все просто. Считаем количество тактов процессора от одного внешнего прерывания до 2го
'пересчитываем сколько тактов нужно отсчитать чтоб получить заданную меньшую частоту
'и генерируем частоту другим таймеро. Если сильно долго небыло сигнала на входе - сбрасываем проц в исходное состояние

$regfile = "m8def.dat"
$crystal = 16000000                                         ' прога не привязана к єтому числу. Но как подсказывает соображалка - кварц и побольше, например 16000000
Config Portb.7 = Output : Set Portb.7
Set Portc.5 : Config Portc.5 = Output
Config Timer0 = Timer , Prescale = 1 : Enable Timer0 : On Timer0 T0:
Config Timer2 = Timer , Prescale = 1 : Enable Timer2 : On Timer2 Pulse:
Config Int0 = Falling : Enable Int0 : On Int0 Captmr :
Enable Interrupts

Dim Z As Single , T As Single , W As Single , Q As Single , Pulse_out As Single , Zapusk As Byte : W = 0
Stop Timer0
'Disable Timer2

Do
Wait 1000                                                   ' Для прикола отдыхаем)))
Loop


Pulse:                                                      ' тут отсчитываем такты до следующего переключения выхода
Incr W
T = W * 255 : T = T + Timer2
If T > Pulse_out Then : Toggle Portb.7 : W = 0 : End If
Return




T0:                                                         ' Тут просто считаем кол-во раз срабатывания таймера
Incr Q
If Q > 1000000 Then Reset Portc.5                           ' Надо подобрать значение, после чего проц будет сбрасыватся. Этот порт соединить с лапой рэсет
Return

Captmr:                                                     ' подсчитываем сколько тактов прошло с момента предыдущего импульса
Stop Timer0
Z = Q * 255 : Z = Z + Timer0
Timer0 = 0
Start Timer0
Z = Z / 2
Pulse_out = Z * 0.81
Q = 0
If Zapusk = 2 Then Enable Timer2
Incr Zapusk : If Zapusk > 3 Then Zapusk = 3

Return

storage virtualization

0

21

Pasha
спасибо, все работает, буду пробовать в железе.
пришлось сначала Pulse_out = Z *1.04, чтобы компенсировать погрешность

Mrshilov, твою прошивку тоже опробую, всем ОГРОМНОЕ спасибо за помошь!

Отредактировано demonizer (2010-09-29 16:26:31)

0

22

Mrshilov
чем точнее, тем лучше.
у меня мотоцикл изначально был с кроссовыми колесами (21 дюйм спереди). я поставил катки на 17'', естессно, спидометр врет. спидометр цифровой вот я и хочу пересчитывать импульсы, чтобы показания были точными.
на счет вычислений в прерываниях - мне тоже не совсем по душе
сейчас я уже добавил работу с еепром, генерирование звука и буззер с транзистором, написал алгоритм программирования, чтобы выбирать коэффициент в зависимости от установленных колес

0

23

Mrshilov
у меня не магнит, от колеса до приборки идет трос, в приборке стоит валкодер с оптопарой, трос приводится червяком

0


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